Removed the last vestiges of libm. These have been repo-copied to

msun/bsdsrc.  Everything except true gamma() and its support functions
was superseded by msun long ago, at least on IEEE machines.
This commit is contained in:
Bruce Evans 2002-03-21 11:33:50 +00:00
parent 6720311838
commit 4bcae9ff30
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=92873
5 changed files with 0 additions and 1139 deletions

View File

@ -1,7 +0,0 @@
$FreeBSD$
The libm library has been superceded by the msun library. The
source has not been delegated to the attic yet because there are
still bits that need to be merged into msun.
(end)

View File

@ -1,206 +0,0 @@
/*
* Copyright (c) 1985, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#ifndef lint
static char sccsid[] = "@(#)exp.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint */
/* EXP(X)
* RETURN THE EXPONENTIAL OF X
* DOUBLE PRECISION (IEEE 53 bits, VAX D FORMAT 56 BITS)
* CODED IN C BY K.C. NG, 1/19/85;
* REVISED BY K.C. NG on 2/6/85, 2/15/85, 3/7/85, 3/24/85, 4/16/85, 6/14/86.
*
* Required system supported functions:
* scalb(x,n)
* copysign(x,y)
* finite(x)
*
* Method:
* 1. Argument Reduction: given the input x, find r and integer k such
* that
* x = k*ln2 + r, |r| <= 0.5*ln2 .
* r will be represented as r := z+c for better accuracy.
*
* 2. Compute exp(r) by
*
* exp(r) = 1 + r + r*R1/(2-R1),
* where
* R1 = x - x^2*(p1+x^2*(p2+x^2*(p3+x^2*(p4+p5*x^2)))).
*
* 3. exp(x) = 2^k * exp(r) .
*
* Special cases:
* exp(INF) is INF, exp(NaN) is NaN;
* exp(-INF)= 0;
* for finite argument, only exp(0)=1 is exact.
*
* Accuracy:
* exp(x) returns the exponential of x nearly rounded. In a test run
* with 1,156,000 random arguments on a VAX, the maximum observed
* error was 0.869 ulps (units in the last place).
*
* 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.
*/
#include "mathimpl.h"
vc(ln2hi, 6.9314718055829871446E-1 ,7217,4031,0000,f7d0, 0, .B17217F7D00000)
vc(ln2lo, 1.6465949582897081279E-12 ,bcd5,2ce7,d9cc,e4f1, -39, .E7BCD5E4F1D9CC)
vc(lnhuge, 9.4961163736712506989E1 ,ec1d,43bd,9010,a73e, 7, .BDEC1DA73E9010)
vc(lntiny,-9.5654310917272452386E1 ,4f01,c3bf,33af,d72e, 7,-.BF4F01D72E33AF)
vc(invln2, 1.4426950408889634148E0 ,aa3b,40b8,17f1,295c, 1, .B8AA3B295C17F1)
vc(p1, 1.6666666666666602251E-1 ,aaaa,3f2a,a9f1,aaaa, -2, .AAAAAAAAAAA9F1)
vc(p2, -2.7777777777015591216E-3 ,0b60,bc36,ec94,b5f5, -8,-.B60B60B5F5EC94)
vc(p3, 6.6137563214379341918E-5 ,b355,398a,f15f,792e, -13, .8AB355792EF15F)
vc(p4, -1.6533902205465250480E-6 ,ea0e,b6dd,5f84,2e93, -19,-.DDEA0E2E935F84)
vc(p5, 4.1381367970572387085E-8 ,bb4b,3431,2683,95f5, -24, .B1BB4B95F52683)
#ifdef vccast
#define ln2hi vccast(ln2hi)
#define ln2lo vccast(ln2lo)
#define lnhuge vccast(lnhuge)
#define lntiny vccast(lntiny)
#define invln2 vccast(invln2)
#define p1 vccast(p1)
#define p2 vccast(p2)
#define p3 vccast(p3)
#define p4 vccast(p4)
#define p5 vccast(p5)
#endif
ic(p1, 1.6666666666666601904E-1, -3, 1.555555555553E)
ic(p2, -2.7777777777015593384E-3, -9, -1.6C16C16BEBD93)
ic(p3, 6.6137563214379343612E-5, -14, 1.1566AAF25DE2C)
ic(p4, -1.6533902205465251539E-6, -20, -1.BBD41C5D26BF1)
ic(p5, 4.1381367970572384604E-8, -25, 1.6376972BEA4D0)
ic(ln2hi, 6.9314718036912381649E-1, -1, 1.62E42FEE00000)
ic(ln2lo, 1.9082149292705877000E-10,-33, 1.A39EF35793C76)
ic(lnhuge, 7.1602103751842355450E2, 9, 1.6602B15B7ECF2)
ic(lntiny,-7.5137154372698068983E2, 9, -1.77AF8EBEAE354)
ic(invln2, 1.4426950408889633870E0, 0, 1.71547652B82FE)
double exp(x)
double x;
{
double z,hi,lo,c;
int k;
#if !defined(vax)&&!defined(tahoe)
if(x!=x) return(x); /* x is NaN */
#endif /* !defined(vax)&&!defined(tahoe) */
if( x <= lnhuge ) {
if( x >= lntiny ) {
/* argument reduction : x --> x - k*ln2 */
k=invln2*x+copysign(0.5,x); /* k=NINT(x/ln2) */
/* express x-k*ln2 as hi-lo and let x=hi-lo rounded */
hi=x-k*ln2hi;
x=hi-(lo=k*ln2lo);
/* return 2^k*[1+x+x*c/(2+c)] */
z=x*x;
c= x - z*(p1+z*(p2+z*(p3+z*(p4+z*p5))));
return scalb(1.0+(hi-(lo-(x*c)/(2.0-c))),k);
}
/* end of x > lntiny */
else
/* exp(-big#) underflows to zero */
if(finite(x)) return(scalb(1.0,-5000));
/* exp(-INF) is zero */
else return(0.0);
}
/* end of x < lnhuge */
else
/* exp(INF) is INF, exp(+big#) overflows to INF */
return( finite(x) ? scalb(1.0,5000) : x);
}
/* returns exp(r = x + c) for |c| < |x| with no overlap. */
double __exp__D(x, c)
double x, c;
{
double z,hi,lo, t;
int k;
#if !defined(vax)&&!defined(tahoe)
if (x!=x) return(x); /* x is NaN */
#endif /* !defined(vax)&&!defined(tahoe) */
if ( x <= lnhuge ) {
if ( x >= lntiny ) {
/* argument reduction : x --> x - k*ln2 */
z = invln2*x;
k = z + copysign(.5, x);
/* express (x+c)-k*ln2 as hi-lo and let x=hi-lo rounded */
hi=(x-k*ln2hi); /* Exact. */
x= hi - (lo = k*ln2lo-c);
/* return 2^k*[1+x+x*c/(2+c)] */
z=x*x;
c= x - z*(p1+z*(p2+z*(p3+z*(p4+z*p5))));
c = (x*c)/(2.0-c);
return scalb(1.+(hi-(lo - c)), k);
}
/* end of x > lntiny */
else
/* exp(-big#) underflows to zero */
if(finite(x)) return(scalb(1.0,-5000));
/* exp(-INF) is zero */
else return(0.0);
}
/* end of x < lnhuge */
else
/* exp(INF) is INF, exp(+big#) overflows to INF */
return( finite(x) ? scalb(1.0,5000) : x);
}

