beta-0.89.2
[luatex.git] / source / libs / mpfr / mpfr-3.1.3 / src / set_q.c
blobaa16a81b44a1ed0bac4dce0fb66bc76b021f1e14
1 /* mpfr_set_q -- set a floating-point number from a multiple-precision rational
3 Copyright 2000-2002, 2004-2015 Free Software Foundation, Inc.
4 Contributed by the AriC and Caramel projects, INRIA.
6 This file is part of the GNU MPFR Library.
8 The GNU MPFR Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
13 The GNU MPFR Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see
20 http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
23 #define MPFR_NEED_LONGLONG_H
24 #include "mpfr-impl.h"
27 * Set f to z, choosing the smallest precision for f
28 * so that z = f*(2^BPML)*zs*2^(RetVal)
30 static int
31 set_z (mpfr_ptr f, mpz_srcptr z, mp_size_t *zs)
33 mp_limb_t *p;
34 mp_size_t s;
35 int c;
36 mpfr_prec_t pf;
38 MPFR_ASSERTD (mpz_sgn (z) != 0);
40 /* Remove useless ending 0 */
41 for (p = PTR (z), s = *zs = ABS (SIZ (z)) ; *p == 0; p++, s--)
42 MPFR_ASSERTD (s >= 0);
44 /* Get working precision */
45 count_leading_zeros (c, p[s-1]);
46 pf = s * GMP_NUMB_BITS - c;
47 if (pf < MPFR_PREC_MIN)
48 pf = MPFR_PREC_MIN;
49 mpfr_init2 (f, pf);
51 /* Copy Mantissa */
52 if (MPFR_LIKELY (c))
53 mpn_lshift (MPFR_MANT (f), p, s, c);
54 else
55 MPN_COPY (MPFR_MANT (f), p, s);
57 MPFR_SET_SIGN (f, mpz_sgn (z));
58 MPFR_SET_EXP (f, 0);
60 return -c;
63 /* set f to the rational q */
64 int
65 mpfr_set_q (mpfr_ptr f, mpq_srcptr q, mpfr_rnd_t rnd)
67 mpz_srcptr num, den;
68 mpfr_t n, d;
69 int inexact;
70 int cn, cd;
71 long shift;
72 mp_size_t sn, sd;
73 MPFR_SAVE_EXPO_DECL (expo);
75 num = mpq_numref (q);
76 den = mpq_denref (q);
77 /* NAN and INF for mpq are not really documented, but could be found */
78 if (MPFR_UNLIKELY (mpz_sgn (num) == 0))
80 if (MPFR_UNLIKELY (mpz_sgn (den) == 0))
82 MPFR_SET_NAN (f);
83 MPFR_RET_NAN;
85 else
87 MPFR_SET_ZERO (f);
88 MPFR_SET_POS (f);
89 MPFR_RET (0);
92 if (MPFR_UNLIKELY (mpz_sgn (den) == 0))
94 MPFR_SET_INF (f);
95 MPFR_SET_SIGN (f, mpz_sgn (num));
96 MPFR_RET (0);
99 MPFR_SAVE_EXPO_MARK (expo);
101 cn = set_z (n, num, &sn);
102 cd = set_z (d, den, &sd);
104 sn -= sd;
105 if (MPFR_UNLIKELY (sn > MPFR_EMAX_MAX / GMP_NUMB_BITS))
107 MPFR_SAVE_EXPO_FREE (expo);
108 inexact = mpfr_overflow (f, rnd, MPFR_SIGN (f));
109 goto end;
111 if (MPFR_UNLIKELY (sn < MPFR_EMIN_MIN / GMP_NUMB_BITS -1))
113 MPFR_SAVE_EXPO_FREE (expo);
114 if (rnd == MPFR_RNDN)
115 rnd = MPFR_RNDZ;
116 inexact = mpfr_underflow (f, rnd, MPFR_SIGN (f));
117 goto end;
120 inexact = mpfr_div (f, n, d, rnd);
121 shift = GMP_NUMB_BITS*sn+cn-cd;
122 MPFR_ASSERTD (shift == GMP_NUMB_BITS*sn+cn-cd);
123 cd = mpfr_mul_2si (f, f, shift, rnd);
124 MPFR_SAVE_EXPO_FREE (expo);
125 if (MPFR_UNLIKELY (cd != 0))
126 inexact = cd;
127 else
128 inexact = mpfr_check_range (f, inexact, rnd);
129 end:
130 mpfr_clear (d);
131 mpfr_clear (n);
132 MPFR_RET (inexact);