/* Copyright JS Foundation and other contributors, http://js.foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is based on work under the following copyright and permission * notice: * * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * * @(#)e_log10.c 1.3 95/01/18 */ #include "jerry-libm-internal.h" /* log10(x) * Return the base 10 logarithm of x * * Method : * Let log10_2hi = leading 40 bits of log10(2) and * log10_2lo = log10(2) - log10_2hi, * ivln10 = 1/log(10) rounded. * Then * n = ilogb(x), * if(n<0) n = n+1; * x = scalbn(x,-n); * log10(x) := n*log10_2hi + (n*log10_2lo + ivln10*log(x)) * * Note 1: * To guarantee log10(10**n)=n, where 10**n is normal, the rounding * mode must set to Round-to-Nearest. * Note 2: * [1/log(10)] rounded to 53 bits has error .198 ulps; * log10 is monotonic at all binary break points. * * Special cases: * log10(x) is NaN with signal if x < 0; * log10(+INF) is +INF with no signal; log10(0) is -INF with signal; * log10(NaN) is that NaN with no signal; * log10(10**N) = N for N=0,1,...,22. * * Constants: * The hexadecimal values are the intended ones for the following constants. * The decimal values may be used, provided that the compiler will convert * from decimal to binary accurately enough to produce the hexadecimal values * shown. */ #define zero 0.0 #define two54 1.80143985094819840000e+16 /* 0x43500000, 0x00000000 */ #define ivln10 4.34294481903251816668e-01 /* 0x3FDBCB7B, 0x1526E50E */ #define log10_2hi 3.01029995663611771306e-01 /* 0x3FD34413, 0x509F6000 */ #define log10_2lo 3.69423907715893078616e-13 /* 0x3D59FEF3, 0x11F12B36 */ double log10 (double x) { double y, z; int i, k, hx; unsigned lx; double_accessor temp; hx = __HI (x); /* high word of x */ lx = __LO (x); /* low word of x */ k = 0; if (hx < 0x00100000) { /* x < 2**-1022 */ if (((hx & 0x7fffffff) | lx) == 0) { /* log(+-0)=-inf */ return -two54 / zero; } if (hx < 0) { /* log(-#) = NaN */ return (x - x) / zero; } k -= 54; x *= two54; /* subnormal number, scale up x */ hx = __HI (x); /* high word of x */ } if (hx >= 0x7ff00000) { return x + x; } k += (hx >> 20) - 1023; i = ((unsigned) k & 0x80000000) >> 31; hx = (hx & 0x000fffff) | ((0x3ff - i) << 20); y = (double) (k + i); temp.dbl = x; temp.as_int.hi = hx; z = y * log10_2lo + ivln10 * log (temp.dbl); return z + y * log10_2hi; } /* log10 */ #undef zero #undef two54 #undef ivln10 #undef log10_2hi #undef log10_2lo