1/* mpfr_modf -- Integral and fractional part. 2 3Copyright 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. 4Contributed by the AriC and Caramel projects, INRIA. 5 6This file is part of the GNU MPFR Library. 7 8The GNU MPFR Library is free software; you can redistribute it and/or modify 9it under the terms of the GNU Lesser General Public License as published by 10the Free Software Foundation; either version 3 of the License, or (at your 11option) any later version. 12 13The GNU MPFR Library is distributed in the hope that it will be useful, but 14WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16License for more details. 17 18You should have received a copy of the GNU Lesser General Public License 19along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see 20http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., 2151 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ 22 23#include "mpfr-impl.h" 24 25#define INEXPOS(y) ((y) == 0 ? 0 : (((y) > 0) ? 1 : 2)) 26#define INEX(y,z) (INEXPOS(y) | (INEXPOS(z) << 2)) 27 28/* Set iop to the integral part of op and fop to its fractional part */ 29int 30mpfr_modf (mpfr_ptr iop, mpfr_ptr fop, mpfr_srcptr op, mpfr_rnd_t rnd_mode) 31{ 32 mpfr_exp_t ope; 33 mpfr_prec_t opq; 34 int inexi, inexf; 35 36 MPFR_LOG_FUNC 37 (("op[%Pu]=%.*Rg rnd=%d", 38 mpfr_get_prec (op), mpfr_log_prec, op, rnd_mode), 39 ("iop[%Pu]=%.*Rg fop[%Pu]=%.*Rg", 40 mpfr_get_prec (iop), mpfr_log_prec, iop, 41 mpfr_get_prec (fop), mpfr_log_prec, fop)); 42 43 MPFR_ASSERTN (iop != fop); 44 45 if ( MPFR_UNLIKELY (MPFR_IS_SINGULAR (op)) ) 46 { 47 if (MPFR_IS_NAN (op)) 48 { 49 MPFR_SET_NAN (iop); 50 MPFR_SET_NAN (fop); 51 MPFR_RET_NAN; 52 } 53 MPFR_SET_SAME_SIGN (iop, op); 54 MPFR_SET_SAME_SIGN (fop, op); 55 if (MPFR_IS_INF (op)) 56 { 57 MPFR_SET_INF (iop); 58 MPFR_SET_ZERO (fop); 59 MPFR_RET (0); 60 } 61 else /* op is zero */ 62 { 63 MPFR_ASSERTD (MPFR_IS_ZERO (op)); 64 MPFR_SET_ZERO (iop); 65 MPFR_SET_ZERO (fop); 66 MPFR_RET (0); 67 } 68 } 69 70 ope = MPFR_GET_EXP (op); 71 opq = MPFR_PREC (op); 72 73 if (ope <= 0) /* 0 < |op| < 1 */ 74 { 75 inexf = (fop != op) ? mpfr_set (fop, op, rnd_mode) : 0; 76 MPFR_SET_SAME_SIGN (iop, op); 77 MPFR_SET_ZERO (iop); 78 MPFR_RET (INEX(0, inexf)); 79 } 80 else if (ope >= opq) /* op has no fractional part */ 81 { 82 inexi = (iop != op) ? mpfr_set (iop, op, rnd_mode) : 0; 83 MPFR_SET_SAME_SIGN (fop, op); 84 MPFR_SET_ZERO (fop); 85 MPFR_RET (INEX(inexi, 0)); 86 } 87 else /* op has both integral and fractional parts */ 88 { 89 if (iop != op) 90 { 91 inexi = mpfr_rint_trunc (iop, op, rnd_mode); 92 inexf = mpfr_frac (fop, op, rnd_mode); 93 } 94 else 95 { 96 MPFR_ASSERTN (fop != op); 97 inexf = mpfr_frac (fop, op, rnd_mode); 98 inexi = mpfr_rint_trunc (iop, op, rnd_mode); 99 } 100 MPFR_RET (INEX(inexi, inexf)); 101 } 102} 103