1use crate::common::{dd_fmla, dyad_fmla, f_fmla};
30use crate::double_double::DoubleDouble;
31use crate::exponents::fast_ldexp;
32use crate::floor::FloorFinite;
33use crate::round_ties_even::RoundTiesEven;
34
35const LN2H: f64 = f64::from_bits(0x3fe62e42fefa39ef);
36const LN2L: f64 = f64::from_bits(0x3c7abc9e3b39803f);
37
38struct Exp2m1 {
39 exp: DoubleDouble,
40 err: f64,
41}
42
43pub(crate) static EXP_M1_2_TABLE1: [(u64, u64); 64] = [
47 (0x0000000000000000, 0x3ff0000000000000),
48 (0xbc719083535b085d, 0x3ff02c9a3e778061),
49 (0x3c8d73e2a475b465, 0x3ff059b0d3158574),
50 (0x3c6186be4bb284ff, 0x3ff0874518759bc8),
51 (0x3c98a62e4adc610b, 0x3ff0b5586cf9890f),
52 (0x3c403a1727c57b53, 0x3ff0e3ec32d3d1a2),
53 (0xbc96c51039449b3a, 0x3ff11301d0125b51),
54 (0xbc932fbf9af1369e, 0x3ff1429aaea92de0),
55 (0xbc819041b9d78a76, 0x3ff172b83c7d517b),
56 (0x3c8e5b4c7b4968e4, 0x3ff1a35beb6fcb75),
57 (0x3c9e016e00a2643c, 0x3ff1d4873168b9aa),
58 (0x3c8dc775814a8495, 0x3ff2063b88628cd6),
59 (0x3c99b07eb6c70573, 0x3ff2387a6e756238),
60 (0x3c82bd339940e9d9, 0x3ff26b4565e27cdd),
61 (0x3c8612e8afad1255, 0x3ff29e9df51fdee1),
62 (0x3c90024754db41d5, 0x3ff2d285a6e4030b),
63 (0x3c86f46ad23182e4, 0x3ff306fe0a31b715),
64 (0x3c932721843659a6, 0x3ff33c08b26416ff),
65 (0xbc963aeabf42eae2, 0x3ff371a7373aa9cb),
66 (0xbc75e436d661f5e3, 0x3ff3a7db34e59ff7),
67 (0x3c8ada0911f09ebc, 0x3ff3dea64c123422),
68 (0xbc5ef3691c309278, 0x3ff4160a21f72e2a),
69 (0x3c489b7a04ef80d0, 0x3ff44e086061892d),
70 (0x3c73c1a3b69062f0, 0x3ff486a2b5c13cd0),
71 (0x3c7d4397afec42e2, 0x3ff4bfdad5362a27),
72 (0xbc94b309d25957e3, 0x3ff4f9b2769d2ca7),
73 (0xbc807abe1db13cad, 0x3ff5342b569d4f82),
74 (0x3c99bb2c011d93ad, 0x3ff56f4736b527da),
75 (0x3c96324c054647ad, 0x3ff5ab07dd485429),
76 (0x3c9ba6f93080e65e, 0x3ff5e76f15ad2148),
77 (0xbc9383c17e40b497, 0x3ff6247eb03a5585),
78 (0xbc9bb60987591c34, 0x3ff6623882552225),
79 (0xbc9bdd3413b26456, 0x3ff6a09e667f3bcd),
80 (0xbc6bbe3a683c88ab, 0x3ff6dfb23c651a2f),
81 (0xbc816e4786887a99, 0x3ff71f75e8ec5f74),
82 (0xbc90245957316dd3, 0x3ff75feb564267c9),
83 (0xbc841577ee04992f, 0x3ff7a11473eb0187),
84 (0x3c705d02ba15797e, 0x3ff7e2f336cf4e62),
85 (0xbc9d4c1dd41532d8, 0x3ff82589994cce13),
86 (0xbc9fc6f89bd4f6ba, 0x3ff868d99b4492ed),
87 (0x3c96e9f156864b27, 0x3ff8ace5422aa0db),
88 (0x3c85cc13a2e3976c, 0x3ff8f1ae99157736),
89 (0xbc675fc781b57ebc, 0x3ff93737b0cdc5e5),
90 (0xbc9d185b7c1b85d1, 0x3ff97d829fde4e50),
91 (0x3c7c7c46b071f2be, 0x3ff9c49182a3f090),
92 (0xbc9359495d1cd533, 0x3ffa0c667b5de565),
93 (0xbc9d2f6edb8d41e1, 0x3ffa5503b23e255d),
94 (0x3c90fac90ef7fd31, 0x3ffa9e6b5579fdbf),
95 (0x3c97a1cd345dcc81, 0x3ffae89f995ad3ad),
96 (0xbc62805e3084d708, 0x3ffb33a2b84f15fb),
97 (0xbc75584f7e54ac3b, 0x3ffb7f76f2fb5e47),
98 (0x3c823dd07a2d9e84, 0x3ffbcc1e904bc1d2),
99 (0x3c811065895048dd, 0x3ffc199bdd85529c),
100 (0x3c92884dff483cad, 0x3ffc67f12e57d14b),
101 (0x3c7503cbd1e949db, 0x3ffcb720dcef9069),
102 (0xbc9cbc3743797a9c, 0x3ffd072d4a07897c),
103 (0x3c82ed02d75b3707, 0x3ffd5818dcfba487),
104 (0x3c9c2300696db532, 0x3ffda9e603db3285),
105 (0xbc91a5cd4f184b5c, 0x3ffdfc97337b9b5f),
106 (0x3c839e8980a9cc8f, 0x3ffe502ee78b3ff6),
107 (0xbc9e9c23179c2893, 0x3ffea4afa2a490da),
108 (0x3c9dc7f486a4b6b0, 0x3ffefa1bee615a27),
109 (0x3c99d3e12dd8a18b, 0x3fff50765b6e4540),
110 (0x3c874853f3a5931e, 0x3fffa7c1819e90d8),
111];
112
113pub(crate) static EXP_M1_2_TABLE2: [(u64, u64); 64] = [
117 (0x0000000000000000, 0x3ff0000000000000),
118 (0x3c9ae8e38c59c72a, 0x3ff000b175effdc7),
119 (0xbc57b5d0d58ea8f4, 0x3ff00162f3904052),
120 (0x3c94115cb6b16a8e, 0x3ff0021478e11ce6),
121 (0xbc8d7c96f201bb2f, 0x3ff002c605e2e8cf),
122 (0x3c984711d4c35e9f, 0x3ff003779a95f959),
123 (0xbc80484245243777, 0x3ff0042936faa3d8),
124 (0xbc94b237da2025f9, 0x3ff004dadb113da0),
125 (0xbc75e00e62d6b30d, 0x3ff0058c86da1c0a),
126 (0x3c9a1d6cedbb9481, 0x3ff0063e3a559473),
127 (0xbc94acf197a00142, 0x3ff006eff583fc3d),
128 (0xbc6eaf2ea42391a5, 0x3ff007a1b865a8ca),
129 (0x3c7da93f90835f75, 0x3ff0085382faef83),
130 (0xbc86a79084ab093c, 0x3ff00905554425d4),
131 (0x3c986364f8fbe8f8, 0x3ff009b72f41a12b),
132 (0xbc882e8e14e3110e, 0x3ff00a6910f3b6fd),
133 (0xbc84f6b2a7609f71, 0x3ff00b1afa5abcbf),
134 (0xbc7e1a258ea8f71b, 0x3ff00bcceb7707ec),
135 (0x3c74362ca5bc26f1, 0x3ff00c7ee448ee02),
136 (0x3c9095a56c919d02, 0x3ff00d30e4d0c483),
137 (0xbc6406ac4e81a645, 0x3ff00de2ed0ee0f5),
138 (0x3c9b5a6902767e09, 0x3ff00e94fd0398e0),
139 (0xbc991b2060859321, 0x3ff00f4714af41d3),
140 (0x3c8427068ab22306, 0x3ff00ff93412315c),
141 (0x3c9c1d0660524e08, 0x3ff010ab5b2cbd11),
142 (0xbc9e7bdfb3204be8, 0x3ff0115d89ff3a8b),
143 (0x3c8843aa8b9cbbc6, 0x3ff0120fc089ff63),
144 (0xbc734104ee7edae9, 0x3ff012c1fecd613b),
145 (0xbc72b6aeb6176892, 0x3ff0137444c9b5b5),
146 (0x3c7a8cd33b8a1bb3, 0x3ff01426927f5278),
147 (0x3c72edc08e5da99a, 0x3ff014d8e7ee8d2f),
148 (0x3c857ba2dc7e0c73, 0x3ff0158b4517bb88),
149 (0x3c9b61299ab8cdb7, 0x3ff0163da9fb3335),
150 (0xbc990565902c5f44, 0x3ff016f0169949ed),
151 (0x3c870fc41c5c2d53, 0x3ff017a28af25567),
152 (0x3c94b9a6e145d76c, 0x3ff018550706ab62),
153 (0xbc7008eff5142bf9, 0x3ff019078ad6a19f),
154 (0xbc977669f033c7de, 0x3ff019ba16628de2),
155 (0xbc909bb78eeead0a, 0x3ff01a6ca9aac5f3),
156 (0x3c9371231477ece5, 0x3ff01b1f44af9f9e),
157 (0x3c75e7626621eb5b, 0x3ff01bd1e77170b4),
158 (0xbc9bc72b100828a5, 0x3ff01c8491f08f08),
159 (0xbc6ce39cbbab8bbe, 0x3ff01d37442d5070),
160 (0x3c816996709da2e2, 0x3ff01de9fe280ac8),
161 (0xbc8c11f5239bf535, 0x3ff01e9cbfe113ef),
162 (0x3c8e1d4eb5edc6b3, 0x3ff01f4f8958c1c6),
163 (0xbc9afb99946ee3f0, 0x3ff020025a8f6a35),
164 (0xbc98f06d8a148a32, 0x3ff020b533856324),
165 (0xbc82bf310fc54eb6, 0x3ff02168143b0281),
166 (0xbc9c95a035eb4175, 0x3ff0221afcb09e3e),
167 (0xbc9491793e46834d, 0x3ff022cdece68c4f),
168 (0xbc73e8d0d9c49091, 0x3ff02380e4dd22ad),
169 (0xbc9314aa16278aa3, 0x3ff02433e494b755),
170 (0x3c848daf888e9651, 0x3ff024e6ec0da046),
171 (0x3c856dc8046821f4, 0x3ff02599fb483385),
172 (0x3c945b42356b9d47, 0x3ff0264d1244c719),
173 (0xbc7082ef51b61d7e, 0x3ff027003103b10e),
174 (0x3c72106ed0920a34, 0x3ff027b357854772),
175 (0xbc9fd4cf26ea5d0f, 0x3ff0286685c9e059),
176 (0xbc909f8775e78084, 0x3ff02919bbd1d1d8),
177 (0x3c564cbba902ca27, 0x3ff029ccf99d720a),
178 (0x3c94383ef231d207, 0x3ff02a803f2d170d),
179 (0x3c94a47a505b3a47, 0x3ff02b338c811703),
180 (0x3c9e47120223467f, 0x3ff02be6e199c811),
181];
182
183#[inline]
187fn q_1(dz: DoubleDouble) -> DoubleDouble {
188 const Q_1: [u64; 5] = [
189 0x3ff0000000000000,
190 0x3ff0000000000000,
191 0x3fe0000000000000,
192 0x3fc5555555995d37,
193 0x3fa55555558489dc,
194 ];
195 let z = dz.to_f64();
196 let mut q = f_fmla(f64::from_bits(Q_1[4]), dz.hi, f64::from_bits(Q_1[3]));
197 q = f_fmla(q, z, f64::from_bits(Q_1[2]));
198
199 let mut p0 = DoubleDouble::from_exact_add(f64::from_bits(Q_1[1]), q * z);
200 p0 = DoubleDouble::quick_mult(dz, p0);
201 p0 = DoubleDouble::f64_add(f64::from_bits(Q_1[0]), p0);
202 p0
203}
204
205#[inline]
206fn exp1(x: DoubleDouble) -> DoubleDouble {
207 const INVLOG2: f64 = f64::from_bits(0x40b71547652b82fe); let k = (x.hi * INVLOG2).round_ties_even_finite();
209
210 const LOG2H: f64 = f64::from_bits(0x3f262e42fefa39ef);
211 const LOG2L: f64 = f64::from_bits(0x3bbabc9e3b39803f);
212 const LOG2DD: DoubleDouble = DoubleDouble::new(LOG2L, LOG2H);
213 let zk = DoubleDouble::quick_mult_f64(LOG2DD, k);
214
215 let mut yz = DoubleDouble::from_exact_add(x.hi - zk.hi, x.lo);
216 yz.lo -= zk.lo;
217
218 let ik: i64 = unsafe { k.to_int_unchecked::<i64>() }; let im: i64 = (ik >> 12).wrapping_add(0x3ff);
220 let i2: i64 = (ik >> 6) & 0x3f;
221 let i1: i64 = ik & 0x3f;
222
223 let t1 = DoubleDouble::from_bit_pair(EXP_M1_2_TABLE1[i2 as usize]);
224 let t2 = DoubleDouble::from_bit_pair(EXP_M1_2_TABLE2[i1 as usize]);
225
226 let p0 = DoubleDouble::quick_mult(t2, t1);
227
228 let mut q = q_1(yz);
229 q = DoubleDouble::quick_mult(p0, q);
230
231 let mut du = (im as u64).wrapping_shl(52);
234 if im == 0x7ff {
235 q.hi *= 2.0;
236 q.lo *= 2.0;
237 du = (im.wrapping_sub(1) as u64).wrapping_shl(52);
238 }
239 q.hi *= f64::from_bits(du);
240 q.lo *= f64::from_bits(du);
241 q
242}
243
244#[inline]
245fn exp2m1_fast(x: f64, tiny: bool) -> Exp2m1 {
246 if tiny {
247 return exp2m1_fast_tiny(x);
248 }
249 let mut v = DoubleDouble::from_exact_mult(LN2H, x);
252 v.lo = f_fmla(x, LN2L, v.lo);
253 let mut p = exp1(v);
265
266 let zf: DoubleDouble = if x >= 0. {
267 DoubleDouble::from_exact_add(p.hi, -1.0)
269 } else {
270 DoubleDouble::from_exact_add(-1.0, p.hi)
271 };
272 p.lo += zf.lo;
273 p.hi = zf.hi;
274 Exp2m1 {
281 exp: p,
282 err: f64::from_bits(0x3b84200000000000) * p.hi, }
284}
285
286#[inline]
290fn q_2(dz: DoubleDouble) -> DoubleDouble {
291 const Q_2: [u64; 9] = [
305 0x3ff0000000000000,
306 0x3ff0000000000000,
307 0x3fe0000000000000,
308 0x3fc5555555555555,
309 0x3c655555555c4d26,
310 0x3fa5555555555555,
311 0x3f81111111111111,
312 0x3f56c16c3fbb4213,
313 0x3f2a01a023ede0d7,
314 ];
315
316 let z = dz.to_f64();
317 let mut q = dd_fmla(f64::from_bits(Q_2[8]), dz.hi, f64::from_bits(Q_2[7]));
318 q = dd_fmla(q, z, f64::from_bits(Q_2[6]));
319 q = dd_fmla(q, z, f64::from_bits(Q_2[5]));
320
321 let mut p = DoubleDouble::from_exact_mult(q, z);
324 let r0 = DoubleDouble::from_exact_add(f64::from_bits(Q_2[3]), p.hi);
325 p.hi = r0.hi;
326 p.lo += r0.lo + f64::from_bits(Q_2[4]);
327
328 p = DoubleDouble::quick_mult(p, dz);
331 let r1 = DoubleDouble::from_exact_add(f64::from_bits(Q_2[2]), p.hi);
332 p.hi = r1.hi;
333 p.lo += r1.lo;
334
335 p = DoubleDouble::quick_mult(p, dz);
337 let r1 = DoubleDouble::from_exact_add(f64::from_bits(Q_2[1]), p.hi);
338 p.hi = r1.hi;
339 p.lo += r1.lo;
340
341 p = DoubleDouble::quick_mult(p, dz);
343 let r1 = DoubleDouble::from_exact_add(f64::from_bits(Q_2[0]), p.hi);
344 p.hi = r1.hi;
345 p.lo += r1.lo;
346 p
347}
348
349#[inline]
351fn exp_2(x: f64) -> DoubleDouble {
352 let k = (x * f64::from_bits(0x40b0000000000000)).round_ties_even_finite();
353 let yhh = f_fmla(-k, f64::from_bits(0x3f30000000000000), x); let ky = DoubleDouble::quick_f64_mult(yhh, DoubleDouble::new(LN2L, LN2H));
360
361 let ik: i64 = unsafe {
362 k.to_int_unchecked::<i64>() };
364 let im = (ik >> 12).wrapping_add(0x3ff);
365 let i2 = (ik >> 6) & 0x3f;
366 let i1 = ik & 0x3f;
367
368 let t1 = DoubleDouble::from_bit_pair(EXP_M1_2_TABLE1[i2 as usize]);
369 let t2 = DoubleDouble::from_bit_pair(EXP_M1_2_TABLE2[i1 as usize]);
370
371 let p = DoubleDouble::quick_mult(t2, t1);
372
373 let mut q = q_2(ky);
374 q = DoubleDouble::quick_mult(p, q);
375 let mut ud: u64 = (im as u64).wrapping_shl(52);
376
377 if im == 0x7ff {
378 q.hi *= 2.0;
379 q.lo *= 2.0;
380 ud = (im.wrapping_sub(1) as u64).wrapping_shl(52);
381 }
382 q.hi *= f64::from_bits(ud);
383 q.lo *= f64::from_bits(ud);
384 q
385}
386
387#[cold]
388pub(crate) fn exp2m1_accurate_tiny(x: f64) -> f64 {
389 let x2 = x * x;
390 let x4 = x2 * x2;
391 const Q: [u64; 22] = [
392 0x3fe62e42fefa39ef,
393 0x3c7abc9e3b398040,
394 0x3fcebfbdff82c58f,
395 0xbc65e43a53e44dcf,
396 0x3fac6b08d704a0c0,
397 0xbc4d331627517168,
398 0x3f83b2ab6fba4e77,
399 0x3c14e65df0779f8c,
400 0x3f55d87fe78a6731,
401 0x3bd0717fbf4bd050,
402 0x3f2430912f86c787,
403 0x3bcbd2bdec9bcd42,
404 0x3eeffcbfc588b0c7,
405 0xbb8e60aa6d5e4aa9,
406 0x3eb62c0223a5c824,
407 0x3e7b5253d395e7d4,
408 0x3e3e4cf5158b9160,
409 0x3dfe8cac734c6058,
410 0x3dbc3bd64f17199d,
411 0x3d78161a17e05651,
412 0x3d33150b3d792231,
413 0x3cec184260bfad7e,
414 ];
415 let mut c13 = dd_fmla(f64::from_bits(Q[20]), x, f64::from_bits(Q[19])); let c11 = dd_fmla(f64::from_bits(Q[18]), x, f64::from_bits(Q[17])); c13 = dd_fmla(f64::from_bits(Q[21]), x2, c13); let mut p = DoubleDouble::from_exact_add(
420 f64::from_bits(Q[15]),
421 f_fmla(f64::from_bits(Q[16]), x, f_fmla(c11, x2, c13 * x4)),
422 );
423 p = DoubleDouble::quick_f64_mult(x, p);
425 let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[14]), p.hi);
426 p.lo += p0.lo;
427 p.hi = p0.hi;
428
429 p = DoubleDouble::quick_f64_mult(x, p);
431 let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[12]), p.hi);
432 p.lo += p0.lo + f64::from_bits(Q[13]);
433 p.hi = p0.hi;
434 p = DoubleDouble::quick_f64_mult(x, p);
436 let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[10]), p.hi);
437 p.lo += p0.lo + f64::from_bits(Q[11]);
438 p.hi = p0.hi;
439 p = DoubleDouble::quick_f64_mult(x, p);
441 let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[8]), p.hi);
442 p.lo += p0.lo + f64::from_bits(Q[9]);
443 p.hi = p0.hi;
444 p = DoubleDouble::quick_f64_mult(x, p);
446 let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[6]), p.hi);
447 p.lo += p0.lo + f64::from_bits(Q[7]);
448 p.hi = p0.hi;
449 p = DoubleDouble::quick_f64_mult(x, p);
451 let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[4]), p.hi);
452 p.lo += p0.lo + f64::from_bits(Q[5]);
453 p.hi = p0.hi;
454 p = DoubleDouble::quick_f64_mult(x, p);
456 let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[2]), p.hi);
457 p.lo += p0.lo + f64::from_bits(Q[3]);
458 p.hi = p0.hi;
459 p = DoubleDouble::quick_f64_mult(x, p);
461 let p0 = DoubleDouble::from_exact_add(f64::from_bits(Q[0]), p.hi);
462 p.lo += p0.lo + f64::from_bits(Q[1]);
463 p.hi = p0.hi;
464 p = DoubleDouble::quick_f64_mult(x, p);
466 p.to_f64()
467}
468
469#[cold]
470fn exp2m1_accurate(x: f64) -> f64 {
471 let t = x.to_bits();
472 let ux = t;
473 let ax = ux & 0x7fffffffffffffffu64;
474
475 if ax <= 0x3fc0000000000000u64 {
476 return exp2m1_accurate_tiny(x);
478 }
479
480 let mut p = exp_2(x);
481
482 let zf: DoubleDouble = DoubleDouble::from_full_exact_add(p.hi, -1.0);
483 p.lo += zf.lo;
484 p.hi = zf.hi;
485 p.to_f64()
486}
487
488#[inline]
498fn exp2m1_fast_tiny(x: f64) -> Exp2m1 {
499 const P: [u64; 12] = [
504 0x3fe62e42fefa39ef,
505 0x3c7abd1697afcaf8,
506 0x3fcebfbdff82c58f,
507 0xbc65e5a1d09e1599,
508 0x3fac6b08d704a0bf,
509 0x3f83b2ab6fba4e78,
510 0x3f55d87fe78a84e6,
511 0x3f2430912f86a480,
512 0x3eeffcbfbc1f2b36,
513 0x3eb62c0226c7f6d1,
514 0x3e7b539529819e63,
515 0x3e3e4d552bed5b9c,
516 ];
517 let x2 = x * x;
518 let x4 = x2 * x2;
519 let mut c8 = dd_fmla(f64::from_bits(P[10]), x, f64::from_bits(P[9])); let c6 = dd_fmla(f64::from_bits(P[8]), x, f64::from_bits(P[7])); let mut c4 = dd_fmla(f64::from_bits(P[6]), x, f64::from_bits(P[5])); c8 = dd_fmla(f64::from_bits(P[11]), x2, c8); c4 = dd_fmla(c6, x2, c4); c4 = dd_fmla(c8, x4, c4); let mut p = DoubleDouble::from_exact_mult(c4, x);
527 let p0 = DoubleDouble::from_exact_add(f64::from_bits(P[4]), p.hi);
528 p.lo += p0.lo;
529 p.hi = p0.hi;
530
531 p = DoubleDouble::quick_f64_mult(x, p);
532
533 let p1 = DoubleDouble::from_exact_add(f64::from_bits(P[2]), p.hi);
534 p.lo += p1.lo + f64::from_bits(P[3]);
535 p.hi = p1.hi;
536
537 p = DoubleDouble::quick_f64_mult(x, p);
538 let p2 = DoubleDouble::from_exact_add(f64::from_bits(P[0]), p.hi);
539 p.lo += p2.lo + f64::from_bits(P[1]);
540 p.hi = p2.hi;
541
542 p = DoubleDouble::quick_f64_mult(x, p);
543
544 Exp2m1 {
545 exp: p,
546 err: f64::from_bits(0x3bd4e00000000000) * p.hi, }
548}
549
550pub fn f_exp2m1(d: f64) -> f64 {
554 let mut x = d;
555 let t = x.to_bits();
556 let ux = t;
557 let ax = ux & 0x7fffffffffffffffu64;
558
559 if ux >= 0xc04b000000000000u64 {
560 if (ux >> 52) == 0xfff {
562 return if ux > 0xfff0000000000000u64 {
564 x + x
565 } else {
566 -1.0
567 };
568 }
569 return -1.0 + f64::from_bits(0x3c90000000000000);
571 } else if ax >= 0x4090000000000000u64 {
572 if (ux >> 52) == 0x7ff {
574 return x + x;
576 }
577 return f_fmla(
580 x,
581 f64::from_bits(0x7bffffffffffffff),
582 f64::from_bits(0x7fefffffffffffff),
583 );
584 } else if ax <= 0x3cc0527dbd87e24du64
585 {
590 return if ax <= 0x3970000000000000u64
594 {
596 if x == 0. {
598 return x;
599 }
600 x *= f64::from_bits(0x4690000000000000);
602 let z = DoubleDouble::quick_mult_f64(DoubleDouble::new(LN2L, LN2H), x);
603 let mut h2 = z.to_f64(); h2 *= f64::from_bits(0x3950000000000000);
606 let mut h = dd_fmla(-h2, f64::from_bits(0x4690000000000000), z.hi);
608 h += z.lo;
610 dyad_fmla(h, f64::from_bits(0x3950000000000000), h2)
615 } else {
616 const C2: f64 = f64::from_bits(0x3fcebfbdff82c58f); let mut z = DoubleDouble::from_exact_mult(LN2H, x);
618 z.lo = dyad_fmla(LN2L, x, z.lo);
619 z.lo += C2 * x * x;
623 z.to_f64()
624 };
625 }
626
627 if ux.wrapping_shl(17) == 0 {
632 let i = x.floor_finite() as i32;
633 if x == i as f64 && -53 <= i && i <= 53 {
634 return if i >= 0 {
635 ((1u64 << i) - 1) as f64
636 } else {
637 -1.0 + fast_ldexp(1.0, i)
638 };
639 }
640 }
641
642 let result = exp2m1_fast(x, ax <= 0x3fc0000000000000u64);
643 let left = result.exp.hi + (result.exp.lo - result.err);
644 let right = result.exp.hi + (result.exp.lo + result.err);
645 if left != right {
646 return exp2m1_accurate(x);
647 }
648 left
649}
650
651#[cfg(test)]
652mod tests {
653 use super::*;
654
655 #[test]
656 fn test_exp2m1() {
657 assert_eq!(f_exp2m1(5.4172231599824623E-312), 3.75493295981e-312);
658 assert_eq!(f_exp2m1( 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017800593653177087), 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012338431302992956);
659 assert_eq!(3., f_exp2m1(2.0));
660 assert_eq!(4.656854249492381, f_exp2m1(2.5));
661 assert_eq!(-0.30801352040368324, f_exp2m1(-0.5311842449009418));
662 }
663}