You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: lib/node_modules/@stdlib/math/base/special/log10/lib/main.js
+63-25
Original file line number
Diff line number
Diff line change
@@ -18,7 +18,7 @@
18
18
*
19
19
* ## Notice
20
20
*
21
-
* The following copyright and license were part of the original implementation available as part of [FreeBSD]{@link https://svnweb.freebsd.org/base/release/9.3.0/lib/msun/src/e_log10.c}. The implementation follows the original, but has been modified for JavaScript.
21
+
* The following copyright and license were part of the original implementation available as part of [FreeBSD]{@link https://svnweb.freebsd.org/base/release/12.2.0/lib/msun/src/e_log10.c}. The implementation follows the original, but has been modified for JavaScript.
22
22
*
23
23
* ```text
24
24
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
varHIGH_BIASED_EXP_0=0x3ff00000|0;// asm type annotation
65
65
66
+
// High/low words workspace:
67
+
varWORDS=[0|0,0|0];
68
+
66
69
67
70
// MAIN //
68
71
@@ -97,49 +100,84 @@ var HIGH_BIASED_EXP_0 = 0x3ff00000|0; // asm type annotation
97
100
* // returns NaN
98
101
*/
99
102
functionlog10(x){
103
+
varvalHi;
104
+
varvalLo;
105
+
varhfsq;
100
106
varhi;
101
-
varhx;
102
107
varlo;
108
+
varhx;
109
+
varlx;
110
+
vary2;
103
111
varf;
112
+
varR;
113
+
varw;
114
+
vary;
104
115
vari;
105
116
vark;
106
-
vary;
107
-
varz;
108
117
109
118
if(isnan(x)||x<0.0){
110
119
returnNaN;
111
120
}
112
-
if(x===0.0){
113
-
returnNINF;
114
-
}
115
-
hx=getHighWord(x);
121
+
toWords.assign(x,WORDS,1,0);
122
+
hx=WORDS[0];
123
+
lx=WORDS[1];
116
124
k=0|0;// asm type annotation
117
125
118
-
// Case: 0 < x < 2**-1022
119
126
if(hx<HIGH_MIN_NORMAL_EXP){
120
-
// Subnormal number, scale up `x`...
127
+
// Case: x < 2**-1022
128
+
if(((hx&ABS_MASK)|lx)===0){
129
+
returnNINF;
130
+
}
121
131
k-=54|0;// asm type annotation
132
+
133
+
// Subnormal number, scale up x:
122
134
x*=TWO54;
123
135
hx=getHighWord(x);
124
136
}
125
137
if(hx>=HIGH_MAX_NORMAL_EXP){
126
138
returnx+x;
127
139
}
128
-
k+=((hx>>20)-BIAS)|0;// asm type annotation
140
+
// Case: log(1) = +0
141
+
if(hx===HIGH_BIASED_EXP_0&&lx===0){
142
+
return0.0;
143
+
}
144
+
k+=((hx>>20)-BIAS)|0;// asm type annotation
129
145
hx&=HIGH_SIGNIFICAND_MASK;
130
-
i=((hx+0x95f64)&0x100000)|0;// asm type annotation
146
+
i=((hx+0x95f64)&HIGH_MIN_NORMAL_EXP)|0;// asm type annotation
131
147
132
148
// Normalize `x` or `x/2`...
133
-
x=setHighWord(x,hx|(i^HIGH_BIASED_EXP_0));
134
-
k+=(i>>20)|0;// asm type annotation
149
+
x=setHighWord(x,hx|(i^HIGH_BIASED_EXP_0));
150
+
k+=(i>>20)|0;// asm type annotation
135
151
y=k;
136
-
f=klog(x);
137
-
x-=1;
138
-
hi=setLowWord(x,0.0);
139
-
lo=x-hi;
140
-
z=(y*LOG10_2LO)+((x+f)*IVLN10LO);
141
-
z+=((lo+f)*IVLN10HI)+(hi*IVLN10HI);
142
-
returnz+(y*LOG10_2HI);
152
+
f=x-1.0;
153
+
hfsq=0.5*f*f;
154
+
R=kernelLog1p(f);
155
+
156
+
/*
157
+
* Notes:
158
+
*
159
+
* - `f-hfsq` must (for args near `1`) be evaluated in extra precision to avoid a large cancellation when `x` is near `sqrt(2)` or `1/sqrt(2)`.This is fairly efficient since `f-hfsq` only depends on `f`, so can be evaluated in parallel with `R`. Not combining `hfsq` with `R` also keeps `R` small (though not as small as a true `lo` term would be), so that extra precision is not needed for terms involving `R`.
160
+
* - When implemented in C, compiler bugs involving extra precision used to break Dekker's theorem for spitting `f-hfsq` as `hi+lo`. These problems are now automatically avoided as a side effect of the optimization of combining the Dekker splitting step with the clear-low-bits step.
161
+
* - This implementation uses Dekker's theorem to normalize `y+val_hi`, so, when implemented in C, compiler bugs may reappear in some configurations.
162
+
* - The multi-precision calculations for the multiplications are routine.
* - Extra precision in for adding `y*log10_2hi` is not strictly needed since there is no very large cancellation near `x = sqrt(2)` or `x = 1/sqrt(2)`, but we do it anyway since it costs little on CPUs with some parallelism and it reduces the error for many args.
0 commit comments