1 1.1 mrg /* mpq_set_d(mpq_t q, double d) -- Set q to d without rounding. 2 1.1 mrg 3 1.1.1.4 mrg Copyright 2000, 2002, 2003, 2012, 2014, 2018 Free Software Foundation, 4 1.1.1.4 mrg Inc. 5 1.1 mrg 6 1.1 mrg This file is part of the GNU MP Library. 7 1.1 mrg 8 1.1 mrg The GNU MP Library is free software; you can redistribute it and/or modify 9 1.1.1.3 mrg it under the terms of either: 10 1.1.1.3 mrg 11 1.1.1.3 mrg * the GNU Lesser General Public License as published by the Free 12 1.1.1.3 mrg Software Foundation; either version 3 of the License, or (at your 13 1.1.1.3 mrg option) any later version. 14 1.1.1.3 mrg 15 1.1.1.3 mrg or 16 1.1.1.3 mrg 17 1.1.1.3 mrg * the GNU General Public License as published by the Free Software 18 1.1.1.3 mrg Foundation; either version 2 of the License, or (at your option) any 19 1.1.1.3 mrg later version. 20 1.1.1.3 mrg 21 1.1.1.3 mrg or both in parallel, as here. 22 1.1 mrg 23 1.1 mrg The GNU MP Library is distributed in the hope that it will be useful, but 24 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 25 1.1.1.3 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 26 1.1.1.3 mrg for more details. 27 1.1 mrg 28 1.1.1.3 mrg You should have received copies of the GNU General Public License and the 29 1.1.1.3 mrg GNU Lesser General Public License along with the GNU MP Library. If not, 30 1.1.1.3 mrg see https://www.gnu.org/licenses/. */ 31 1.1 mrg 32 1.1 mrg #include "config.h" 33 1.1 mrg 34 1.1 mrg #if HAVE_FLOAT_H 35 1.1 mrg #include <float.h> /* for DBL_MAX */ 36 1.1 mrg #endif 37 1.1 mrg 38 1.1 mrg #include "gmp-impl.h" 39 1.1 mrg #include "longlong.h" 40 1.1 mrg 41 1.1 mrg #if LIMBS_PER_DOUBLE > 4 42 1.1 mrg choke me 43 1.1 mrg #endif 44 1.1 mrg 45 1.1 mrg void 46 1.1 mrg mpq_set_d (mpq_ptr dest, double d) 47 1.1 mrg { 48 1.1 mrg int negative; 49 1.1 mrg mp_exp_t exp; 50 1.1 mrg mp_limb_t tp[LIMBS_PER_DOUBLE]; 51 1.1 mrg mp_ptr np, dp; 52 1.1 mrg mp_size_t nn, dn; 53 1.1 mrg int c; 54 1.1 mrg 55 1.1 mrg DOUBLE_NAN_INF_ACTION (d, 56 1.1 mrg __gmp_invalid_operation (), 57 1.1 mrg __gmp_invalid_operation ()); 58 1.1 mrg 59 1.1 mrg negative = d < 0; 60 1.1 mrg d = ABS (d); 61 1.1 mrg 62 1.1 mrg exp = __gmp_extract_double (tp, d); 63 1.1 mrg 64 1.1 mrg /* There are two main version of the conversion. The `then' arm handles 65 1.1 mrg numbers with a fractional part, while the `else' arm handles integers. */ 66 1.1 mrg #if LIMBS_PER_DOUBLE == 4 67 1.1 mrg if (exp <= 1 || (exp == 2 && (tp[0] | tp[1]) != 0)) 68 1.1 mrg #endif 69 1.1 mrg #if LIMBS_PER_DOUBLE == 3 70 1.1 mrg if (exp <= 1 || (exp == 2 && tp[0] != 0)) 71 1.1 mrg #endif 72 1.1 mrg #if LIMBS_PER_DOUBLE == 2 73 1.1 mrg if (exp <= 1) 74 1.1 mrg #endif 75 1.1 mrg { 76 1.1 mrg if (d == 0.0) 77 1.1 mrg { 78 1.1.1.2 mrg SIZ(NUM(dest)) = 0; 79 1.1.1.2 mrg SIZ(DEN(dest)) = 1; 80 1.1.1.4 mrg MPZ_NEWALLOC (DEN(dest), 1)[0] = 1; 81 1.1 mrg return; 82 1.1 mrg } 83 1.1 mrg 84 1.1 mrg #if LIMBS_PER_DOUBLE == 4 85 1.1.1.3 mrg np = MPZ_NEWALLOC (NUM(dest), 4); 86 1.1 mrg if ((tp[0] | tp[1] | tp[2]) == 0) 87 1.1 mrg np[0] = tp[3], nn = 1; 88 1.1 mrg else if ((tp[0] | tp[1]) == 0) 89 1.1 mrg np[1] = tp[3], np[0] = tp[2], nn = 2; 90 1.1 mrg else if (tp[0] == 0) 91 1.1 mrg np[2] = tp[3], np[1] = tp[2], np[0] = tp[1], nn = 3; 92 1.1 mrg else 93 1.1 mrg np[3] = tp[3], np[2] = tp[2], np[1] = tp[1], np[0] = tp[0], nn = 4; 94 1.1 mrg #endif 95 1.1 mrg #if LIMBS_PER_DOUBLE == 3 96 1.1.1.3 mrg np = MPZ_NEWALLOC (NUM(dest), 3); 97 1.1 mrg if ((tp[0] | tp[1]) == 0) 98 1.1 mrg np[0] = tp[2], nn = 1; 99 1.1 mrg else if (tp[0] == 0) 100 1.1 mrg np[1] = tp[2], np[0] = tp[1], nn = 2; 101 1.1 mrg else 102 1.1 mrg np[2] = tp[2], np[1] = tp[1], np[0] = tp[0], nn = 3; 103 1.1 mrg #endif 104 1.1 mrg #if LIMBS_PER_DOUBLE == 2 105 1.1.1.3 mrg np = MPZ_NEWALLOC (NUM(dest), 2); 106 1.1 mrg if (tp[0] == 0) 107 1.1 mrg np[0] = tp[1], nn = 1; 108 1.1 mrg else 109 1.1 mrg np[1] = tp[1], np[0] = tp[0], nn = 2; 110 1.1 mrg #endif 111 1.1.1.3 mrg dn = nn + 1 - exp; 112 1.1.1.3 mrg ASSERT (dn > 0); /* -exp >= -1; nn >= 1*/ 113 1.1.1.2 mrg dp = MPZ_NEWALLOC (DEN(dest), dn); 114 1.1 mrg MPN_ZERO (dp, dn - 1); 115 1.1 mrg dp[dn - 1] = 1; 116 1.1 mrg count_trailing_zeros (c, np[0] | dp[0]); 117 1.1 mrg if (c != 0) 118 1.1 mrg { 119 1.1 mrg mpn_rshift (np, np, nn, c); 120 1.1 mrg nn -= np[nn - 1] == 0; 121 1.1.1.3 mrg --dn; 122 1.1.1.3 mrg dp[dn - 1] = CNST_LIMB(1) << (GMP_LIMB_BITS - c); 123 1.1 mrg } 124 1.1.1.2 mrg SIZ(DEN(dest)) = dn; 125 1.1 mrg } 126 1.1 mrg else 127 1.1 mrg { 128 1.1 mrg nn = exp; 129 1.1.1.2 mrg np = MPZ_NEWALLOC (NUM(dest), nn); 130 1.1 mrg switch (nn) 131 1.1 mrg { 132 1.1 mrg default: 133 1.1 mrg MPN_ZERO (np, nn - LIMBS_PER_DOUBLE); 134 1.1 mrg np += nn - LIMBS_PER_DOUBLE; 135 1.1 mrg /* fall through */ 136 1.1 mrg #if LIMBS_PER_DOUBLE == 2 137 1.1 mrg case 2: 138 1.1 mrg np[1] = tp[1], np[0] = tp[0]; 139 1.1 mrg break; 140 1.1 mrg #endif 141 1.1 mrg #if LIMBS_PER_DOUBLE == 3 142 1.1 mrg case 3: 143 1.1 mrg np[2] = tp[2], np[1] = tp[1], np[0] = tp[0]; 144 1.1 mrg break; 145 1.1 mrg case 2: 146 1.1 mrg np[1] = tp[2], np[0] = tp[1]; 147 1.1 mrg break; 148 1.1 mrg #endif 149 1.1 mrg #if LIMBS_PER_DOUBLE == 4 150 1.1 mrg case 4: 151 1.1 mrg np[3] = tp[3], np[2] = tp[2], np[1] = tp[1], np[0] = tp[0]; 152 1.1 mrg break; 153 1.1 mrg case 3: 154 1.1 mrg np[2] = tp[3], np[1] = tp[2], np[0] = tp[1]; 155 1.1 mrg break; 156 1.1 mrg case 2: 157 1.1 mrg np[1] = tp[3], np[0] = tp[2]; 158 1.1 mrg break; 159 1.1 mrg #endif 160 1.1 mrg } 161 1.1.1.4 mrg MPZ_NEWALLOC (DEN(dest), 1)[0] = 1; 162 1.1.1.2 mrg SIZ(DEN(dest)) = 1; 163 1.1 mrg } 164 1.1.1.3 mrg SIZ(NUM(dest)) = negative ? -nn : nn; 165 1.1 mrg } 166