Annotation of OpenXM_contrib/gmp/extract-dbl.c, Revision 1.1.1.2
1.1 maekawa 1: /* __gmp_extract_double -- convert from double to array of mp_limb_t.
2:
1.1.1.2 ! ohara 3: Copyright 1996, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
1.1 maekawa 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 2.1 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; see the file COPYING.LIB. If not, write to
19: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20: MA 02111-1307, USA. */
21:
22: #include "gmp.h"
23: #include "gmp-impl.h"
24:
25: #ifdef XDEBUG
26: #undef _GMP_IEEE_FLOATS
27: #endif
28:
29: #ifndef _GMP_IEEE_FLOATS
30: #define _GMP_IEEE_FLOATS 0
31: #endif
32:
1.1.1.2 ! ohara 33: #define BITS_IN_MANTISSA 53
! 34:
1.1 maekawa 35: /* Extract a non-negative double in d. */
36:
37: int
38: __gmp_extract_double (mp_ptr rp, double d)
39: {
40: long exp;
41: unsigned sc;
1.1.1.2 ! ohara 42: #ifdef _LONG_LONG_LIMB
! 43: #define BITS_PER_PART 64 /* somewhat bogus */
! 44: unsigned long long int manl;
! 45: #else
! 46: #define BITS_PER_PART GMP_LIMB_BITS
! 47: unsigned long int manh, manl;
! 48: #endif
1.1 maekawa 49:
50: /* BUGS
51:
52: 1. Should handle Inf and NaN in IEEE specific code.
53: 2. Handle Inf and NaN also in default code, to avoid hangs.
1.1.1.2 ! ohara 54: 3. Generalize to handle all GMP_LIMB_BITS >= 32.
1.1 maekawa 55: 4. This lits is incomplete and misspelled.
56: */
57:
1.1.1.2 ! ohara 58: ASSERT (d >= 0.0);
! 59:
1.1 maekawa 60: if (d == 0.0)
61: {
1.1.1.2 ! ohara 62: MPN_ZERO (rp, LIMBS_PER_DOUBLE);
1.1 maekawa 63: return 0;
64: }
65:
66: #if _GMP_IEEE_FLOATS
67: {
68: #if defined (__alpha) && __GNUC__ == 2 && __GNUC_MINOR__ == 8
69: /* Work around alpha-specific bug in GCC 2.8.x. */
70: volatile
71: #endif
72: union ieee_double_extract x;
73: x.d = d;
74: exp = x.s.exp;
1.1.1.2 ! ohara 75: #if BITS_PER_PART == 64 /* generalize this to BITS_PER_PART > BITS_IN_MANTISSA */
1.1 maekawa 76: manl = (((mp_limb_t) 1 << 63)
77: | ((mp_limb_t) x.s.manh << 43) | ((mp_limb_t) x.s.manl << 11));
78: if (exp == 0)
79: {
80: /* Denormalized number. Don't try to be clever about this,
81: since it is not an important case to make fast. */
82: exp = 1;
83: do
84: {
85: manl = manl << 1;
86: exp--;
87: }
88: while ((mp_limb_signed_t) manl >= 0);
89: }
1.1.1.2 ! ohara 90: #endif
! 91: #if BITS_PER_PART == 32
1.1 maekawa 92: manh = ((mp_limb_t) 1 << 31) | (x.s.manh << 11) | (x.s.manl >> 21);
93: manl = x.s.manl << 11;
94: if (exp == 0)
95: {
96: /* Denormalized number. Don't try to be clever about this,
97: since it is not an important case to make fast. */
98: exp = 1;
99: do
100: {
101: manh = (manh << 1) | (manl >> 31);
102: manl = manl << 1;
103: exp--;
104: }
105: while ((mp_limb_signed_t) manh >= 0);
106: }
107: #endif
1.1.1.2 ! ohara 108: #if BITS_PER_PART != 32 && BITS_PER_PART != 64
! 109: You need to generalize the code above to handle this.
! 110: #endif
1.1 maekawa 111: exp -= 1022; /* Remove IEEE bias. */
112: }
113: #else
114: {
115: /* Unknown (or known to be non-IEEE) double format. */
116: exp = 0;
117: if (d >= 1.0)
118: {
119: if (d * 0.5 == d)
120: abort ();
121:
122: while (d >= 32768.0)
123: {
124: d *= (1.0 / 65536.0);
125: exp += 16;
126: }
127: while (d >= 1.0)
128: {
129: d *= 0.5;
130: exp += 1;
131: }
132: }
133: else if (d < 0.5)
134: {
135: while (d < (1.0 / 65536.0))
136: {
137: d *= 65536.0;
138: exp -= 16;
139: }
140: while (d < 0.5)
141: {
142: d *= 2.0;
143: exp -= 1;
144: }
145: }
146:
1.1.1.2 ! ohara 147: d *= (4.0 * ((unsigned long int) 1 << (BITS_PER_PART - 2)));
! 148: #if BITS_PER_PART == 64
1.1 maekawa 149: manl = d;
150: #else
151: manh = d;
1.1.1.2 ! ohara 152: manl = (d - manh) * (4.0 * ((unsigned long int) 1 << (BITS_PER_PART - 2)));
1.1 maekawa 153: #endif
154: }
1.1.1.2 ! ohara 155: #endif /* IEEE */
! 156:
! 157: /* Up until here, we have ignored the actual limb size. Remains
! 158: to split manh,,manl into an array of LIMBS_PER_DOUBLE limbs.
! 159: */
1.1 maekawa 160:
1.1.1.2 ! ohara 161: sc = (unsigned) (exp + 64 * GMP_NUMB_BITS) % GMP_NUMB_BITS;
1.1 maekawa 162:
163: /* We add something here to get rounding right. */
1.1.1.2 ! ohara 164: exp = (exp + 64 * GMP_NUMB_BITS) / GMP_NUMB_BITS - 64 * GMP_NUMB_BITS / GMP_NUMB_BITS + 1;
1.1 maekawa 165:
1.1.1.2 ! ohara 166: #if LIMBS_PER_DOUBLE == 2
! 167: #if GMP_NAIL_BITS == 0
1.1 maekawa 168: if (sc != 0)
169: {
1.1.1.2 ! ohara 170: rp[1] = manl >> (GMP_LIMB_BITS - sc);
1.1 maekawa 171: rp[0] = manl << sc;
172: }
173: else
174: {
175: rp[1] = manl;
176: rp[0] = 0;
177: exp--;
178: }
179: #else
1.1.1.2 ! ohara 180: if (sc > GMP_NAIL_BITS)
! 181: {
! 182: rp[1] = manl >> (GMP_LIMB_BITS - sc);
! 183: rp[0] = (manl << (sc - GMP_NAIL_BITS)) & GMP_NUMB_MASK;
! 184: }
! 185: else
! 186: {
! 187: if (sc == 0)
! 188: {
! 189: rp[1] = manl >> GMP_NAIL_BITS;
! 190: rp[0] = (manl << GMP_NUMB_BITS - GMP_NAIL_BITS) & GMP_NUMB_MASK;
! 191: exp--;
! 192: }
! 193: else
! 194: {
! 195: rp[1] = manl >> (GMP_LIMB_BITS - sc);
! 196: rp[0] = (manl >> (GMP_NAIL_BITS - sc)) & GMP_NUMB_MASK;
! 197: }
! 198: }
! 199: #endif
! 200: #endif
! 201:
! 202: #if LIMBS_PER_DOUBLE == 3
! 203: #if GMP_NAIL_BITS == 0
1.1 maekawa 204: if (sc != 0)
205: {
1.1.1.2 ! ohara 206: rp[2] = manh >> (GMP_LIMB_BITS - sc);
! 207: rp[1] = (manh << sc) | (manl >> (GMP_LIMB_BITS - sc));
1.1 maekawa 208: rp[0] = manl << sc;
209: }
210: else
211: {
212: rp[2] = manh;
213: rp[1] = manl;
214: rp[0] = 0;
215: exp--;
216: }
1.1.1.2 ! ohara 217: #else
! 218: if (sc > GMP_NAIL_BITS)
! 219: {
! 220: rp[2] = (manh >> (GMP_LIMB_BITS - sc));
! 221: rp[1] = ((manh << (sc - GMP_NAIL_BITS)) |
! 222: (manl >> (GMP_LIMB_BITS - sc + GMP_NAIL_BITS))) & GMP_NUMB_MASK;
! 223: if (sc >= 2 * GMP_NAIL_BITS)
! 224: rp[0] = (manl << sc - 2 * GMP_NAIL_BITS) & GMP_NUMB_MASK;
! 225: else
! 226: rp[0] = manl >> (2 * GMP_NAIL_BITS - sc) & GMP_NUMB_MASK;
! 227: }
! 228: else
! 229: {
! 230: if (sc == 0)
! 231: {
! 232: rp[2] = manh >> GMP_NAIL_BITS;
! 233: rp[1] = ((manh << GMP_NUMB_BITS - GMP_NAIL_BITS) | (manl >> 2 * GMP_NAIL_BITS)) & GMP_NUMB_MASK;
! 234: rp[0] = 0;
! 235: exp--;
! 236: }
! 237: else
! 238: {
! 239: rp[2] = (manh >> (GMP_LIMB_BITS - sc));
! 240: rp[1] = (manh >> (GMP_NAIL_BITS - sc)) & GMP_NUMB_MASK;
! 241: rp[0] = ((manh << (GMP_NUMB_BITS - GMP_NAIL_BITS + sc))
! 242: | (manl >> (GMP_LIMB_BITS - (GMP_NUMB_BITS - GMP_NAIL_BITS + sc)))) & GMP_NUMB_MASK;
! 243: }
! 244: }
! 245: #endif
! 246: #endif
! 247:
! 248: #if LIMBS_PER_DOUBLE > 3
! 249: /* Insert code for splitting manh,,manl into LIMBS_PER_DOUBLE
! 250: mp_limb_t's at rp. */
! 251: if (sc != 0)
! 252: {
! 253: /* This is not perfect, and would fail for GMP_LIMB_BITS == 16.
! 254: The ASSERT_ALWAYS should catch the problematic cases. */
! 255: ASSERT_ALWAYS ((manl << sc) == 0);
! 256: manl = (manh << sc) | (manl >> (GMP_LIMB_BITS - sc));
! 257: manh = manh >> (GMP_LIMB_BITS - sc);
! 258: }
! 259: {
! 260: int i;
! 261: for (i = LIMBS_PER_DOUBLE - 1; i >= 0; i--)
! 262: {
! 263: rp[i] = manh >> (BITS_PER_LONGINT - GMP_LIMB_BITS);
! 264: manh = ((manh << GMP_LIMB_BITS)
! 265: | (manl >> (BITS_PER_LONGINT - GMP_LIMB_BITS)));
! 266: manl = manl << GMP_LIMB_BITS;
! 267: }
! 268: }
1.1 maekawa 269: #endif
270:
271: return exp;
272: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>