summaryrefslogtreecommitdiff
path: root/Build/source/libs/mpfr/mpfr-src/src/round_raw_generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/mpfr/mpfr-src/src/round_raw_generic.c')
-rw-r--r--Build/source/libs/mpfr/mpfr-src/src/round_raw_generic.c117
1 files changed, 62 insertions, 55 deletions
diff --git a/Build/source/libs/mpfr/mpfr-src/src/round_raw_generic.c b/Build/source/libs/mpfr/mpfr-src/src/round_raw_generic.c
index f78b254e21c..66dc9ed4f8f 100644
--- a/Build/source/libs/mpfr/mpfr-src/src/round_raw_generic.c
+++ b/Build/source/libs/mpfr/mpfr-src/src/round_raw_generic.c
@@ -48,6 +48,10 @@ http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
* to 1. In this case, the even rounding is done away from 0, which is
* a natural generalization. Indeed, a number with 1-bit precision can
* be seen as a subnormal number with more precision.
+ *
+ * MPFR_RNDNA is now supported, but needs to be tested [TODO] and is
+ * still not part of the API. In particular, the MPFR_RNDNA value (-1)
+ * may change in the future without notice.
*/
int
@@ -64,7 +68,7 @@ mpfr_round_raw_generic(
{
mp_size_t xsize, nw;
mp_limb_t himask, lomask, sb;
- int rw;
+ int rw, new_use_inexp;
#if flag == 0
int carry;
#endif
@@ -76,9 +80,22 @@ mpfr_round_raw_generic(
MPFR_ASSERTD(inexp != ((int*) 0));
MPFR_ASSERTD(neg == 0 || neg == 1);
- if (flag && !use_inexp &&
- (xprec <= yprec || MPFR_IS_LIKE_RNDZ (rnd_mode, neg)))
- return 0;
+ if (rnd_mode == MPFR_RNDF)
+ {
+ if (use_inexp)
+ *inexp = 0; /* make sure it has a valid value */
+ if (flag)
+ return 0;
+ rnd_mode = MPFR_RNDZ; /* faster */
+ new_use_inexp = 0;
+ }
+ else
+ {
+ if (flag && !use_inexp &&
+ (xprec <= yprec || MPFR_IS_LIKE_RNDZ (rnd_mode, neg)))
+ return 0;
+ new_use_inexp = use_inexp;
+ }
xsize = MPFR_PREC2LIMBS (xprec);
nw = yprec / GMP_NUMB_BITS;
@@ -86,7 +103,7 @@ mpfr_round_raw_generic(
if (MPFR_UNLIKELY(xprec <= yprec))
{ /* No rounding is necessary. */
- /* if yp=xp, maybe an overlap: MPN_COPY_DECR is ok when src <= dst */
+ /* if yp=xp, maybe an overlap: mpn_copyd is OK when src <= dst */
if (MPFR_LIKELY(rw))
nw++;
MPFR_ASSERTD(nw >= 1);
@@ -94,13 +111,13 @@ mpfr_round_raw_generic(
if (use_inexp)
*inexp = 0;
#if flag == 0
- MPN_COPY_DECR(yp + (nw - xsize), xp, xsize);
+ mpn_copyd (yp + (nw - xsize), xp, xsize);
MPN_ZERO(yp, nw - xsize);
#endif
return 0;
}
- if (use_inexp || !MPFR_IS_LIKE_RNDZ(rnd_mode, neg))
+ if (new_use_inexp || !MPFR_IS_LIKE_RNDZ(rnd_mode, neg))
{
mp_size_t k = xsize - nw - 1;
@@ -112,26 +129,25 @@ mpfr_round_raw_generic(
}
else
{
- lomask = ~(mp_limb_t) 0;
- himask = ~(mp_limb_t) 0;
+ lomask = MPFR_LIMB_MAX;
+ himask = MPFR_LIMB_MAX;
}
MPFR_ASSERTD(k >= 0);
sb = xp[k] & lomask; /* First non-significant bits */
- /* Rounding to nearest ? */
- if (MPFR_LIKELY( rnd_mode == MPFR_RNDN) )
+ /* Rounding to nearest? */
+ if (rnd_mode == MPFR_RNDN || rnd_mode == MPFR_RNDNA)
{
/* Rounding to nearest */
mp_limb_t rbmask = MPFR_LIMB_ONE << (GMP_NUMB_BITS - 1 - rw);
- if (sb & rbmask) /* rounding bit */
- sb &= ~rbmask; /* it is 1, clear it */
- else
- {
- /* Rounding bit is 0, behave like rounding to 0 */
- goto rnd_RNDZ;
- }
+
+ if ((sb & rbmask) == 0) /* rounding bit = 0 ? */
+ goto rnd_RNDZ; /* yes, behave like rounding toward zero */
+ /* Rounding to nearest with rounding bit = 1 */
+ if (MPFR_UNLIKELY (rnd_mode == MPFR_RNDNA))
+ goto away_addone_ulp; /* like rounding away from zero */
+ sb &= ~rbmask; /* first bits after the rounding bit */
while (MPFR_UNLIKELY(sb == 0) && k > 0)
sb = xp[--k];
- /* rounding to nearest, with rounding bit = 1 */
if (MPFR_UNLIKELY(sb == 0)) /* Even rounding. */
{
/* sb == 0 && rnd_mode == MPFR_RNDN */
@@ -140,34 +156,32 @@ mpfr_round_raw_generic(
{
if (use_inexp)
*inexp = 2*MPFR_EVEN_INEX*neg-MPFR_EVEN_INEX;
- /* ((neg!=0)^(sb!=0)) ? MPFR_EVEN_INEX : -MPFR_EVEN_INEX;*/
- /* Since neg = 0 or 1 and sb=0*/
-#if flag == 1
- return 0 /*sb != 0 && rnd_mode != MPFR_RNDZ */;
-#else
- MPN_COPY_INCR(yp, xp + xsize - nw, nw);
+ /* ((neg!=0)^(sb!=0)) ? MPFR_EVEN_INEX : -MPFR_EVEN_INEX */
+ /* since neg = 0 or 1 and sb = 0 */
+#if flag == 0
+ mpn_copyi (yp, xp + xsize - nw, nw);
yp[0] &= himask;
- return 0;
#endif
+ return 0; /* sb != 0 && rnd_mode != MPFR_RNDZ */
}
else
{
+ away_addone_ulp:
/* sb != 0 && rnd_mode == MPFR_RNDN */
if (use_inexp)
*inexp = MPFR_EVEN_INEX-2*MPFR_EVEN_INEX*neg;
- /*((neg!=0)^(sb!=0))? MPFR_EVEN_INEX : -MPFR_EVEN_INEX; */
- /*Since neg= 0 or 1 and sb != 0 */
+ /* ((neg!=0)^(sb!=0)) ? MPFR_EVEN_INEX : -MPFR_EVEN_INEX */
+ /* since neg = 0 or 1 and sb != 0 */
goto rnd_RNDN_add_one_ulp;
}
}
- else /* sb != 0 && rnd_mode == MPFR_RNDN*/
+ else /* sb != 0 && rnd_mode == MPFR_RNDN */
{
if (use_inexp)
- /* *inexp = (neg == 0) ? 1 : -1; but since neg = 0 or 1 */
- *inexp = 1-2*neg;
+ *inexp = 1-2*neg; /* neg == 0 ? 1 : -1 */
rnd_RNDN_add_one_ulp:
#if flag == 1
- return 1; /*sb != 0 && rnd_mode != MPFR_RNDZ;*/
+ return 1; /* sb != 0 && rnd_mode != MPFR_RNDZ */
#else
carry = mpn_add_1 (yp, xp + xsize - nw, nw,
rw ?
@@ -178,7 +192,7 @@ mpfr_round_raw_generic(
#endif
}
}
- /* Rounding to Zero ? */
+ /* Rounding toward zero? */
else if (MPFR_IS_LIKE_RNDZ(rnd_mode, neg))
{
/* rnd_mode == MPFR_RNDZ */
@@ -187,41 +201,36 @@ mpfr_round_raw_generic(
sb = xp[--k];
if (use_inexp)
/* rnd_mode == MPFR_RNDZ and neg = 0 or 1 */
- /* (neg != 0) ^ (rnd_mode != MPFR_RNDZ)) ? 1 : -1);*/
+ /* ((neg != 0) ^ (rnd_mode != MPFR_RNDZ)) ? 1 : -1 */
*inexp = MPFR_UNLIKELY(sb == 0) ? 0 : (2*neg-1);
-#if flag == 1
- return 0; /*sb != 0 && rnd_mode != MPFR_RNDZ;*/
-#else
- MPN_COPY_INCR(yp, xp + xsize - nw, nw);
+#if flag == 0
+ mpn_copyi (yp, xp + xsize - nw, nw);
yp[0] &= himask;
- return 0;
#endif
+ return 0; /* sb != 0 && rnd_mode != MPFR_RNDZ */
}
else
{
- /* rnd_mode = Away */
+ /* Rounding away from zero */
while (MPFR_UNLIKELY(sb == 0) && k > 0)
sb = xp[--k];
if (MPFR_UNLIKELY(sb == 0))
{
/* sb = 0 && rnd_mode != MPFR_RNDZ */
if (use_inexp)
- /* (neg != 0) ^ (rnd_mode != MPFR_RNDZ)) ? 1 : -1);*/
+ /* ((neg != 0) ^ (rnd_mode != MPFR_RNDZ)) ? 1 : -1 */
*inexp = 0;
-#if flag == 1
- return 0;
-#else
- MPN_COPY_INCR(yp, xp + xsize - nw, nw);
+#if flag == 0
+ mpn_copyi (yp, xp + xsize - nw, nw);
yp[0] &= himask;
- return 0;
#endif
+ return 0;
}
else
{
/* sb != 0 && rnd_mode != MPFR_RNDZ */
if (use_inexp)
- /* (neg != 0) ^ (rnd_mode != MPFR_RNDZ)) ? 1 : -1);*/
- *inexp = 1-2*neg;
+ *inexp = 1-2*neg; /* neg == 0 ? 1 : -1 */
#if flag == 1
return 1;
#else
@@ -236,21 +245,19 @@ mpfr_round_raw_generic(
}
else
{
- /* Roundind mode = Zero / No inexact flag */
-#if flag == 1
- return 0 /*sb != 0 && rnd_mode != MPFR_RNDZ*/;
-#else
+ /* Rounding toward zero / no inexact flag */
+#if flag == 0
if (MPFR_LIKELY(rw))
{
nw++;
himask = ~MPFR_LIMB_MASK (GMP_NUMB_BITS - rw);
}
else
- himask = ~(mp_limb_t) 0;
- MPN_COPY_INCR(yp, xp + xsize - nw, nw);
+ himask = MPFR_LIMB_MAX;
+ mpn_copyi (yp, xp + xsize - nw, nw);
yp[0] &= himask;
- return 0;
#endif
+ return 0;
}
}