// origin: FreeBSD /usr/src/lib/msun/src/s_exp2.c */ //- // Copyright (c) 2005 David Schultz <das@FreeBSD.ORG> // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF // SUCH DAMAGE.
// exp2(x): compute the base 2 exponential of x // // Accuracy: Peak error < 0.503 ulp for normalized results. // // Method: (accurate tables) // // Reduce x: // x = k + y, for integer k and |y| <= 1/2. // Thus we have exp2(x) = 2**k * exp2(y). // // Reduce y: // y = i/TBLSIZE + z - eps[i] for integer i near y * TBLSIZE. // Thus we have exp2(y) = exp2(i/TBLSIZE) * exp2(z - eps[i]), // with |z - eps[i]| <= 2**-9 + 2**-39 for the table used. // // We compute exp2(i/TBLSIZE) via table lookup and exp2(z - eps[i]) via // a degree-5 minimax polynomial with maximum error under 1.3 * 2**-61. // The values in exp2t[] and eps[] are chosen such that // exp2t[i] = exp2(i/TBLSIZE + eps[i]), and eps[i] is a small offset such // that exp2t[i] is accurate to 2**-64. // // Note that the range of i is +-TBLSIZE/2, so we actually index the tables // by i0 = i + TBLSIZE/2. For cache efficiency, exp2t[] and eps[] are // virtual tables, interleaved in the real table tbl[]. // // This method is due to Gal, with many details due to Gal and Bachelis: // // Gal, S. and Bachelis, B. An Accurate Elementary Mathematical Library // for the IEEE Floating Point Standard. TOMS 17(1), 26-46 (1991).
/// Exponential, base 2 (f64) /// /// Calculate `2^x`, that is, 2 raised to the power `x`. #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] pubfn exp2(mut x: f64) -> f64 { let redux = f64::from_bits(0x4338000000000000) / TBLSIZE as f64; let p1 = f64::from_bits(0x3fe62e42fefa39ef); let p2 = f64::from_bits(0x3fcebfbdff82c575); let p3 = f64::from_bits(0x3fac6b08d704a0a6); let p4 = f64::from_bits(0x3f83b2ab88f70400); let p5 = f64::from_bits(0x3f55d88003875c74);
// double_t r, t, z; // uint32_t ix, i0; // union {double f; uint64_t i;} u = {x}; // union {uint32_t u; int32_t i;} k; let x1p1023 = f64::from_bits(0x7fe0000000000000); let x1p52 = f64::from_bits(0x4330000000000000); let _0x1p_149 = f64::from_bits(0xb6a0000000000000);
/* Filter out exceptional cases. */ let ui = f64::to_bits(x); let ix = ui >> 32 & 0x7fffffff; if ix >= 0x408ff000 { /* |x| >= 1022 or nan */ if ix >= 0x40900000 && ui >> 63 == 0 { /* x >= 1024 or nan */ /* overflow */
x *= x1p1023; return x;
} if ix >= 0x7ff00000 { /* -inf or -nan */ return -1.0 / x;
} if ui >> 63 != 0 { /* x <= -1022 */ /* underflow */ if x <= -1075.0 || x - x1p52 + x1p52 != x {
force_eval!((_0x1p_149 / x) as f32);
} if x <= -1075.0 { return0.0;
}
}
} elseif ix < 0x3c900000 { /* |x| < 0x1p-54 */ return1.0 + x;
}
/* Reduce x, computing z, i0, and k. */ let ui = f64::to_bits(x + redux); letmut i0 = ui as u32;
i0 = i0.wrapping_add(TBLSIZE as u32 / 2); let ku = i0 / TBLSIZE as u32 * TBLSIZE as u32; let ki = div!(ku as i32, TBLSIZE as i32);
i0 %= TBLSIZE as u32; let uf = f64::from_bits(ui) - redux; letmut z = x - uf;
/* Compute r = exp2(y) = exp2t[i0] * p(z - eps[i]). */ let t = f64::from_bits(i!(TBL, 2 * i0 as usize)); /* exp2t[i0] */
z -= f64::from_bits(i!(TBL, 2 * i0 as usize + 1)); /* eps[i0] */ let r = t + t * z * (p1 + z * (p2 + z * (p3 + z * (p4 + z * p5))));
scalbn(r, ki)
}
#[test] fn i0_wrap_test() { let x = -3.0 / 256.0;
assert_eq!(exp2(x), f64::from_bits(0x3fefbdba3692d514));
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.19 Sekunden
(vorverarbeitet am 2026-06-22)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.