diff options
Diffstat (limited to 'Build/source/libs/mpfr/mpfr-src/src/rndna.c')
-rw-r--r-- | Build/source/libs/mpfr/mpfr-src/src/rndna.c | 199 |
1 files changed, 0 insertions, 199 deletions
diff --git a/Build/source/libs/mpfr/mpfr-src/src/rndna.c b/Build/source/libs/mpfr/mpfr-src/src/rndna.c deleted file mode 100644 index 23997bf0ee7..00000000000 --- a/Build/source/libs/mpfr/mpfr-src/src/rndna.c +++ /dev/null @@ -1,199 +0,0 @@ -/* mpfr_round_nearest_away -- round to nearest away - -Copyright 2012-2020 Free Software Foundation, Inc. -Contributed by the AriC and Caramba projects, INRIA. - -This file is part of the GNU MPFR Library. - -The GNU MPFR Library is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 3 of the License, or (at your -option) any later version. - -The GNU MPFR Library is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see -https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., -51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include "mpfr-impl.h" - -/* Note: this doesn't work for 2^(emin-2). Currently, the best that can be - done is to extend the exponent range internally, and do not support the - case emin = MPFR_EMIN_MIN from the caller. */ - -/* In order to work, we'll save the context within the mantissa of 'rop'. - For that, we need to do some low level stuff like for init2/clear to create - a mantissa of bigger size, which contains the extra context. - To add a new field of type T in the context, add its type in - mpfr_size_limb_extended_t (if it is not already present) - and add a new value for the enum mpfr_index_extended_t before MANTISSA. */ -typedef union { - mp_size_t si; - mp_limb_t li; - mpfr_exp_t ex; - mpfr_prec_t pr; - mpfr_sign_t sg; - mpfr_flags_t fl; - mpfr_limb_ptr pi; -} mpfr_size_limb_extended_t; -typedef enum { - ALLOC_SIZE = 0, - OLD_MANTISSA, - OLD_EXPONENT, - OLD_SIGN, - OLD_PREC, - OLD_FLAGS, - OLD_EXP_MIN, - OLD_EXP_MAX, - MANTISSA -} mpfr_index_extended_t ; - -#define MPFR_MALLOC_EXTENDED_SIZE(s) \ - (MANTISSA * sizeof(mpfr_size_limb_extended_t) + \ - MPFR_BYTES_PER_MP_LIMB * (size_t) (s)) - -/* This function is called before the applied function - and prepares rop to give it one more bit of precision - and to save its old value within it. */ -void -mpfr_round_nearest_away_begin (mpfr_t rop) -{ - mpfr_t tmp; - mp_size_t xsize; - mpfr_size_limb_extended_t *ext; - mpfr_prec_t p; - int inexact; - MPFR_SAVE_EXPO_DECL (expo); - - /* when emin is the smallest possible value, we cannot - determine the correct round-to-nearest-away rounding for - 0.25*2^emin, which gets rounded to 0 with nearest-even, - instead of 0.5^2^emin. */ - MPFR_ASSERTN(__gmpfr_emin > MPFR_EMIN_MIN); - - p = MPFR_PREC (rop) + 1; - MPFR_SAVE_EXPO_MARK (expo); - - /* We can't use mpfr_init2 since we need to store an additional context - within the mantissa. */ - MPFR_ASSERTN(p <= MPFR_PREC_MAX); - /* Allocate the context within the needed mantissa. */ - xsize = MPFR_PREC2LIMBS (p); - ext = (mpfr_size_limb_extended_t *) - mpfr_allocate_func (MPFR_MALLOC_EXTENDED_SIZE(xsize)); - - /* Save the context first. */ - ext[ALLOC_SIZE].si = xsize; - ext[OLD_MANTISSA].pi = MPFR_MANT(rop); - ext[OLD_EXPONENT].ex = MPFR_EXP(rop); - ext[OLD_SIGN].sg = MPFR_SIGN(rop); - ext[OLD_PREC].pr = MPFR_PREC(rop); - ext[OLD_FLAGS].fl = expo.saved_flags; - ext[OLD_EXP_MIN].ex = expo.saved_emin; - ext[OLD_EXP_MAX].ex = expo.saved_emax; - - /* Create tmp as a proper NAN. */ - MPFR_PREC(tmp) = p; /* Set prec */ - MPFR_SET_POS(tmp); /* Set a sign */ - MPFR_MANT(tmp) = (mp_limb_t*)(ext+MANTISSA); /* Set Mantissa ptr */ - MPFR_SET_NAN(tmp); /* initializes to NaN */ - - /* Note: This full initialization to NaN may be unnecessary because of - the mpfr_set just below, but this is cleaner in case internals would - change in the future (for instance, some fields of tmp could be read - before being set, and reading an uninitialized value is UB here). */ - - /* Copy rop into tmp now (rop may be used as input later). */ - MPFR_DBGRES (inexact = mpfr_set(tmp, rop, MPFR_RNDN)); - MPFR_ASSERTD(inexact == 0); /* Shall be exact since prec(tmp) > prec(rop) */ - - /* Overwrite rop with tmp. */ - rop[0] = tmp[0]; - - /* The new rop now contains a copy of the old rop, with one extra bit of - precision while keeping the old rop "hidden" within its mantissa. */ - - return; -} - -/* This function is called after the applied function. - rop is the one prepared in the function above, - and contains the result of the applied function. - This function restores rop like it was before the - calls to mpfr_round_nearest_away_begin while - copying it back the result of the applied function - and performing additional roundings. */ -int -mpfr_round_nearest_away_end (mpfr_t rop, int inex) -{ - mpfr_t tmp; - mp_size_t xsize; - mpfr_size_limb_extended_t *ext; - mpfr_prec_t n; - MPFR_SAVE_EXPO_DECL (expo); - - /* Get back the hidden context. - Note: The cast to void * prevents the compiler from emitting a warning - (or error), such as: - cast increases required alignment of target type - with the -Wcast-align GCC option. Correct alignment is a consequence - of the code that built rop. - */ - ext = ((mpfr_size_limb_extended_t *) (void *) MPFR_MANT(rop)) - MANTISSA; - - /* Create tmp with the result of the function. */ - tmp[0] = rop[0]; - - /* Revert rop back to what it was before calling - mpfr_round_neareset_away_begin. */ - MPFR_PREC(rop) = ext[OLD_PREC].pr; - MPFR_SIGN(rop) = ext[OLD_SIGN].sg; - MPFR_EXP(rop) = ext[OLD_EXPONENT].ex; - MPFR_MANT(rop) = ext[OLD_MANTISSA].pi; - MPFR_ASSERTD(MPFR_PREC(tmp) == MPFR_PREC(rop)+1); - - /* Restore the saved context. */ - expo.saved_flags = ext[OLD_FLAGS].fl; - expo.saved_emin = ext[OLD_EXP_MIN].ex; - expo.saved_emax = ext[OLD_EXP_MAX].ex; - xsize = ext[ALLOC_SIZE].si; - - /* Perform RNDNA. */ - n = MPFR_PREC(rop); - if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (tmp))) - mpfr_set (rop, tmp, MPFR_RNDN); /* inex unchanged */ - else - { - int lastbit, sh; - - MPFR_UNSIGNED_MINUS_MODULO(sh, n + 1); - lastbit = (MPFR_MANT(tmp)[0] >> sh) & 1; - - if (lastbit == 0) - mpfr_set (rop, tmp, MPFR_RNDN); /* exact, inex unchanged */ - else if (inex == 0) /* midpoint: round away from zero */ - inex = mpfr_set (rop, tmp, MPFR_RNDA); - else /* lastbit == 1, inex != 0: double rounding */ - inex = mpfr_set (rop, tmp, (inex > 0) ? MPFR_RNDD : MPFR_RNDU); - } - - MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags); - MPFR_SAVE_EXPO_FREE (expo); - - /* special treatment for the case rop = +/- 2^(emin-2), which should be - rounded to +/- 2^(emin-1). We do as if it was rounded to zero, thus the - mpfr_check_range() call will round it to +/- 2^(emin-1). */ - if (inex == 0 && mpfr_cmp_si_2exp (rop, (mpfr_sgn (rop) > 0) ? 1 : -1, - __gmpfr_emin - 2) == 0) - inex = -mpfr_sgn (rop); - - /* Free tmp (cannot call mpfr_clear): free the associated context. */ - mpfr_free_func(ext, MPFR_MALLOC_EXTENDED_SIZE(xsize)); - - return mpfr_check_range (rop, inex, MPFR_RNDN); -} |