summaryrefslogtreecommitdiff
path: root/Build/source/libs/mpfr/mpfr-src/src/fpif.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/mpfr/mpfr-src/src/fpif.c')
-rw-r--r--Build/source/libs/mpfr/mpfr-src/src/fpif.c651
1 files changed, 651 insertions, 0 deletions
diff --git a/Build/source/libs/mpfr/mpfr-src/src/fpif.c b/Build/source/libs/mpfr/mpfr-src/src/fpif.c
new file mode 100644
index 00000000000..7dd620ba7be
--- /dev/null
+++ b/Build/source/libs/mpfr/mpfr-src/src/fpif.c
@@ -0,0 +1,651 @@
+/* mpfr_fpif -- Binary export & import of MPFR numbers
+ (floating-point interchange format)
+
+Copyright 2012-2017 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
+http://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.
+ * 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)); \
+ if ((buffer) == NULL) \
+ { \
+ *(buffer_size) = 0; \
+ return NULL; \
+ } \
+ } \
+ *(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;
+
+ 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--;
+ }
+
+ 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
+ * 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)];
+
+ if (fh == NULL)
+ return 1;
+
+ 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,
+ * buffer_size : IN/OUT : size of the buffer => size used in the buffer
+ * return 0 if successful
+ */
+static int
+mpfr_fpif_read_limbs (mpfr_t x, unsigned char *buffer, size_t *buffer_size)
+{
+ mpfr_prec_t precision;
+ size_t nb_byte;
+ size_t 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;
+
+ if ((buffer == NULL) || (*buffer_size < nb_byte))
+ {
+ *buffer_size = 0;
+ return 1;
+ }
+ *buffer_size = nb_byte;
+
+ 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));
+
+ return 0;
+}
+
+/* External Function */
+/*
+ * fh : IN : file hander
+ * 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);
+ if (buf == NULL)
+ return -1;
+
+ 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);
+ if (bufResult == NULL)
+ {
+ mpfr_free_func (buf, buf_size);
+ return -1;
+ }
+ 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 hander
+ * 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;
+ 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);
+ if (buffer == NULL)
+ {
+ mpfr_set_nan (x);
+ return -1;
+ }
+ status = fread (buffer, used_size, 1, fh);
+ if (status != 1)
+ {
+ mpfr_free_func (buffer, used_size);
+ mpfr_set_nan (x);
+ return -1;
+ }
+ status = mpfr_fpif_read_limbs (x, buffer, &used_size);
+ mpfr_free_func (buffer, used_size);
+ if (status != 0)
+ {
+ mpfr_set_nan (x);
+ return -1;
+ }
+ }
+
+ return 0;
+}