1/* mpfr_modf -- Integral and fractional part. 2 3Copyright 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. 4Contributed by the Arenaire and Cacao 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 (("op[%#R]=%R rnd=%d", op, op, rnd_mode), 37 ("iop[%#R]=%R fop[%#R]=%R", iop, iop, fop, fop)); 38 39 MPFR_ASSERTN (iop != fop); 40 41 if ( MPFR_UNLIKELY (MPFR_IS_SINGULAR (op)) ) 42 { 43 if (MPFR_IS_NAN (op)) 44 { 45 MPFR_SET_NAN (iop); 46 MPFR_SET_NAN (fop); 47 MPFR_RET_NAN; 48 } 49 MPFR_SET_SAME_SIGN (iop, op); 50 MPFR_SET_SAME_SIGN (fop, op); 51 if (MPFR_IS_INF (op)) 52 { 53 MPFR_SET_INF (iop); 54 MPFR_SET_ZERO (fop); 55 MPFR_RET (0); 56 } 57 else /* op is zero */ 58 { 59 MPFR_ASSERTD (MPFR_IS_ZERO (op)); 60 MPFR_SET_ZERO (iop); 61 MPFR_SET_ZERO (fop); 62 MPFR_RET (0); 63 } 64 } 65 66 ope = MPFR_GET_EXP (op); 67 opq = MPFR_PREC (op); 68 69 if (ope <= 0) /* 0 < |op| < 1 */ 70 { 71 inexf = (fop != op) ? mpfr_set (fop, op, rnd_mode) : 0; 72 MPFR_SET_SAME_SIGN (iop, op); 73 MPFR_SET_ZERO (iop); 74 MPFR_RET (INEX(0, inexf)); 75 } 76 else if (ope >= opq) /* op has no fractional part */ 77 { 78 inexi = (iop != op) ? mpfr_set (iop, op, rnd_mode) : 0; 79 MPFR_SET_SAME_SIGN (fop, op); 80 MPFR_SET_ZERO (fop); 81 MPFR_RET (INEX(inexi, 0)); 82 } 83 else /* op has both integral and fractional parts */ 84 { 85 if (iop != op) 86 { 87 inexi = mpfr_rint_trunc (iop, op, rnd_mode); 88 inexf = mpfr_frac (fop, op, rnd_mode); 89 } 90 else 91 { 92 MPFR_ASSERTN (fop != op); 93 inexf = mpfr_frac (fop, op, rnd_mode); 94 inexi = mpfr_rint_trunc (iop, op, rnd_mode); 95 } 96 MPFR_RET (INEX(inexi, inexf)); 97 } 98} 99