log10 function

double log10(
  1. double x
)

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;
}