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