1105401Stmm/* mpfr_get_z -- get a multiple-precision integer from
2105401Stmm                 a floating-point number
3105401Stmm
4105401StmmCopyright 2004, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
5105401StmmContributed by the AriC and Caramel projects, INRIA.
6105401Stmm
7105401StmmThis file is part of the GNU MPFR Library.
8105401Stmm
9105401StmmThe GNU MPFR Library is free software; you can redistribute it and/or modify
10105401Stmmit under the terms of the GNU Lesser General Public License as published by
11105401Stmmthe Free Software Foundation; either version 3 of the License, or (at your
12105401Stmmoption) any later version.
13105401Stmm
14105401StmmThe GNU MPFR Library is distributed in the hope that it will be useful, but
15105401StmmWITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16105401Stmmor FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
17105401StmmLicense for more details.
18105401Stmm
19105401StmmYou should have received a copy of the GNU Lesser General Public License
20105401Stmmalong with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
21105401Stmmhttp://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
22105401Stmm51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
23105401Stmm
24105401Stmm#include "mpfr-impl.h"
25105401Stmm
26105401Stmmint
27105401Stmmmpfr_get_z (mpz_ptr z, mpfr_srcptr f, mpfr_rnd_t rnd)
28105401Stmm{
29129589Smarius  int inex;
30129589Smarius  mpfr_t r;
31129589Smarius  mpfr_exp_t exp;
32129589Smarius
33129589Smarius  if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (f)))
34105401Stmm    {
35105401Stmm      if (MPFR_UNLIKELY (MPFR_NOTZERO (f)))
36129589Smarius        MPFR_SET_ERANGE ();
37129589Smarius      mpz_set_ui (z, 0);
38105401Stmm      /* The ternary value is 0 even for infinity. Giving the rounding
39129589Smarius         direction in this case would not make much sense anyway, and
40105401Stmm         the direction would not necessarily match rnd. */
41105401Stmm      return 0;
42105401Stmm    }
43129589Smarius
44129589Smarius  exp = MPFR_GET_EXP (f);
45129589Smarius  /* if exp <= 0, then |f|<1, thus |o(f)|<=1 */
46129589Smarius  MPFR_ASSERTN (exp < 0 || exp <= MPFR_PREC_MAX);
47129589Smarius  mpfr_init2 (r, (exp < (mpfr_exp_t) MPFR_PREC_MIN ?
48129589Smarius                  MPFR_PREC_MIN : (mpfr_prec_t) exp));
49105401Stmm  inex = mpfr_rint (r, f, rnd);
50129589Smarius  MPFR_ASSERTN (inex != 1 && inex != -1); /* integral part of f is
51129589Smarius                                             representable in r */
52129589Smarius  MPFR_ASSERTN (MPFR_IS_FP (r));
53129589Smarius  exp = mpfr_get_z_2exp (z, r);
54129589Smarius  if (exp >= 0)
55129589Smarius    mpz_mul_2exp (z, z, exp);
56129589Smarius  else
57105401Stmm    mpz_fdiv_q_2exp (z, z, -exp);
58105401Stmm  mpfr_clear (r);
59105401Stmm
60105401Stmm  return inex;
61105401Stmm}
62105401Stmm