1/* mpz_set_d(integer, val) -- Assign INTEGER with a double value VAL. 2 3Copyright 1995, 1996, 2000, 2001, 2002, 2003, 2006 Free Software Foundation, 4Inc. 5 6This file is part of the GNU MP Library. 7 8The GNU MP 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 MP 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 MP Library. If not, see http://www.gnu.org/licenses/. */ 20 21#include "config.h" 22 23#if HAVE_FLOAT_H 24#include <float.h> /* for DBL_MAX */ 25#endif 26 27#include "gmp.h" 28#include "gmp-impl.h" 29 30 31/* We used to have a special case for d < MP_BASE_AS_DOUBLE, just casting 32 double -> limb. Unfortunately gcc 3.3 on powerpc970-apple-darwin6.8.5 33 got this wrong. (It assumed __fixunsdfdi returned its result in a single 34 64-bit register, where instead that function followed the calling 35 conventions and gave the result in two parts r3 and r4.) Hence the use 36 of __gmp_extract_double in all cases. */ 37 38void 39mpz_set_d (mpz_ptr r, double d) 40{ 41 int negative; 42 mp_limb_t tp[LIMBS_PER_DOUBLE]; 43 mp_ptr rp; 44 mp_size_t rn; 45 46 DOUBLE_NAN_INF_ACTION (d, 47 __gmp_invalid_operation (), 48 __gmp_invalid_operation ()); 49 50 negative = d < 0; 51 d = ABS (d); 52 53 rn = __gmp_extract_double (tp, d); 54 55 if (ALLOC(r) < rn) 56 _mpz_realloc (r, rn); 57 58 if (rn <= 0) 59 rn = 0; 60 61 rp = PTR (r); 62 63 switch (rn) 64 { 65 default: 66 MPN_ZERO (rp, rn - LIMBS_PER_DOUBLE); 67 rp += rn - LIMBS_PER_DOUBLE; 68 /* fall through */ 69#if LIMBS_PER_DOUBLE == 2 70 case 2: 71 rp[1] = tp[1], rp[0] = tp[0]; 72 break; 73 case 1: 74 rp[0] = tp[1]; 75 break; 76#endif 77#if LIMBS_PER_DOUBLE == 3 78 case 3: 79 rp[2] = tp[2], rp[1] = tp[1], rp[0] = tp[0]; 80 break; 81 case 2: 82 rp[1] = tp[2], rp[0] = tp[1]; 83 break; 84 case 1: 85 rp[0] = tp[2]; 86 break; 87#endif 88#if LIMBS_PER_DOUBLE == 4 89 case 4: 90 rp[3] = tp[3], rp[2] = tp[2], rp[1] = tp[1], rp[0] = tp[0]; 91 break; 92 case 3: 93 rp[2] = tp[3], rp[1] = tp[2], rp[0] = tp[1]; 94 break; 95 case 2: 96 rp[1] = tp[3], rp[0] = tp[2]; 97 break; 98 case 1: 99 rp[0] = tp[3]; 100 break; 101#endif 102 case 0: 103 break; 104 } 105 106 SIZ(r) = negative ? -rn : rn; 107} 108