summaryrefslogtreecommitdiff
path: root/Build/source/libs/mpfr/mpfr-src/src/get_ld.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/mpfr/mpfr-src/src/get_ld.c')
-rw-r--r--Build/source/libs/mpfr/mpfr-src/src/get_ld.c104
1 files changed, 82 insertions, 22 deletions
diff --git a/Build/source/libs/mpfr/mpfr-src/src/get_ld.c b/Build/source/libs/mpfr/mpfr-src/src/get_ld.c
index d5f987ee410..6b6a5b9df6c 100644
--- a/Build/source/libs/mpfr/mpfr-src/src/get_ld.c
+++ b/Build/source/libs/mpfr/mpfr-src/src/get_ld.c
@@ -1,7 +1,7 @@
/* mpfr_get_ld, mpfr_get_ld_2exp -- convert a multiple precision floating-point
number to a machine long double
-Copyright 2002-2019 Free Software Foundation, Inc.
+Copyright 2002-2020 Free Software Foundation, Inc.
Contributed by the AriC and Caramba projects, INRIA.
This file is part of the GNU MPFR Library.
@@ -94,8 +94,73 @@ mpfr_get_ld (mpfr_srcptr x, mpfr_rnd_t rnd_mode)
ld.s.manl = tmpmant[1] >> (denorm - 32);
ld.s.manh = 0;
}
+#elif GMP_NUMB_BITS == 16
+ if (MPFR_LIKELY (denorm == 0))
+ {
+ /* manl = tmpmant[1] | tmpmant[0]
+ manh = tmpmant[3] | tmpmant[2] */
+ ld.s.manl = tmpmant[0] | ((unsigned long) tmpmant[1] << 16);
+ ld.s.manh = tmpmant[2] | ((unsigned long) tmpmant[3] << 16);
+ }
+ else if (denorm < 16)
+ {
+ /* manl = low(mant[2],denorm) | mant[1] | high(mant[0],16-denorm)
+ manh = mant[3] | high(mant[2],16-denorm) */
+ ld.s.manl = (tmpmant[0] >> denorm)
+ | ((unsigned long) tmpmant[1] << (16 - denorm))
+ | ((unsigned long) tmpmant[2] << (32 - denorm));
+ ld.s.manh = (tmpmant[2] >> denorm)
+ | ((unsigned long) tmpmant[3] << (16 - denorm));
+ }
+ else if (denorm == 16)
+ {
+ /* manl = tmpmant[2] | tmpmant[1]
+ manh = 0000000000 | tmpmant[3] */
+ ld.s.manl = tmpmant[1] | ((unsigned long) tmpmant[2] << 16);
+ ld.s.manh = tmpmant[3];
+ }
+ else if (denorm < 32)
+ {
+ /* manl = low(mant[3],denorm-16) | mant[2] | high(mant[1],32-denorm)
+ manh = high(mant[3],32-denorm) */
+ ld.s.manl = (tmpmant[1] >> (denorm - 16))
+ | ((unsigned long) tmpmant[2] << (32 - denorm))
+ | ((unsigned long) tmpmant[3] << (48 - denorm));
+ ld.s.manh = tmpmant[3] >> (denorm - 16);
+ }
+ else if (denorm == 32)
+ {
+ /* manl = tmpmant[3] | tmpmant[2]
+ manh = 0 */
+ ld.s.manl = tmpmant[2] | ((unsigned long) tmpmant[3] << 16);
+ ld.s.manh = 0;
+ }
+ else if (denorm < 48)
+ {
+ /* manl = zero(denorm-32) | tmpmant[3] | high(tmpmant[2],48-denorm)
+ manh = 0 */
+ ld.s.manl = (tmpmant[2] >> (denorm - 32))
+ | ((unsigned long) tmpmant[3] << (48 - denorm));
+ ld.s.manh = 0;
+ }
+ else /* 48 <= denorm < 64 */
+ {
+ /* we assume a right shift of 0 is identity */
+ ld.s.manl = tmpmant[3] >> (denorm - 48);
+ ld.s.manh = 0;
+ }
+#elif GMP_NUMB_BITS == 8
+ {
+ unsigned long long mant = 0;
+ int i;
+ for (i = 0; i < 8; i++)
+ mant |= ((unsigned long) tmpmant[i] << (8*i));
+ mant >>= denorm;
+ ld.s.manl = mant;
+ ld.s.manh = mant >> 32;
+ }
#else
-# error "GMP_NUMB_BITS must be 32 or >= 64"
+# error "GMP_NUMB_BITS must be 16, 32 or >= 64"
/* Other values have never been supported anyway. */
#endif
if (MPFR_LIKELY (denorm == 0))
@@ -251,28 +316,23 @@ mpfr_get_ld_2exp (long *expptr, mpfr_srcptr src, mpfr_rnd_t rnd_mode)
MPFR_ALIAS (tmp, src, MPFR_SIGN (src), 0);
ret = mpfr_get_ld (tmp, rnd_mode);
- if (MPFR_IS_PURE_FP(src))
- {
- exp = MPFR_GET_EXP (src);
+ exp = MPFR_GET_EXP (src);
- /* rounding can give 1.0, adjust back to 0.5 <= abs(ret) < 1.0 */
- if (ret == 1.0)
- {
- ret = 0.5;
- exp ++;
- }
- else if (ret == -1.0)
- {
- ret = -0.5;
- exp ++;
- }
-
- MPFR_ASSERTN ((ret >= 0.5 && ret < 1.0)
- || (ret <= -0.5 && ret > -1.0));
- MPFR_ASSERTN (exp >= LONG_MIN && exp <= LONG_MAX);
+ /* rounding can give 1.0, adjust back to 0.5 <= abs(ret) < 1.0 */
+ if (ret == 1.0)
+ {
+ ret = 0.5;
+ exp ++;
}
- else
- exp = 0;
+ else if (ret == -1.0)
+ {
+ ret = -0.5;
+ exp ++;
+ }
+
+ MPFR_ASSERTN ((ret >= 0.5 && ret < 1.0)
+ || (ret <= -0.5 && ret > -1.0));
+ MPFR_ASSERTN (exp >= LONG_MIN && exp <= LONG_MAX);
*expptr = exp;
return ret;