View File

@ -1,339 +0,0 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#ifndef lint
static char sccsid[] = "@(#)gamma.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint */
/*
* This code by P. McIlroy, Oct 1992;
*
* The financial support of UUNET Communications Services is greatfully
* acknowledged.
*/
#include <math.h>
#include "mathimpl.h"
#include <errno.h>
/* METHOD:
* x < 0: Use reflection formula, G(x) = pi/(sin(pi*x)*x*G(x))
* At negative integers, return +Inf, and set errno.
*
* x < 6.5:
* Use argument reduction G(x+1) = xG(x) to reach the
* range [1.066124,2.066124]. Use a rational
* approximation centered at the minimum (x0+1) to
* ensure monotonicity.
*
* x >= 6.5: Use the asymptotic approximation (Stirling's formula)
* adjusted for equal-ripples:
*
* log(G(x)) ~= (x-.5)*(log(x)-1) + .5(log(2*pi)-1) + 1/x*P(1/(x*x))
*
* Keep extra precision in multiplying (x-.5)(log(x)-1), to
* avoid premature round-off.
*
* Special values:
* non-positive integer: Set overflow trap; return +Inf;
* x > 171.63: Set overflow trap; return +Inf;
* NaN: Set invalid trap; return NaN
*
* Accuracy: Gamma(x) is accurate to within
* x > 0: error provably < 0.9ulp.
* Maximum observed in 1,000,000 trials was .87ulp.
* x < 0:
* Maximum observed error < 4ulp in 1,000,000 trials.
*/
static double neg_gam __P((double));
static double small_gam __P((double));
static double smaller_gam __P((double));
static struct Double large_gam __P((double));
static struct Double ratfun_gam __P((double, double));
/*
* Rational approximation, A0 + x*x*P(x)/Q(x), on the interval
* [1.066.., 2.066..] accurate to 4.25e-19.
*/
#define LEFT -.3955078125 /* left boundary for rat. approx */
#define x0 .461632144968362356785 /* xmin - 1 */
#define a0_hi 0.88560319441088874992
#define a0_lo -.00000000000000004996427036469019695
#define P0 6.21389571821820863029017800727e-01
#define P1 2.65757198651533466104979197553e-01
#define P2 5.53859446429917461063308081748e-03
#define P3 1.38456698304096573887145282811e-03
#define P4 2.40659950032711365819348969808e-03
#define Q0 1.45019531250000000000000000000e+00
#define Q1 1.06258521948016171343454061571e+00
#define Q2 -2.07474561943859936441469926649e-01
#define Q3 -1.46734131782005422506287573015e-01
#define Q4 3.07878176156175520361557573779e-02
#define Q5 5.12449347980666221336054633184e-03
#define Q6 -1.76012741431666995019222898833e-03
#define Q7 9.35021023573788935372153030556e-05
#define Q8 6.13275507472443958924745652239e-06
/*
* Constants for large x approximation (x in [6, Inf])
* (Accurate to 2.8*10^-19 absolute)
*/
#define lns2pi_hi 0.418945312500000
#define lns2pi_lo -.000006779295327258219670263595
#define Pa0 8.33333333333333148296162562474e-02
#define Pa1 -2.77777777774548123579378966497e-03
#define Pa2 7.93650778754435631476282786423e-04
#define Pa3 -5.95235082566672847950717262222e-04
#define Pa4 8.41428560346653702135821806252e-04
#define Pa5 -1.89773526463879200348872089421e-03
#define Pa6 5.69394463439411649408050664078e-03
#define Pa7 -1.44705562421428915453880392761e-02
static const double zero = 0., one = 1.0, tiny = 1e-300;
static int endian;
/*
* TRUNC sets trailing bits in a floating-point number to zero.
* is a temporary variable.
*/
#if defined(vax) || defined(tahoe)
#define _IEEE 0
#define TRUNC(x) x = (double) (float) (x)
#else
#define _IEEE 1
#define TRUNC(x) *(((int *) &x) + endian) &= 0xf8000000
#define infnan(x) 0.0
#endif
double
gamma(x)
double x;
{
struct Double u;
endian = (*(int *) &one) ? 1 : 0;
if (x >= 6) {
if(x > 171.63)
return(one/zero);
u = large_gam(x);
return(__exp__D(u.a, u.b));
} else if (x >= 1.0 + LEFT + x0)
return (small_gam(x));
else if (x > 1.e-17)
return (smaller_gam(x));
else if (x > -1.e-17) {
if (x == 0.0)
if (!_IEEE) return (infnan(ERANGE));
else return (one/x);
one+1e-20; /* Raise inexact flag. */
return (one/x);
} else if (!finite(x)) {
if (_IEEE) /* x = NaN, -Inf */
return (x*x);
else
return (infnan(EDOM));
} else
return (neg_gam(x));
}
/*
* Accurate to max(ulp(1/128) absolute, 2^-66 relative) error.
*/
static struct Double
large_gam(x)
double x;
{
double z, p;
int i;
struct Double t, u, v;
z = one/(x*x);
p = Pa0+z*(Pa1+z*(Pa2+z*(Pa3+z*(Pa4+z*(Pa5+z*(Pa6+z*Pa7))))));
p = p/x;
u = __log__D(x);
u.a -= one;
v.a = (x -= .5);
TRUNC(v.a);
v.b = x - v.a;
t.a = v.a*u.a; /* t = (x-.5)*(log(x)-1) */
t.b = v.b*u.a + x*u.b;
/* return t.a + t.b + lns2pi_hi + lns2pi_lo + p */
t.b += lns2pi_lo; t.b += p;
u.a = lns2pi_hi + t.b; u.a += t.a;
u.b = t.a - u.a;
u.b += lns2pi_hi; u.b += t.b;
return (u);
}
/*
* Good to < 1 ulp. (provably .90 ulp; .87 ulp on 1,000,000 runs.)
* It also has correct monotonicity.
*/
static double
small_gam(x)
double x;
{
double y, ym1, t, x1;
struct Double yy, r;
y = x - one;
ym1 = y - one;
if (y <= 1.0 + (LEFT + x0)) {
yy = ratfun_gam(y - x0, 0);
return (yy.a + yy.b);
}
r.a = y;
TRUNC(r.a);
yy.a = r.a - one;
y = ym1;
yy.b = r.b = y - yy.a;
/* Argument reduction: G(x+1) = x*G(x) */
for (ym1 = y-one; ym1 > LEFT + x0; y = ym1--, yy.a--) {
t = r.a*yy.a;
r.b = r.a*yy.b + y*r.b;
r.a = t;
TRUNC(r.a);
r.b += (t - r.a);
}
/* Return r*gamma(y). */
yy = ratfun_gam(y - x0, 0);
y = r.b*(yy.a + yy.b) + r.a*yy.b;
y += yy.a*r.a;
return (y);
}
/*
* Good on (0, 1+x0+LEFT]. Accurate to 1ulp.
*/
static double
smaller_gam(x)
double x;
{
double t, d;
struct Double r, xx;
if (x < x0 + LEFT) {
t = x, TRUNC(t);
d = (t+x)*(x-t);
t *= t;
xx.a = (t + x), TRUNC(xx.a);
xx.b = x - xx.a; xx.b += t; xx.b += d;
t = (one-x0); t += x;
d = (one-x0); d -= t; d += x;
x = xx.a + xx.b;
} else {
xx.a = x, TRUNC(xx.a);
xx.b = x - xx.a;
t = x - x0;
d = (-x0 -t); d += x;
}
r = ratfun_gam(t, d);
d = r.a/x, TRUNC(d);
r.a -= d*xx.a; r.a -= d*xx.b; r.a += r.b;
return (d + r.a/x);
}
/*
* returns (z+c)^2 * P(z)/Q(z) + a0
*/
static struct Double
ratfun_gam(z, c)
double z, c;
{
int i;
double p, q;
struct Double r, t;
q = Q0 +z*(Q1+z*(Q2+z*(Q3+z*(Q4+z*(Q5+z*(Q6+z*(Q7+z*Q8)))))));
p = P0 + z*(P1 + z*(P2 + z*(P3 + z*P4)));
/* return r.a + r.b = a0 + (z+c)^2*p/q, with r.a truncated to 26 bits. */
p = p/q;
t.a = z, TRUNC(t.a); /* t ~= z + c */
t.b = (z - t.a) + c;
t.b *= (t.a + z);
q = (t.a *= t.a); /* t = (z+c)^2 */
TRUNC(t.a);
t.b += (q - t.a);
r.a = p, TRUNC(r.a); /* r = P/Q */
r.b = p - r.a;
t.b = t.b*p + t.a*r.b + a0_lo;
t.a *= r.a; /* t = (z+c)^2*(P/Q) */
r.a = t.a + a0_hi, TRUNC(r.a);
r.b = ((a0_hi-r.a) + t.a) + t.b;
return (r); /* r = a0 + t */
}
static double
neg_gam(x)
double x;
{
int sgn = 1;
struct Double lg, lsine;
double y, z;
y = floor(x + .5);
if (y == x) /* Negative integer. */
if(!_IEEE)
return (infnan(ERANGE));
else
return (one/zero);
z = fabs(x - y);
y = .5*ceil(x);
if (y == ceil(y))
sgn = -1;
if (z < .25)
z = sin(M_PI*z);
else
z = cos(M_PI*(0.5-z));
/* Special case: G(1-x) = Inf; G(x) may be nonzero. */
if (x < -170) {
if (x < -190)
return ((double)sgn*tiny*tiny);
y = one - x; /* exact: 128 < |x| < 255 */
lg = large_gam(y);
lsine = __log__D(M_PI/z); /* = TRUNC(log(u)) + small */
lg.a -= lsine.a; /* exact (opposite signs) */
lg.b -= lsine.b;
y = -(lg.a + lg.b);
z = (y + lg.a) + lg.b;
y = __exp__D(y, z);
if (sgn < 0) y = -y;
return (y);
}
y = one-x;
if (one-y == x)
y = gamma(y);
else /* 1-x is inexact */
y = -x*gamma(-x);
if (sgn < 0) y = -y;
return (M_PI / (y*z));
}

