Skip to content
This repository was archived by the owner on Apr 28, 2025. It is now read-only.

Commit 66bb51a

Browse files
committed
try to fix #170
Signed-off-by: Benjamin Schultzer <[email protected]>
1 parent fb0547e commit 66bb51a

File tree

2 files changed

+67
-63
lines changed

2 files changed

+67
-63
lines changed

src/math/jnf.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,14 @@ pub fn jnf(n: i32, mut x: f32) -> f32 {
7575
}
7676
temp = 0.5 * x;
7777
b = temp;
78-
a = 1.0;
78+
let mut a = 1;
7979
i = 2;
8080
while i <= nm1 + 1 {
81-
a *= i as f32; /* a = n! */
81+
a *= i; /* a = n! */
8282
b *= temp; /* b = (x/2)^n */
8383
i += 1;
8484
}
85-
b = b / a;
85+
b /= a as f32;
8686
} else {
8787
/* use backward recurrence */
8888
/* x x^2 x^2
@@ -124,7 +124,7 @@ pub fn jnf(n: i32, mut x: f32) -> f32 {
124124
let mut k: i32;
125125

126126
nf = (nm1 as f32) + 1.0;
127-
w = 2.0 * (nf as f32) / x;
127+
w = 2.0 * nf / x;
128128
h = 2.0 / x;
129129
z = w + h;
130130
q0 = w;
@@ -169,10 +169,10 @@ pub fn jnf(n: i32, mut x: f32) -> f32 {
169169
b = 2.0 * (i as f32) * b / x - a;
170170
a = temp;
171171
/* scale b to avoid spurious overflow */
172-
let x1p60 = f32::from_bits(0x5d800000); // 0x1p60 == 2^60
173-
if b > x1p60 {
172+
// let x1p60 = f32::from_bits(0x5d800000); // 0x1p60 == 2^60
173+
if b > 1.152922e+18 {
174174
a /= b;
175-
t /= b;
175+
t = t / b;
176176
b = 1.0;
177177
}
178178
i -= 1;
@@ -182,8 +182,9 @@ pub fn jnf(n: i32, mut x: f32) -> f32 {
182182
w = j1f(x);
183183
if fabsf(z) >= fabsf(w) {
184184
b = t * z / b;
185+
// panic!("{:?} {:?} {:?} {:?} {:?} {:?}", t, z, w, b, f32::from_bits(0x5d800000), 1.152922e+18);
185186
} else {
186-
b = t * w / a;
187+
b = t * (w / a);
187188
}
188189
}
189190
}

src/math/logf.rs

Lines changed: 58 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,69 @@
1-
/* origin: FreeBSD /usr/src/lib/msun/src/e_logf.c */
2-
/*
3-
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
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-
*/
1+
const LOGF_TABLE_BITS: u32 = 4;
2+
const T: [(f64, f64); 16] = [(1.398907162146528e0, -3.3569133332882284e-1),
3+
(1.3403141896637998e0, -2.929040563774074e-1),
4+
(1.286432210124115e0, -2.518726580937369e-1),
5+
(1.2367150214269895e0, -2.1245868807117255e-1),
6+
(1.1906977166711752e0, -1.7453945183745634e-1),
7+
(1.1479821020556429e0, -1.380057072319758e-1),
8+
(1.1082251448272158e0, -1.0275976698545139e-1),
9+
(1.0711297413057381e0, -6.871392447020525e-2),
10+
(1.036437278977283e0, -3.57891387398228e-2),
11+
(1e0, 0e0),
12+
(9.492859795739057e-1, 5.204517742929496e-2),
13+
(8.951049428609004e-1, 1.1081431298787942e-1),
14+
(8.476821620351103e-1, 1.652495223695143e-1),
15+
(8.050314851692001e-1, 2.1687389031699977e-1),
16+
(7.664671008843108e-1, 2.659635028121397e-1),
17+
(7.31428603316328e-1, 3.127556664073557e-1)];
1518

16-
const LN2_HI: f32 = 6.9313812256e-01; /* 0x3f317180 */
17-
const LN2_LO: f32 = 9.0580006145e-06; /* 0x3717f7d1 */
18-
/* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */
19-
const LG1: f32 = 0.66666662693; /* 0xaaaaaa.0p-24*/
20-
const LG2: f32 = 0.40000972152; /* 0xccce13.0p-25 */
21-
const LG3: f32 = 0.28498786688; /* 0x91e9ee.0p-25 */
22-
const LG4: f32 = 0.24279078841; /* 0xf89e26.0p-26 */
19+
const A: [f64; 3] = [-2.5089342214237154e-1, 3.33456765744066e-1, -4.999997485802103e-1];
20+
const LN2: f64 = 6.931471805599453e-1;
21+
const N: u32 = (1 << LOGF_TABLE_BITS);
22+
const OFF: u32 = 0x3f330000;
2323

2424
#[inline]
2525
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
26-
pub fn logf(mut x: f32) -> f32 {
27-
let x1p25 = f32::from_bits(0x4c000000); // 0x1p25f === 2 ^ 25
28-
26+
pub fn logf(x: f32) -> f32 {
2927
let mut ix = x.to_bits();
30-
let mut k = 0i32;
3128

32-
if (ix < 0x00800000) || ((ix >> 31) != 0) {
33-
/* x < 2**-126 */
34-
if ix << 1 == 0 {
35-
return -1. / (x * x); /* log(+-0)=-inf */
36-
}
37-
if (ix >> 31) != 0 {
38-
return (x - x) / 0.; /* log(-#) = NaN */
39-
}
40-
/* subnormal number, scale up x */
41-
k -= 25;
42-
x *= x1p25;
43-
ix = x.to_bits();
44-
} else if ix >= 0x7f800000 {
45-
return x;
46-
} else if ix == 0x3f800000 {
29+
/* Fix sign of zero with downward rounding when x==1. */
30+
if ix == 0x3f800000 {
4731
return 0.;
4832
}
33+
if ix - 0x00800000 >= 0x7f800000 - 0x00800000 {
34+
/* x < 0x1p-126 or inf or nan. */
35+
if ix * 2 == 0 {
36+
return -1. / 0.;
37+
}
38+
if ix == 0x7f800000 { /* log(inf) == inf. */
39+
return x;
40+
}
41+
if (ix & 0x80000000) != 0 || ix * 2 >= 0xff000000 {
42+
return (x - x) / (x - x);
43+
}
44+
/* x is subnormal, normalize it. */
45+
ix = f32::to_bits(x * 8.388608e6);
46+
ix -= 23 << 23;
47+
}
48+
49+
/* x = 2^k z; where z is in range [OFF,2*OFF] and exact.
50+
The range is split into N subintervals.
51+
The ith subinterval contains z and c is near its center. */
52+
let tmp = ix - OFF;
53+
let i = (tmp >> (23 - LOGF_TABLE_BITS)) % N;
54+
let k = tmp as i32 >> 23; /* arithmetic shift */
55+
let iz = ix - (tmp & 0x1ff << 23);
56+
let (invc, logc) = T[i as usize];
57+
let z = f32::from_bits(iz) as f64;
4958

50-
/* reduce x into [sqrt(2)/2, sqrt(2)] */
51-
ix += 0x3f800000 - 0x3f3504f3;
52-
k += ((ix >> 23) as i32) - 0x7f;
53-
ix = (ix & 0x007fffff) + 0x3f3504f3;
54-
x = f32::from_bits(ix);
59+
/* log(x) = log1p(z/c-1) + log(c) + k*Ln2 */
60+
let r = z * invc - 1.;
61+
let y0 = logc + k as f64 * LN2;
5562

56-
let f = x - 1.;
57-
let s = f / (2. + f);
58-
let z = s * s;
59-
let w = z * z;
60-
let t1 = w * (LG2 + w * LG4);
61-
let t2 = z * (LG1 + w * LG3);
62-
let r = t2 + t1;
63-
let hfsq = 0.5 * f * f;
64-
let dk = k as f32;
65-
s * (hfsq + r) + dk * LN2_LO - hfsq + f + dk * LN2_HI
63+
/* Pipelined polynomial evaluation to approximate log1p(r). */
64+
let r2 = r * r;
65+
let mut y = A[1] * r + A[2];
66+
y = A[0] * r2 + y;
67+
y = y * r2 + (y0 + r);
68+
return y as f32;
6669
}

0 commit comments

Comments
 (0)