Coverage Report

Created: 2025-06-24 07:03

/src/moddable/xs/tools/fdlibm/k_log.h
Line
Count
Source
1
2
/*
3
 * ====================================================
4
 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * Developed at SunSoft, a Sun Microsystems, Inc. business.
7
 * Permission to use, copy, modify, and distribute this
8
 * software is freely granted, provided that this notice 
9
 * is preserved.
10
 * ====================================================
11
 */
12
13
/*
14
 * k_log1p(f):
15
 * Return log(1+f) - f for 1+f in ~[sqrt(2)/2, sqrt(2)].
16
 *
17
 * The following describes the overall strategy for computing
18
 * logarithms in base e.  The argument reduction and adding the final
19
 * term of the polynomial are done by the caller for increased accuracy
20
 * when different bases are used.
21
 *
22
 * Method :                  
23
 *   1. Argument Reduction: find k and f such that 
24
 *      x = 2^k * (1+f), 
25
 *     where  sqrt(2)/2 < 1+f < sqrt(2) .
26
 *
27
 *   2. Approximation of log(1+f).
28
 *  Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
29
 *     = 2s + 2/3 s**3 + 2/5 s**5 + .....,
30
 *         = 2s + s*R
31
 *      We use a special Reme algorithm on [0,0.1716] to generate 
32
 *  a polynomial of degree 14 to approximate R The maximum error 
33
 *  of this polynomial approximation is bounded by 2**-58.45. In
34
 *  other words,
35
 *            2      4      6      8      10      12      14
36
 *      R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s  +Lg6*s  +Lg7*s
37
 *    (the values of Lg1 to Lg7 are listed in the program)
38
 *  and
39
 *      |      2          14          |     -58.45
40
 *      | Lg1*s +...+Lg7*s    -  R(z) | <= 2 
41
 *      |                             |
42
 *  Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
43
 *  In order to guarantee error in log below 1ulp, we compute log
44
 *  by
45
 *    log(1+f) = f - s*(f - R)  (if f is not too large)
46
 *    log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy)
47
 *  
48
 *  3. Finally,  log(x) = k*ln2 + log(1+f).  
49
 *          = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
50
 *     Here ln2 is split into two floating point number: 
51
 *      ln2_hi + ln2_lo,
52
 *     where n*ln2_hi is always exact for |n| < 2000.
53
 *
54
 * Special cases:
55
 *  log(x) is NaN with signal if x < 0 (including -INF) ; 
56
 *  log(+INF) is +INF; log(0) is -INF with signal;
57
 *  log(NaN) is that NaN with no signal.
58
 *
59
 * Accuracy:
60
 *  according to an error analysis, the error is always less than
61
 *  1 ulp (unit in the last place).
62
 *
63
 * Constants:
64
 * The hexadecimal values are the intended ones for the following 
65
 * constants. The decimal values may be used, provided that the 
66
 * compiler will convert from decimal to binary accurately enough 
67
 * to produce the hexadecimal values shown.
68
 */
69
70
static const double
71
Lg1 = 6.666666666666735130e-01,  /* 3FE55555 55555593 */
72
Lg2 = 3.999999999940941908e-01,  /* 3FD99999 9997FA04 */
73
Lg3 = 2.857142874366239149e-01,  /* 3FD24924 94229359 */
74
Lg4 = 2.222219843214978396e-01,  /* 3FCC71C5 1D8E78AF */
75
Lg5 = 1.818357216161805012e-01,  /* 3FC74664 96CB03DE */
76
Lg6 = 1.531383769920937332e-01,  /* 3FC39A09 D078C69F */
77
Lg7 = 1.479819860511658591e-01;  /* 3FC2F112 DF3E5244 */
78
79
/*
80
 * We always inline k_log1p(), since doing so produces a
81
 * substantial performance improvement (~40% on amd64).
82
 */
83
static inline double
84
k_log1p(double f)
85
17
{
86
17
  double hfsq,s,z,R,w,t1,t2;
87
88
17
  s = f/(2.0+f);
89
17
  z = s*s;
90
17
  w = z*z;
91
17
  t1= w*(Lg2+w*(Lg4+w*Lg6));
92
17
  t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7)));
93
17
  R = t2+t1;
94
17
  hfsq=0.5*f*f;
95
17
  return s*(hfsq+R);
96
17
}