View File

@ -1,489 +0,0 @@
/*
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#ifndef lint
static char sccsid[] = "@(#)log.c 8.2 (Berkeley) 11/30/93";
#endif /* not lint */
#include <math.h>
#include <errno.h>
#include "mathimpl.h"
/* Table-driven natural logarithm.
*
* This code was derived, with minor modifications, from:
* Peter Tang, "Table-Driven Implementation of the
* Logarithm in IEEE Floating-Point arithmetic." ACM Trans.
* Math Software, vol 16. no 4, pp 378-400, Dec 1990).
*
* Calculates log(2^m*F*(1+f/F)), |f/j| <= 1/256,
* where F = j/128 for j an integer in [0, 128].
*
* log(2^m) = log2_hi*m + log2_tail*m
* since m is an integer, the dominant term is exact.
* m has at most 10 digits (for subnormal numbers),
* and log2_hi has 11 trailing zero bits.
*
* log(F) = logF_hi[j] + logF_lo[j] is in tabular form in log_table.h
* logF_hi[] + 512 is exact.
*
* log(1+f/F) = 2*f/(2*F + f) + 1/12 * (2*f/(2*F + f))**3 + ...
* the leading term is calculated to extra precision in two
* parts, the larger of which adds exactly to the dominant
* m and F terms.
* There are two cases:
* 1. when m, j are non-zero (m | j), use absolute
* precision for the leading term.
* 2. when m = j = 0, |1-x| < 1/256, and log(x) ~= (x-1).
* In this case, use a relative precision of 24 bits.
* (This is done differently in the original paper)
*
* Special cases:
* 0 return signalling -Inf
* neg return signalling NaN
* +Inf return +Inf
*/
#if defined(vax) || defined(tahoe)
#define _IEEE 0
#define TRUNC(x) x = (double) (float) (x)
#else
#define _IEEE 1
#define endian (((*(int *) &one)) ? 1 : 0)
#define TRUNC(x) *(((int *) &x) + endian) &= 0xf8000000
#define infnan(x) 0.0
#endif
#define N 128
/* Table of log(Fj) = logF_head[j] + logF_tail[j], for Fj = 1+j/128.
* Used for generation of extend precision logarithms.
* The constant 35184372088832 is 2^45, so the divide is exact.
* It ensures correct reading of logF_head, even for inaccurate
* decimal-to-binary conversion routines. (Everybody gets the
* right answer for integers less than 2^53.)
* Values for log(F) were generated using error < 10^-57 absolute
* with the bc -l package.
*/
static double A1 = .08333333333333178827;
static double A2 = .01250000000377174923;
static double A3 = .002232139987919447809;
static double A4 = .0004348877777076145742;
static double logF_head[N+1] = {
0.,
.007782140442060381246,
.015504186535963526694,
.023167059281547608406,
.030771658666765233647,
.038318864302141264488,
.045809536031242714670,
.053244514518837604555,
.060624621816486978786,
.067950661908525944454,
.075223421237524235039,
.082443669210988446138,
.089612158689760690322,
.096729626458454731618,
.103796793681567578460,
.110814366340264314203,
.117783035656430001836,
.124703478501032805070,
.131576357788617315236,
.138402322859292326029,
.145182009844575077295,
.151916042025732167530,
.158605030176659056451,
.165249572895390883786,
.171850256926518341060,
.178407657472689606947,
.184922338493834104156,
.191394852999565046047,
.197825743329758552135,
.204215541428766300668,
.210564769107350002741,
.216873938300523150246,
.223143551314024080056,
.229374101064877322642,
.235566071312860003672,
.241719936886966024758,
.247836163904594286577,
.253915209980732470285,
.259957524436686071567,
.265963548496984003577,
.271933715484010463114,
.277868451003087102435,
.283768173130738432519,
.289633292582948342896,
.295464212893421063199,
.301261330578199704177,
.307025035294827830512,
.312755710004239517729,
.318453731118097493890,
.324119468654316733591,
.329753286372579168528,
.335355541920762334484,
.340926586970454081892,
.346466767346100823488,
.351976423156884266063,
.357455888922231679316,
.362905493689140712376,
.368325561158599157352,
.373716409793814818840,
.379078352934811846353,
.384411698910298582632,
.389716751140440464951,
.394993808240542421117,
.400243164127459749579,
.405465108107819105498,
.410659924985338875558,
.415827895143593195825,
.420969294644237379543,
.426084395310681429691,
.431173464818130014464,
.436236766774527495726,
.441274560805140936281,
.446287102628048160113,
.451274644139630254358,
.456237433481874177232,
.461175715122408291790,
.466089729924533457960,
.470979715219073113985,
.475845904869856894947,
.480688529345570714212,
.485507815781602403149,
.490303988045525329653,
.495077266798034543171,
.499827869556611403822,
.504556010751912253908,
.509261901790523552335,
.513945751101346104405,
.518607764208354637958,
.523248143765158602036,
.527867089620485785417,
.532464798869114019908,
.537041465897345915436,
.541597282432121573947,
.546132437597407260909,
.550647117952394182793,
.555141507540611200965,
.559615787935399566777,
.564070138285387656651,
.568504735352689749561,
.572919753562018740922,
.577315365035246941260,
.581691739635061821900,
.586049045003164792433,
.590387446602107957005,
.594707107746216934174,
.599008189645246602594,
.603290851438941899687,
.607555250224322662688,
.611801541106615331955,
.616029877215623855590,
.620240409751204424537,
.624433288012369303032,
.628608659422752680256,
.632766669570628437213,
.636907462236194987781,
.641031179420679109171,
.645137961373620782978,
.649227946625615004450,
.653301272011958644725,
.657358072709030238911,
.661398482245203922502,
.665422632544505177065,
.669430653942981734871,
.673422675212350441142,
.677398823590920073911,
.681359224807238206267,
.685304003098281100392,
.689233281238557538017,
.693147180560117703862
};
static double logF_tail[N+1] = {
0.,
-.00000000000000543229938420049,
.00000000000000172745674997061,
-.00000000000001323017818229233,
-.00000000000001154527628289872,
-.00000000000000466529469958300,
.00000000000005148849572685810,
-.00000000000002532168943117445,
-.00000000000005213620639136504,
-.00000000000001819506003016881,
.00000000000006329065958724544,
.00000000000008614512936087814,
-.00000000000007355770219435028,
.00000000000009638067658552277,
.00000000000007598636597194141,
.00000000000002579999128306990,
-.00000000000004654729747598444,
-.00000000000007556920687451336,
.00000000000010195735223708472,
-.00000000000017319034406422306,
-.00000000000007718001336828098,
.00000000000010980754099855238,
-.00000000000002047235780046195,
-.00000000000008372091099235912,
.00000000000014088127937111135,
.00000000000012869017157588257,
.00000000000017788850778198106,
.00000000000006440856150696891,
.00000000000016132822667240822,
-.00000000000007540916511956188,
-.00000000000000036507188831790,
.00000000000009120937249914984,
.00000000000018567570959796010,
-.00000000000003149265065191483,
-.00000000000009309459495196889,
.00000000000017914338601329117,
-.00000000000001302979717330866,
.00000000000023097385217586939,
.00000000000023999540484211737,
.00000000000015393776174455408,
-.00000000000036870428315837678,
.00000000000036920375082080089,
-.00000000000009383417223663699,
.00000000000009433398189512690,
.00000000000041481318704258568,
-.00000000000003792316480209314,
.00000000000008403156304792424,
-.00000000000034262934348285429,
.00000000000043712191957429145,
-.00000000000010475750058776541,
-.00000000000011118671389559323,
.00000000000037549577257259853,
.00000000000013912841212197565,
.00000000000010775743037572640,
.00000000000029391859187648000,
-.00000000000042790509060060774,
.00000000000022774076114039555,
.00000000000010849569622967912,
-.00000000000023073801945705758,
.00000000000015761203773969435,
.00000000000003345710269544082,
-.00000000000041525158063436123,
.00000000000032655698896907146,
-.00000000000044704265010452446,
.00000000000034527647952039772,
-.00000000000007048962392109746,
.00000000000011776978751369214,
-.00000000000010774341461609578,
.00000000000021863343293215910,
.00000000000024132639491333131,
.00000000000039057462209830700,
-.00000000000026570679203560751,
.00000000000037135141919592021,
-.00000000000017166921336082431,
-.00000000000028658285157914353,
-.00000000000023812542263446809,
.00000000000006576659768580062,
-.00000000000028210143846181267,
.00000000000010701931762114254,
.00000000000018119346366441110,
.00000000000009840465278232627,
-.00000000000033149150282752542,
-.00000000000018302857356041668,
-.00000000000016207400156744949,
.00000000000048303314949553201,
-.00000000000071560553172382115,
.00000000000088821239518571855,
-.00000000000030900580513238244,
-.00000000000061076551972851496,
.00000000000035659969663347830,
.00000000000035782396591276383,
-.00000000000046226087001544578,
.00000000000062279762917225156,
.00000000000072838947272065741,
.00000000000026809646615211673,
-.00000000000010960825046059278,
.00000000000002311949383800537,
-.00000000000058469058005299247,
-.00000000000002103748251144494,
-.00000000000023323182945587408,
-.00000000000042333694288141916,
-.00000000000043933937969737844,
.00000000000041341647073835565,
.00000000000006841763641591466,
.00000000000047585534004430641,
.00000000000083679678674757695,
-.00000000000085763734646658640,
.00000000000021913281229340092,
-.00000000000062242842536431148,
-.00000000000010983594325438430,
.00000000000065310431377633651,
-.00000000000047580199021710769,
-.00000000000037854251265457040,
.00000000000040939233218678664,
.00000000000087424383914858291,
.00000000000025218188456842882,
-.00000000000003608131360422557,
-.00000000000050518555924280902,
.00000000000078699403323355317,
-.00000000000067020876961949060,
.00000000000016108575753932458,
.00000000000058527188436251509,
-.00000000000035246757297904791,
-.00000000000018372084495629058,
.00000000000088606689813494916,
.00000000000066486268071468700,
.00000000000063831615170646519,
.00000000000025144230728376072,
-.00000000000017239444525614834
};
double
#ifdef _ANSI_SOURCE
log(double x)
#else
log(x) double x;
#endif
{
int m, j;
double F, f, g, q, u, u2, v, zero = 0.0, one = 1.0;
volatile double u1;
/* Catch special cases */
if (x <= 0)
if (_IEEE && x == zero) /* log(0) = -Inf */
return (-one/zero);
else if (_IEEE) /* log(neg) = NaN */
return (zero/zero);
else if (x == zero) /* NOT REACHED IF _IEEE */
return (infnan(-ERANGE));
else
return (infnan(EDOM));
else if (!finite(x))
if (_IEEE) /* x = NaN, Inf */
return (x+x);
else
return (infnan(ERANGE));
/* Argument reduction: 1 <= g < 2; x/2^m = g; */
/* y = F*(1 + f/F) for |f| <= 2^-8 */
m = logb(x);
g = ldexp(x, -m);
if (_IEEE && m == -1022) {
j = logb(g), m += j;
g = ldexp(g, -j);
}
j = N*(g-1) + .5;
F = (1.0/N) * j + 1; /* F*128 is an integer in [128, 512] */
f = g - F;
/* Approximate expansion for log(1+f/F) ~= u + q */
g = 1/(2*F+f);
u = 2*f*g;
v = u*u;
q = u*v*(A1 + v*(A2 + v*(A3 + v*A4)));
/* case 1: u1 = u rounded to 2^-43 absolute. Since u < 2^-8,
* u1 has at most 35 bits, and F*u1 is exact, as F has < 8 bits.
* It also adds exactly to |m*log2_hi + log_F_head[j] | < 750
*/
if (m | j)
u1 = u + 513, u1 -= 513;
/* case 2: |1-x| < 1/256. The m- and j- dependent terms are zero;
* u1 = u to 24 bits.
*/
else
u1 = u, TRUNC(u1);
u2 = (2.0*(f - F*u1) - u1*f) * g;
/* u1 + u2 = 2f/(2F+f) to extra precision. */
/* log(x) = log(2^m*F*(1+f/F)) = */
/* (m*log2_hi+logF_head[j]+u1) + (m*log2_lo+logF_tail[j]+q); */
/* (exact) + (tiny) */
u1 += m*logF_head[N] + logF_head[j]; /* exact */
u2 = (u2 + logF_tail[j]) + q; /* tiny */
u2 += logF_tail[N]*m;
return (u1 + u2);
}
/*
* Extra precision variant, returning struct {double a, b;};
* log(x) = a+b to 63 bits, with a is rounded to 26 bits.
*/
struct Double
#ifdef _ANSI_SOURCE
__log__D(double x)
#else
__log__D(x) double x;
#endif
{
int m, j;
double F, f, g, q, u, v, u2, one = 1.0;
volatile double u1;
struct Double r;
/* Argument reduction: 1 <= g < 2; x/2^m = g; */
/* y = F*(1 + f/F) for |f| <= 2^-8 */
m = logb(x);
g = ldexp(x, -m);
if (_IEEE && m == -1022) {
j = logb(g), m += j;
g = ldexp(g, -j);
}
j = N*(g-1) + .5;
F = (1.0/N) * j + 1;
f = g - F;
g = 1/(2*F+f);
u = 2*f*g;
v = u*u;
q = u*v*(A1 + v*(A2 + v*(A3 + v*A4)));
if (m | j)
u1 = u + 513, u1 -= 513;
else
u1 = u, TRUNC(u1);
u2 = (2.0*(f - F*u1) - u1*f) * g;
u1 += m*logF_head[N] + logF_head[j];
u2 += logF_tail[j]; u2 += q;
u2 += logF_tail[N]*m;
r.a = u1 + u2; /* Only difference is here */
TRUNC(r.a);
r.b = (u1 - r.a) + u2;
return (r);
}

