1 /* mpfr_set_q -- set a floating-point number from a multiple-precision rational
3 Copyright 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 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)
31 set_z (mpfr_ptr f
, mpz_srcptr z
, mp_size_t
*zs
)
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
)
53 mpn_lshift (MPFR_MANT (f
), p
, s
, c
);
55 MPN_COPY (MPFR_MANT (f
), p
, s
);
57 MPFR_SET_SIGN (f
, mpz_sgn (z
));
63 /* set f to the rational q */
65 mpfr_set_q (mpfr_ptr f
, mpq_srcptr q
, mpfr_rnd_t rnd
)
73 MPFR_SAVE_EXPO_DECL (expo
);
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))
92 if (MPFR_UNLIKELY (mpz_sgn (den
) == 0))
95 MPFR_SET_SIGN (f
, mpz_sgn (num
));
99 MPFR_SAVE_EXPO_MARK (expo
);
101 cn
= set_z (n
, num
, &sn
);
102 cd
= set_z (d
, den
, &sd
);
105 if (MPFR_UNLIKELY (sn
> MPFR_EMAX_MAX
/ GMP_NUMB_BITS
))
107 inexact
= mpfr_overflow (f
, rnd
, MPFR_SIGN (f
));
110 if (MPFR_UNLIKELY (sn
< MPFR_EMIN_MIN
/ GMP_NUMB_BITS
-1))
112 if (rnd
== MPFR_RNDN
)
114 inexact
= mpfr_underflow (f
, rnd
, MPFR_SIGN (f
));
118 inexact
= mpfr_div (f
, n
, d
, rnd
);
119 shift
= GMP_NUMB_BITS
*sn
+cn
-cd
;
120 MPFR_ASSERTD (shift
== GMP_NUMB_BITS
*sn
+cn
-cd
);
121 cd
= mpfr_mul_2si (f
, f
, shift
, rnd
);
122 MPFR_SAVE_EXPO_FREE (expo
);
123 if (MPFR_UNLIKELY (cd
!= 0))
126 inexact
= mpfr_check_range (f
, inexact
, rnd
);