Skip to content

Commit aecc1b6

Browse files
committed
Add newlib exp2f
1 parent efcc86b commit aecc1b6

File tree

1 file changed

+29
-126
lines changed

1 file changed

+29
-126
lines changed

Diff for: src/math/exp2f.rs

+29-126
Original file line numberDiff line numberDiff line change
@@ -1,132 +1,35 @@
1-
// origin: FreeBSD /usr/src/lib/msun/src/s_exp2f.c
2-
//-
3-
// Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
4-
// All rights reserved.
5-
//
6-
// Redistribution and use in source and binary forms, with or without
7-
// modification, are permitted provided that the following conditions
8-
// are met:
9-
// 1. Redistributions of source code must retain the above copyright
10-
// notice, this list of conditions and the following disclaimer.
11-
// 2. Redistributions in binary form must reproduce the above copyright
12-
// notice, this list of conditions and the following disclaimer in the
13-
// documentation and/or other materials provided with the distribution.
14-
//
15-
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16-
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17-
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18-
// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19-
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20-
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21-
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22-
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23-
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24-
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25-
// SUCH DAMAGE.
26-
27-
const TBLSIZE: usize = 16;
28-
29-
static EXP2FT: [u64; TBLSIZE] = [
30-
0x3fe6a09e667f3bcd,
31-
0x3fe7a11473eb0187,
32-
0x3fe8ace5422aa0db,
33-
0x3fe9c49182a3f090,
34-
0x3feae89f995ad3ad,
35-
0x3fec199bdd85529c,
36-
0x3fed5818dcfba487,
37-
0x3feea4afa2a490da,
38-
0x3ff0000000000000,
39-
0x3ff0b5586cf9890f,
40-
0x3ff172b83c7d517b,
41-
0x3ff2387a6e756238,
42-
0x3ff306fe0a31b715,
43-
0x3ff3dea64c123422,
44-
0x3ff4bfdad5362a27,
45-
0x3ff5ab07dd485429,
46-
];
47-
48-
// exp2f(x): compute the base 2 exponential of x
49-
//
50-
// Accuracy: Peak error < 0.501 ulp; location of peak: -0.030110927.
51-
//
52-
// Method: (equally-spaced tables)
53-
//
54-
// Reduce x:
55-
// x = k + y, for integer k and |y| <= 1/2.
56-
// Thus we have exp2f(x) = 2**k * exp2(y).
57-
//
58-
// Reduce y:
59-
// y = i/TBLSIZE + z for integer i near y * TBLSIZE.
60-
// Thus we have exp2(y) = exp2(i/TBLSIZE) * exp2(z),
61-
// with |z| <= 2**-(TBLSIZE+1).
62-
//
63-
// We compute exp2(i/TBLSIZE) via table lookup and exp2(z) via a
64-
// degree-4 minimax polynomial with maximum error under 1.4 * 2**-33.
65-
// Using double precision for everything except the reduction makes
66-
// roundoff error insignificant and simplifies the scaling step.
67-
//
68-
// This method is due to Tang, but I do not use his suggested parameters:
69-
//
70-
// Tang, P. Table-driven Implementation of the Exponential Function
71-
// in IEEE Floating-Point Arithmetic. TOMS 15(2), 144-157 (1989).
1+
/* wf_exp2.c -- float version of w_exp2.c.
2+
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
3+
*/
4+
5+
/*
6+
* ====================================================
7+
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
8+
*
9+
* Developed at SunPro, a Sun Microsystems, Inc. business.
10+
* Permission to use, copy, modify, and distribute this
11+
* software is freely granted, provided that this notice
12+
* is preserved.
13+
* ====================================================
14+
*/
15+
16+
use super::powf;
17+
18+
/// Exponential, base 2 (f32)
19+
///
20+
/// Calculate `2^x`, that is, 2 raised to the power `x`.
7221
#[inline]
7322
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
74-
pub fn exp2f(mut x: f32) -> f32 {
75-
let redux = f32::from_bits(0x4b400000) / TBLSIZE as f32;
76-
let p1 = f32::from_bits(0x3f317218);
77-
let p2 = f32::from_bits(0x3e75fdf0);
78-
let p3 = f32::from_bits(0x3d6359a4);
79-
let p4 = f32::from_bits(0x3c1d964e);
80-
81-
// double_t t, r, z;
82-
// uint32_t ix, i0, k;
83-
84-
let x1p127 = f32::from_bits(0x7f000000);
23+
pub fn exp2f(x: f32) -> f32 {
24+
powf(2f32, x)
25+
}
8526

86-
/* Filter out exceptional cases. */
87-
let ui = f32::to_bits(x);
88-
let ix = ui & 0x7fffffff;
89-
if ix > 0x42fc0000 {
90-
/* |x| > 126 */
91-
if ix > 0x7f800000 {
92-
/* NaN */
93-
return x;
94-
}
95-
if ui >= 0x43000000 && ui < 0x80000000 {
96-
/* x >= 128 */
97-
x *= x1p127;
98-
return x;
99-
}
100-
if ui >= 0x80000000 {
101-
/* x < -126 */
102-
if ui >= 0xc3160000 || (ui & 0x0000ffff != 0) {
103-
force_eval!(f32::from_bits(0x80000001) / x);
104-
}
105-
if ui >= 0xc3160000 {
106-
/* x <= -150 */
107-
return 0.0;
108-
}
109-
}
110-
} else if ix <= 0x33000000 {
111-
/* |x| <= 0x1p-25 */
112-
return 1.0 + x;
27+
#[cfg(test)]
28+
mod tests {
29+
#[test]
30+
fn sanity_check() {
31+
assert_eq!(super::exp2f(1.1), 2.143547);
11332
}
33+
}
11434

115-
/* Reduce x, computing z, i0, and k. */
116-
let ui = f32::to_bits(x + redux);
117-
let mut i0 = ui;
118-
i0 += TBLSIZE as u32 / 2;
119-
let k = i0 / TBLSIZE as u32;
120-
let ukf = f64::from_bits(((0x3ff + k) as u64) << 52);
121-
i0 &= TBLSIZE as u32 - 1;
122-
let mut uf = f32::from_bits(ui);
123-
uf -= redux;
124-
let z: f64 = (x - uf) as f64;
125-
/* Compute r = exp2(y) = exp2ft[i0] * p(z). */
126-
let r: f64 = f64::from_bits(EXP2FT[i0 as usize]);
127-
let t: f64 = r as f64 * z;
128-
let r: f64 = r + t * (p1 as f64 + z * p2 as f64) + t * (z * z) * (p3 as f64 + z * p4 as f64);
12935

130-
/* Scale by 2**k */
131-
(r * ukf) as f32
132-
}

0 commit comments

Comments
 (0)