View File

@ -1,98 +0,0 @@
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)mathimpl.h 8.1 (Berkeley) 6/4/93
*/
#include <sys/cdefs.h>
#include <math.h>
#if defined(vax)||defined(tahoe)
/* Deal with different ways to concatenate in cpp */
# ifdef __STDC__
# define cat3(a,b,c) a ## b ## c
# else
# define cat3(a,b,c) a/**/b/**/c
# endif
/* Deal with vax/tahoe byte order issues */
# ifdef vax
# define cat3t(a,b,c) cat3(a,b,c)
# else
# define cat3t(a,b,c) cat3(a,c,b)
# endif
# define vccast(name) (*(const double *)(cat3(name,,x)))
/*
* Define a constant to high precision on a Vax or Tahoe.
*
* Args are the name to define, the decimal floating point value,
* four 16-bit chunks of the float value in hex
* (because the vax and tahoe differ in float format!), the power
* of 2 of the hex-float exponent, and the hex-float mantissa.
* Most of these arguments are not used at compile time; they are
* used in a post-check to make sure the constants were compiled
* correctly.
*
* People who want to use the constant will have to do their own
* #define foo vccast(foo)
* since CPP cannot do this for them from inside another macro (sigh).
* We define "vccast" if this needs doing.
*/
# define vc(name, value, x1,x2,x3,x4, bexp, xval) \
const static long cat3(name,,x)[] = {cat3t(0x,x1,x2), cat3t(0x,x3,x4)};
# define ic(name, value, bexp, xval) ;
#else /* vax or tahoe */
/* Hooray, we have an IEEE machine */
# undef vccast
# define vc(name, value, x1,x2,x3,x4, bexp, xval) ;
# define ic(name, value, bexp, xval) \
const static double name = value;
#endif /* defined(vax)||defined(tahoe) */
/*
* Functions internal to the math package, yet not static.
*/
extern double __exp__E();
extern double __log__L();
struct Double {double a, b;};
double __exp__D __P((double, double));
struct Double __log__D __P((double));