diff options
Diffstat (limited to 'Build/source/libs/mpfr/mpfr-src/src/fpif.c')
-rw-r--r-- | Build/source/libs/mpfr/mpfr-src/src/fpif.c | 634 |
1 files changed, 0 insertions, 634 deletions
diff --git a/Build/source/libs/mpfr/mpfr-src/src/fpif.c b/Build/source/libs/mpfr/mpfr-src/src/fpif.c deleted file mode 100644 index df775dbd7ae..00000000000 --- a/Build/source/libs/mpfr/mpfr-src/src/fpif.c +++ /dev/null @@ -1,634 +0,0 @@ -/* mpfr_fpif -- Binary export & import of MPFR numbers - (floating-point interchange format) - -Copyright 2012-2020 Free Software Foundation, Inc. -Contributed by Olivier Demengeon. - -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" - -#if !defined (HAVE_BIG_ENDIAN) && !defined (HAVE_LITTLE_ENDIAN) -#error "Endianness is unknown. Not supported yet." -#endif - -/* The format is described as follows. Any multi-byte number is encoded - in little endian. - - 1. We first store the precision p (this format is able to represent - any precision from 1 to 2^64 + 248). - Let B be the first byte (0 <= B <= 255). - * If B >= 8, the precision p is B-7. - Here, the condition is equivalent to 1 <= p <= 248. - * If B <= 7, the next B+1 bytes contain p-249. - Here, the condition is equivalent to 249 <= p <= 2^64 + 248. - We will use the following macros: - * MPFR_MAX_PRECSIZE = 7 - * MPFR_MAX_EMBEDDED_PRECISION = 255 - 7 = 248 - - 2. Then we store the sign bit and exponent related information - (possibly a special value). We first have byte A = [seeeeeee], - where s is the sign bit and E = [eeeeeee] such that: - * If 0 <= E <= 94, then the exponent e is E-47 (-47 <= e <= 47). - * If 95 <= E <= 110, the exponent is stored in the next E-94 bytes - (1 to 16 bytes) in sign + absolute value representation, - where the absolute value is increased by 47 (e <= -47 or 47 <= e). - * If 111 <= E <= 118, the exponent size S is stored in the next - E-110 bytes (1 to 8), then the exponent itself is stored in the - next S bytes. [Not implemented yet] - * If 119 <= E <= 127, we have a special value: - E = 119 (MPFR_KIND_ZERO) for a signed zero; - E = 120 (MPFR_KIND_INF) for a signed infinity; - E = 121 (MPFR_KIND_NAN) for NaN. - - 3. Then we store the significand (for regular values). - - The sign bit is preserved by the import/export functions, even for NaN. - - Note: When a size is stored, it must be minimal, i.e. a number cannot - start with a null byte. Otherwise the import may fail. -*/ - -#define MPFR_MAX_PRECSIZE 7 -#define MPFR_MAX_EMBEDDED_PRECISION (255 - MPFR_MAX_PRECSIZE) - -#define MPFR_KIND_ZERO 119 -#define MPFR_KIND_INF 120 -#define MPFR_KIND_NAN 121 -#define MPFR_MAX_EMBEDDED_EXPONENT 47 -#define MPFR_EXTERNAL_EXPONENT 94 - -/* Begin: Low level helper functions */ - -/* storage must have an unsigned type */ -#define COUNT_NB_BYTE(storage, size) \ - do \ - { \ - (storage) >>= 8; \ - (size)++; \ - } \ - while ((storage) != 0) - -#define ALLOC_RESULT(buffer, buffer_size, wanted_size) \ - do \ - { \ - if ((buffer) == NULL || *(buffer_size) < (wanted_size)) \ - { \ - (buffer) = (unsigned char *) mpfr_reallocate_func \ - ((buffer), *(buffer_size), (wanted_size)); \ - MPFR_ASSERTN((buffer) != 0); \ - } \ - *(buffer_size) = (wanted_size); \ - } \ - while (0) - -/* - * size in byte of a MPFR number in a binary object of a variable size - */ -#define MAX_VARIABLE_STORAGE(exponent_size, precision) \ - ((size_t)(((precision) >> 3) + (exponent_size) + \ - ((precision) > 248 ? sizeof(mpfr_prec_t) : 0) + 3)) - -/* copy in result[] the values in data[] with a different endianness, - where data_size might be smaller than data_max_size, so that we only - copy data_size bytes from the end of data[]. */ -static void -#if defined (HAVE_BIG_ENDIAN) -putLittleEndianData (unsigned char *result, unsigned char *data, - size_t data_max_size, size_t data_size) -#elif defined (HAVE_LITTLE_ENDIAN) -putBigEndianData (unsigned char *result, unsigned char *data, - size_t data_max_size, size_t data_size) -#endif -{ - size_t j; - - MPFR_ASSERTD (data_size <= data_max_size); - for (j = 0; j < data_size; j++) - result[j] = data[data_max_size - j - 1]; -} - -/* copy in result[] the values in data[] with the same endianness */ -static void -#if defined (HAVE_BIG_ENDIAN) -putBigEndianData (unsigned char *result, unsigned char *data, - size_t data_max_size, size_t data_size) -#elif defined (HAVE_LITTLE_ENDIAN) -putLittleEndianData (unsigned char *result, unsigned char *data, - size_t data_max_size, size_t data_size) -#endif -{ - MPFR_ASSERTD (data_size <= data_max_size); - memcpy (result, data, data_size); -} - -/* copy in result[] the values in data[] with a different endianness; - the data are written at the end of the result[] buffer (if - data_size < data_max_size, the first bytes of result[] are - left untouched). */ -static void -#if defined (HAVE_BIG_ENDIAN) -getLittleEndianData (unsigned char *result, unsigned char *data, - size_t data_max_size, size_t data_size) -#elif defined (HAVE_LITTLE_ENDIAN) -getBigEndianData (unsigned char *result, unsigned char *data, - size_t data_max_size, size_t data_size) -#endif -{ - size_t j; - - MPFR_ASSERTD (data_size <= data_max_size); - for (j = 0; j < data_size; j++) - result[data_max_size - j - 1] = data[j]; -} - -/* copy in result[] the values in data[] with the same endianness */ -static void -#if defined (HAVE_BIG_ENDIAN) -getBigEndianData (unsigned char *result, unsigned char *data, - size_t data_max_size, size_t data_size) -#elif defined (HAVE_LITTLE_ENDIAN) -getLittleEndianData (unsigned char *result, unsigned char *data, - size_t data_max_size, size_t data_size) -#endif -{ - MPFR_ASSERTD (data_size <= data_max_size); - memcpy (result, data, data_size); -} - -/* End: Low level helper functions */ - -/* Internal Function */ -/* - * buffer : OUT : store the precision in binary format, can be null - * (may be reallocated if too small) - * buffer_size : IN/OUT : size of the buffer => size used in the buffer - * precision : IN : precision to store - * return pointer to a buffer storing the precision in binary format - */ -static unsigned char * -mpfr_fpif_store_precision (unsigned char *buffer, size_t *buffer_size, - mpfr_prec_t precision) -{ - unsigned char *result; - size_t size_precision; - - MPFR_ASSERTD (precision >= 1); - size_precision = 0; - - if (precision > MPFR_MAX_EMBEDDED_PRECISION) - { - mpfr_uprec_t copy_precision; - - copy_precision = precision - (MPFR_MAX_EMBEDDED_PRECISION + 1); - COUNT_NB_BYTE(copy_precision, size_precision); - } - - result = buffer; - ALLOC_RESULT(result, buffer_size, size_precision + 1); - - if (precision > MPFR_MAX_EMBEDDED_PRECISION) - { - result[0] = size_precision - 1; - precision -= (MPFR_MAX_EMBEDDED_PRECISION + 1); - putLittleEndianData (result + 1, (unsigned char *) &precision, - sizeof(mpfr_prec_t), size_precision); - } - else - result[0] = precision + MPFR_MAX_PRECSIZE; - - return result; -} - -#define BUFFER_SIZE 8 - -/* - * fh : IN : file handler - * return the precision stored in the binary buffer, 0 in case of error - */ -static mpfr_prec_t -mpfr_fpif_read_precision_from_file (FILE *fh) -{ - mpfr_prec_t precision; - size_t precision_size; - unsigned char buffer[BUFFER_SIZE]; - - if (fh == NULL) - return 0; - - if (fread (buffer, 1, 1, fh) != 1) - return 0; - - precision_size = buffer[0]; - if (precision_size > MPFR_MAX_PRECSIZE) - return precision_size - MPFR_MAX_PRECSIZE; - - precision_size++; - MPFR_ASSERTD (precision_size <= BUFFER_SIZE); - - /* Read the precision in little-endian format. */ - if (fread (buffer, precision_size, 1, fh) != 1) - return 0; - - /* Justification of the #if below. */ - MPFR_ASSERTD (precision_size <= MPFR_MAX_PRECSIZE + 1); - -#if (MPFR_MAX_PRECSIZE + 1) * CHAR_BIT > MPFR_PREC_BITS - while (precision_size > sizeof(mpfr_prec_t)) - { - if (buffer[precision_size-1] != 0) - return 0; /* the read precision doesn't fit in a mpfr_prec_t */ - precision_size--; - } -#endif - - /* To detect bugs affecting particular platforms (thus MPFR_ASSERTN)... */ - MPFR_ASSERTN (precision_size <= sizeof(mpfr_prec_t)); - - /* Since mpfr_prec_t is signed, one also needs to check that the - most significant bit of the corresponding unsigned value is 0. */ - if (precision_size == sizeof(mpfr_prec_t) && - buffer[precision_size-1] >= 0x80) - return 0; /* the read precision doesn't fit in a mpfr_prec_t */ - - precision = 0; /* to pad with 0's if data_size < data_max_size */ - - /* On big-endian machines, the data must be copied at the end of the - precision object in the memory; thus data_max_size (3rd argument) - must be sizeof(mpfr_prec_t). */ - getLittleEndianData ((unsigned char *) &precision, buffer, - sizeof(mpfr_prec_t), precision_size); - - return precision + (MPFR_MAX_EMBEDDED_PRECISION + 1); -} - -/* - * buffer : OUT : store the kind of the MPFR number x, its sign, the size of - * its exponent and its exponent value in a binary format, - * can be null (may be reallocated if too small) - * buffer_size : IN/OUT : size of the buffer => size used in the buffer - * x : IN : MPFR number - * return pointer to a buffer storing the kind of the MPFR number x, its sign, - * the size of its exponent and its exponent value in a binary format, - */ -/* TODO - * Exponents that use more than 16 bytes are not managed (not an issue - * until one has integer types larger than 128 bits). - */ -static unsigned char* -mpfr_fpif_store_exponent (unsigned char *buffer, size_t *buffer_size, mpfr_t x) -{ - unsigned char *result; - mpfr_uexp_t uexp; - size_t exponent_size; - - exponent_size = 0; - - if (MPFR_IS_PURE_FP (x)) - { - mpfr_exp_t exponent = MPFR_GET_EXP (x); - - if (exponent > MPFR_MAX_EMBEDDED_EXPONENT || - exponent < -MPFR_MAX_EMBEDDED_EXPONENT) - { - mpfr_uexp_t copy_exponent, exp_sign_bit; - - uexp = SAFE_ABS (mpfr_uexp_t, exponent) - - MPFR_MAX_EMBEDDED_EXPONENT; - - /* Shift uexp to take the sign bit of the exponent into account. - Because of constraints on the valid exponents, this cannot - overflow (check with an MPFR_ASSERTD). */ - copy_exponent = uexp << 1; - MPFR_ASSERTD (copy_exponent > uexp); - COUNT_NB_BYTE(copy_exponent, exponent_size); - MPFR_ASSERTN (exponent_size <= 16); /* see TODO */ - - /* Sign bit of the exponent. */ - exp_sign_bit = (mpfr_uexp_t) 1 << (8 * exponent_size - 1); - MPFR_ASSERTD (uexp < exp_sign_bit); - if (exponent < 0) - uexp |= exp_sign_bit; - } - else - uexp = exponent + MPFR_MAX_EMBEDDED_EXPONENT; - } - - result = buffer; - ALLOC_RESULT(result, buffer_size, exponent_size + 1); - - if (MPFR_IS_PURE_FP (x)) - { - if (exponent_size == 0) - result[0] = uexp; - else - { - result[0] = MPFR_EXTERNAL_EXPONENT + exponent_size; - - putLittleEndianData (result + 1, (unsigned char *) &uexp, - sizeof(mpfr_exp_t), exponent_size); - } - } - else if (MPFR_IS_ZERO (x)) - result[0] = MPFR_KIND_ZERO; - else if (MPFR_IS_INF (x)) - result[0] = MPFR_KIND_INF; - else - { - MPFR_ASSERTD (MPFR_IS_NAN (x)); - result[0] = MPFR_KIND_NAN; - } - - /* Set the sign, even for NaN. */ - if (MPFR_IS_NEG (x)) - result[0] |= 0x80; - - return result; -} - -/* - * x : OUT : MPFR number extracted from the binary buffer - * fh : IN : file handler (should not be NULL) - * return 0 if successful - */ -/* TODO - * Exponents that use more than 16 bytes are not managed (this is not - * an issue if the data were written by MPFR with mpfr_exp_t not larger - * than 128 bits). - */ -static int -mpfr_fpif_read_exponent_from_file (mpfr_t x, FILE * fh) -{ - mpfr_exp_t exponent; - mpfr_uexp_t uexp; - size_t exponent_size; - int sign; - unsigned char buffer[sizeof(mpfr_exp_t)]; - - MPFR_ASSERTD(fh != NULL); - - if (fread (buffer, 1, 1, fh) != 1) - return 1; - - /* sign value that can be used with MPFR_SET_SIGN, - mpfr_set_zero and mpfr_set_inf */ - sign = (buffer[0] & 0x80) ? MPFR_SIGN_NEG : MPFR_SIGN_POS; - /* Set the sign, even for NaN. */ - MPFR_SET_SIGN (x, sign); - - exponent = buffer[0] & 0x7F; - exponent_size = 1; - - if (exponent > MPFR_EXTERNAL_EXPONENT && exponent < MPFR_KIND_ZERO) - { - mpfr_uexp_t exp_sign_bit; - - exponent_size = exponent - MPFR_EXTERNAL_EXPONENT; - - /* A failure is acceptable when the exponent starts with leading zeros, - even if it would fit in mpfr_exp_t (see format description). */ - if (MPFR_UNLIKELY (exponent_size > 16 /* see TODO */ || - exponent_size > sizeof(mpfr_exp_t))) - return 1; - - if (MPFR_UNLIKELY (fread (buffer, exponent_size, 1, fh) != 1)) - return 1; - - uexp = 0; - getLittleEndianData ((unsigned char *) &uexp, buffer, - sizeof(mpfr_exp_t), exponent_size); - - /* Sign bit of the exponent. */ - exp_sign_bit = uexp & ((mpfr_uexp_t) 1 << (8 * exponent_size - 1)); - - uexp &= ~exp_sign_bit; - uexp += MPFR_MAX_EMBEDDED_EXPONENT; - if (MPFR_UNLIKELY (uexp > MPFR_EMAX_MAX && uexp > -MPFR_EMIN_MIN)) - return 1; - - exponent = exp_sign_bit ? - (mpfr_exp_t) uexp : (mpfr_exp_t) uexp; - if (MPFR_UNLIKELY (! MPFR_EXP_IN_RANGE (exponent))) - return 1; - MPFR_SET_EXP (x, exponent); - - exponent_size++; - } - else if (exponent == MPFR_KIND_ZERO) - MPFR_SET_ZERO (x); - else if (exponent == MPFR_KIND_INF) - MPFR_SET_INF (x); - else if (exponent == MPFR_KIND_NAN) - MPFR_SET_NAN (x); - else if (exponent <= MPFR_EXTERNAL_EXPONENT) - { - exponent -= MPFR_MAX_EMBEDDED_EXPONENT; - if (MPFR_UNLIKELY (! MPFR_EXP_IN_RANGE (exponent))) - return 1; - MPFR_SET_EXP (x, exponent); - } - else - return 1; - - return 0; -} - -/* - * buffer : OUT : store the limb of the MPFR number x in a binary format, - * can be null (may be reallocated if too small) - * buffer_size : IN/OUT : size of the buffer => size used in the buffer - * x : IN : MPFR number - * return pointer to a buffer storing the limb of the MPFR number x in a binary - * format - */ -static unsigned char* -mpfr_fpif_store_limbs (unsigned char *buffer, size_t *buffer_size, mpfr_t x) -{ - unsigned char *result; - mpfr_prec_t precision; - size_t nb_byte; - size_t nb_limb, mp_bytes_per_limb; - size_t nb_partial_byte; - size_t i, j; - - precision = mpfr_get_prec (x); - nb_byte = (precision + 7) >> 3; - mp_bytes_per_limb = mp_bits_per_limb >> 3; - nb_partial_byte = nb_byte % mp_bytes_per_limb; - nb_limb = (nb_byte + mp_bytes_per_limb - 1) / mp_bytes_per_limb; - - result = buffer; - ALLOC_RESULT(result, buffer_size, nb_byte); - - putBigEndianData (result, (unsigned char*) MPFR_MANT(x), - sizeof(mp_limb_t), nb_partial_byte); - for (i = nb_partial_byte, j = (nb_partial_byte == 0) ? 0 : 1; j < nb_limb; - i += mp_bytes_per_limb, j++) - putLittleEndianData (result + i, (unsigned char*) (MPFR_MANT(x) + j), - sizeof(mp_limb_t), sizeof(mp_limb_t)); - - return result; -} - -/* - * x : OUT : MPFR number extracted from the binary buffer, should have the same - * precision than the number in the binary format - * buffer : IN : limb of the MPFR number x in a binary format - * nb_byte : IN : size of the buffer (in bytes) - * Assume buffer is not NULL. - */ -static void -mpfr_fpif_read_limbs (mpfr_t x, unsigned char *buffer, size_t nb_byte) -{ - size_t mp_bytes_per_limb; - size_t nb_partial_byte; - size_t i, j; - - MPFR_ASSERTD (buffer != NULL); - - mp_bytes_per_limb = mp_bits_per_limb >> 3; - nb_partial_byte = nb_byte % mp_bytes_per_limb; - - if (nb_partial_byte > 0) - { - memset (MPFR_MANT(x), 0, sizeof(mp_limb_t)); - getBigEndianData ((unsigned char*) MPFR_MANT(x), buffer, - sizeof(mp_limb_t), nb_partial_byte); - } - for (i = nb_partial_byte, j = (nb_partial_byte == 0) ? 0 : 1; i < nb_byte; - i += mp_bytes_per_limb, j++) - getLittleEndianData ((unsigned char*) (MPFR_MANT(x) + j), buffer + i, - sizeof(mp_limb_t), sizeof(mp_limb_t)); -} - -/* External Function */ -/* - * fh : IN : file handler - * x : IN : MPFR number to put in the file - * return 0 if successful - */ -int -mpfr_fpif_export (FILE *fh, mpfr_t x) -{ - int status; - unsigned char *buf; - unsigned char *bufResult; - size_t used_size, buf_size; - - if (fh == NULL) - return -1; - - buf_size = MAX_VARIABLE_STORAGE(sizeof(mpfr_exp_t), mpfr_get_prec (x)); - buf = (unsigned char*) mpfr_allocate_func (buf_size); - MPFR_ASSERTN(buf != NULL); - - used_size = buf_size; - buf = mpfr_fpif_store_precision (buf, &used_size, mpfr_get_prec (x)); - used_size > buf_size ? buf_size = used_size : 0; - status = fwrite (buf, used_size, 1, fh); - if (status != 1) - { - mpfr_free_func (buf, buf_size); - return -1; - } - used_size = buf_size; - bufResult = mpfr_fpif_store_exponent (buf, &used_size, x); - /* bufResult cannot be NULL: if reallocation failed in - mpfr_fpif_store_exponent, an assertion failed */ - buf = bufResult; - used_size > buf_size ? buf_size = used_size : 0; - status = fwrite (buf, used_size, 1, fh); - if (status != 1) - { - mpfr_free_func (buf, buf_size); - return -1; - } - - if (mpfr_regular_p (x)) - { - used_size = buf_size; - buf = mpfr_fpif_store_limbs (buf, &used_size, x); - used_size > buf_size ? buf_size = used_size : 0; - status = fwrite (buf, used_size, 1, fh); - if (status != 1) - { - mpfr_free_func (buf, buf_size); - return -1; - } - } - - mpfr_free_func (buf, buf_size); - return 0; -} - -/* - * x : IN/OUT : MPFR number extracted from the file, its precision is reset to - * be able to hold the number - * fh : IN : file handler - * Return 0 if the import was successful. - */ -int -mpfr_fpif_import (mpfr_t x, FILE *fh) -{ - int status; - mpfr_prec_t precision; - unsigned char *buffer; - size_t used_size; - - precision = mpfr_fpif_read_precision_from_file (fh); - if (precision == 0) /* precision = 0 means an error */ - return -1; - MPFR_ASSERTD(fh != NULL); /* checked by mpfr_fpif_read_precision_from_file */ - if (precision > MPFR_PREC_MAX) - return -1; - MPFR_STAT_STATIC_ASSERT (MPFR_PREC_MIN == 1); /* as specified */ - mpfr_set_prec (x, precision); - - status = mpfr_fpif_read_exponent_from_file (x, fh); - if (status != 0) - { - mpfr_set_nan (x); - return -1; - } - - /* Warning! The significand of x is not set yet. Thus use MPFR_IS_SINGULAR - for the test. */ - if (!MPFR_IS_SINGULAR (x)) - { - /* For portability, we need to consider bytes with only 8 significant - bits in the interchange format. That's OK because CHAR_BIT >= 8. - But the implementation is currently not clear when CHAR_BIT > 8. - This may have never been tested. For safety, require CHAR_BIT == 8, - and test/adapt the code if this ever fails. */ - MPFR_STAT_STATIC_ASSERT (CHAR_BIT == 8); - MPFR_STAT_STATIC_ASSERT ((MPFR_PREC_MAX + 7) >> 3 <= (size_t) -1); - used_size = (precision + 7) >> 3; /* ceil(precision/8) */ - buffer = (unsigned char*) mpfr_allocate_func (used_size); - MPFR_ASSERTN(buffer != NULL); - status = fread (buffer, used_size, 1, fh); - if (status != 1) - { - mpfr_free_func (buffer, used_size); - mpfr_set_nan (x); - return -1; - } - mpfr_fpif_read_limbs (x, buffer, used_size); - mpfr_free_func (buffer, used_size); - } - - return 0; -} |