log10 function
Implementation
double log10(double x) {
final u = _Union(x);
double hfsq, f, s, z, R, w, t1, t2, dk, y, hi, lo, val_hi, val_lo;
int hx; // unsigned
int k;
hx = u.i >>> 32;
k = 0;
if (hx < 0x00100000 || hx >>> 31 != 0) {
if (u.i << 1 == 0) {
return -1 / (x * x); /* log(+-0)=-inf */
}
if (hx >>> 31 != 0) {
return (x - x) / 0.0; /* log(-#) = NaN */
}
/* subnormal number, scale x up */
k -= 54;
x *= _0x1p54.asDouble();
u.f = x;
hx = u.i >>> 32;
} else if (hx >= 0x7ff00000) {
return x;
} else if (hx == 0x3ff00000 && u.i << 32 == 0) {
return 0;
}
/* reduce x into [sqrt(2)/2, sqrt(2)] */
hx += 0x3ff00000 - 0x3fe6a09e;
k += (hx >>> 20).toInt() - 0x3ff;
hx = (hx & 0x000fffff) + 0x3fe6a09e;
u.i = (hx << 32).toUnsigned(64) | (u.i & 0xffffffff);
x = u.f;
f = x - 1.0;
hfsq = 0.5 * f * f;
s = f / (2.0 + f);
z = s * s;
w = z * z;
t1 = w * (_Lg2 + w * (_Lg4 + w * _Lg6));
t2 = z * (_Lg1 + w * (_Lg3 + w * (_Lg5 + w * _Lg7)));
R = t2 + t1;
/* See log2.c for details. */
/* hi+lo = f - hfsq + s*(hfsq+R) ~ log(1+f) */
hi = f - hfsq;
u.f = hi;
u.i &= (-1 << 32).toUnsigned(64);
hi = u.f;
lo = f - hi - hfsq + s * (hfsq + R);
/* val_hi+val_lo ~ log10(1+f) + k*log10(2) */
val_hi = hi * _ivln10hi;
dk = k.toDouble();
y = dk * _log10_2hi;
val_lo = dk * _log10_2lo + (lo + hi) * _ivln10lo + lo * _ivln10hi;
/*
* Extra precision in for adding y 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.
*/
w = y + val_hi;
val_lo += (y - w) + val_hi;
val_hi = w;
return val_lo + val_hi;
}