diff options
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.c | 117 |
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; } } |