125c28e8Piotr Jasiukajtis/*
225c28e8Piotr Jasiukajtis * CDDL HEADER START
325c28e8Piotr Jasiukajtis *
425c28e8Piotr Jasiukajtis * The contents of this file are subject to the terms of the
525c28e8Piotr Jasiukajtis * Common Development and Distribution License (the "License").
625c28e8Piotr Jasiukajtis * You may not use this file except in compliance with the License.
725c28e8Piotr Jasiukajtis *
825c28e8Piotr Jasiukajtis * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
925c28e8Piotr Jasiukajtis * or http://www.opensolaris.org/os/licensing.
1025c28e8Piotr Jasiukajtis * See the License for the specific language governing permissions
1125c28e8Piotr Jasiukajtis * and limitations under the License.
1225c28e8Piotr Jasiukajtis *
1325c28e8Piotr Jasiukajtis * When distributing Covered Code, include this CDDL HEADER in each
1425c28e8Piotr Jasiukajtis * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1525c28e8Piotr Jasiukajtis * If applicable, add the following below this CDDL HEADER, with the
1625c28e8Piotr Jasiukajtis * fields enclosed by brackets "[]" replaced with your own identifying
1725c28e8Piotr Jasiukajtis * information: Portions Copyright [yyyy] [name of copyright owner]
1825c28e8Piotr Jasiukajtis *
1925c28e8Piotr Jasiukajtis * CDDL HEADER END
2025c28e8Piotr Jasiukajtis */
2125c28e8Piotr Jasiukajtis
2225c28e8Piotr Jasiukajtis/*
2325c28e8Piotr Jasiukajtis * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
2425c28e8Piotr Jasiukajtis */
2525c28e8Piotr Jasiukajtis/*
2625c28e8Piotr Jasiukajtis * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
2725c28e8Piotr Jasiukajtis * Use is subject to license terms.
2825c28e8Piotr Jasiukajtis */
2925c28e8Piotr Jasiukajtis
30ddc0e0bRichard Lowe#pragma weak __logl = logl
3125c28e8Piotr Jasiukajtis
3225c28e8Piotr Jasiukajtis/*
3325c28e8Piotr Jasiukajtis * logl(x)
3425c28e8Piotr Jasiukajtis * Table look-up algorithm
3525c28e8Piotr Jasiukajtis * By K.C. Ng, March 6, 1989
3625c28e8Piotr Jasiukajtis *
3725c28e8Piotr Jasiukajtis * (a). For x in [31/33,33/31], using a special approximation:
3825c28e8Piotr Jasiukajtis *	f = x - 1;
3925c28e8Piotr Jasiukajtis *	s = f/(2.0+f);	... here |s| <= 0.03125
4025c28e8Piotr Jasiukajtis *	z = s*s;
4125c28e8Piotr Jasiukajtis *	return f-s*(f-z*(B1+z*(B2+z*(B3+z*(B4+...+z*B9)...))));
4225c28e8Piotr Jasiukajtis *
4325c28e8Piotr Jasiukajtis * (b). Otherwise, normalize x = 2^n * 1.f.
4425c28e8Piotr Jasiukajtis *	Use a 6-bit table look-up: find a 6 bit g that match f to 6.5 bits,
4525c28e8Piotr Jasiukajtis *	then
4625c28e8Piotr Jasiukajtis *	    log(x) = n*ln2 + log(1.g) + log(1.f/1.g).
4725c28e8Piotr Jasiukajtis *	Here the leading and trailing values of log(1.g) are obtained from
4825c28e8Piotr Jasiukajtis *	a size-64 table.
4925c28e8Piotr Jasiukajtis *	For log(1.f/1.g), let s = (1.f-1.g)/(1.f+1.g), then
5025c28e8Piotr Jasiukajtis *	    log(1.f/1.g) = log((1+s)/(1-s)) = 2s + 2/3 s^3 + 2/5 s^5 +...
5125c28e8Piotr Jasiukajtis *	Note that |s|<2**-8=0.00390625. We use an odd s-polynomial
5225c28e8Piotr Jasiukajtis *	approximation to compute log(1.f/1.g):
5325c28e8Piotr Jasiukajtis *		s*(A1+s^2*(A2+s^2*(A3+s^2*(A4+s^2*(A5+s^2*(A6+s^2*A7))))))
5425c28e8Piotr Jasiukajtis *	(Precision is 2**-136.91 bits, absolute error)
5525c28e8Piotr Jasiukajtis *
5625c28e8Piotr Jasiukajtis * (c). The final result is computed by
5725c28e8Piotr Jasiukajtis *		(n*ln2_hi+_TBL_logl_hi[j]) +
5825c28e8Piotr Jasiukajtis *			( (n*ln2_lo+_TBL_logl_lo[j]) + s*(A1+...) )
5925c28e8Piotr Jasiukajtis *
6025c28e8Piotr Jasiukajtis * Note.
6125c28e8Piotr Jasiukajtis *	For ln2_hi and _TBL_logl_hi[j], we force their last 32 bit to be zero
6225c28e8Piotr Jasiukajtis *	so that n*ln2_hi + _TBL_logl_hi[j] is exact. Here
6325c28e8Piotr Jasiukajtis *	_TBL_logl_hi[j] + _TBL_logl_lo[j] match log(1+j*2**-6) to 194 bits
6425c28e8Piotr Jasiukajtis *
6525c28e8Piotr Jasiukajtis *
6625c28e8Piotr Jasiukajtis * Special cases:
6725c28e8Piotr Jasiukajtis *	log(x) is NaN with signal if x < 0 (including -INF) ;
6825c28e8Piotr Jasiukajtis *	log(+INF) is +INF; log(0) is -INF with signal;
6925c28e8Piotr Jasiukajtis *	log(NaN) is that NaN with no signal.
7025c28e8Piotr Jasiukajtis *
7125c28e8Piotr Jasiukajtis * Constants:
7225c28e8Piotr Jasiukajtis * The hexadecimal values are the intended ones for the following constants.
7325c28e8Piotr Jasiukajtis * The decimal values may be used, provided that the compiler will convert
7425c28e8Piotr Jasiukajtis * from decimal to binary accurately enough to produce the hexadecimal values
7525c28e8Piotr Jasiukajtis * shown.
7625c28e8Piotr Jasiukajtis */
7725c28e8Piotr Jasiukajtis
7825c28e8Piotr Jasiukajtis#include "libm.h"
7925c28e8Piotr Jasiukajtis
8025c28e8Piotr Jasiukajtisextern const long double _TBL_logl_hi[], _TBL_logl_lo[];
8125c28e8Piotr Jasiukajtis
8225c28e8Piotr Jasiukajtisstatic const long double
8325c28e8Piotr Jasiukajtis	zero	=   0.0L,
8425c28e8Piotr Jasiukajtis	one	=   1.0L,
8525c28e8Piotr Jasiukajtis	two	=   2.0L,
8625c28e8Piotr Jasiukajtis	two113  =   10384593717069655257060992658440192.0L,
8725c28e8Piotr Jasiukajtis	ln2hi	=   6.931471805599453094172319547495844850203e-0001L,
8825c28e8Piotr Jasiukajtis	ln2lo	=   1.667085920830552208890449330400379754169e-0025L,
8925c28e8Piotr Jasiukajtis	A1	=   2.000000000000000000000000000000000000024e+0000L,
9025c28e8Piotr Jasiukajtis	A2	=   6.666666666666666666666666666666091393804e-0001L,
9125c28e8Piotr Jasiukajtis	A3	=   4.000000000000000000000000407167070220671e-0001L,
9225c28e8Piotr Jasiukajtis	A4	=   2.857142857142857142730077490612903681164e-0001L,
9325c28e8Piotr Jasiukajtis	A5	=   2.222222222222242577702836920812882605099e-0001L,
9425c28e8Piotr Jasiukajtis	A6	=   1.818181816435493395985912667105885828356e-0001L,
9525c28e8Piotr Jasiukajtis	A7	=   1.538537835211839751112067512805496931725e-0001L,
9625c28e8Piotr Jasiukajtis	B1	=   6.666666666666666666666666666666961498329e-0001L,
9725c28e8Piotr Jasiukajtis	B2	=   3.999999999999999999999999990037655042358e-0001L,
9825c28e8Piotr Jasiukajtis	B3	=   2.857142857142857142857273426428347457918e-0001L,
9925c28e8Piotr Jasiukajtis	B4	=   2.222222222222222221353229049747910109566e-0001L,
10025c28e8Piotr Jasiukajtis	B5	=   1.818181818181821503532559306309070138046e-0001L,
10125c28e8Piotr Jasiukajtis	B6	=   1.538461538453809210486356084587356788556e-0001L,
10225c28e8Piotr Jasiukajtis	B7	=   1.333333344463358756121456892645178795480e-0001L,
10325c28e8Piotr Jasiukajtis	B8	=   1.176460904783899064854645174603360383792e-0001L,
10425c28e8Piotr Jasiukajtis	B9	=   1.057293869956598995326368602518056990746e-0001L;
10525c28e8Piotr Jasiukajtis
10625c28e8Piotr Jasiukajtislong double
10725c28e8Piotr Jasiukajtislogl(long double x) {
10825c28e8Piotr Jasiukajtis	long double f, s, z, qn, h, t;
10925c28e8Piotr Jasiukajtis	int *px = (int *) &x;
11025c28e8Piotr Jasiukajtis	int *pz = (int *) &z;
11125c28e8Piotr Jasiukajtis	int i, j, ix, i0, i1, n;
11225c28e8Piotr Jasiukajtis
11325c28e8Piotr Jasiukajtis	/* get long double precision word ordering */
11425c28e8Piotr Jasiukajtis	if (*(int *) &one == 0) {
11525c28e8Piotr Jasiukajtis		i0 = 3;
11625c28e8Piotr Jasiukajtis		i1 = 0;
11725c28e8Piotr Jasiukajtis	} else {
11825c28e8Piotr Jasiukajtis		i0 = 0;
11925c28e8Piotr Jasiukajtis		i1 = 3;
12025c28e8Piotr Jasiukajtis	}
12125c28e8Piotr Jasiukajtis
12225c28e8Piotr Jasiukajtis	n = 0;
12325c28e8Piotr Jasiukajtis	ix = px[i0];
12425c28e8Piotr Jasiukajtis	if (ix > 0x3ffee0f8) {	/* if x >  31/33 */
12525c28e8Piotr Jasiukajtis		if (ix < 0x3fff1084) {	/* if x < 33/31 */
12625c28e8Piotr Jasiukajtis			f = x - one;
12725c28e8Piotr Jasiukajtis			z = f * f;
12825c28e8Piotr Jasiukajtis			if (((ix - 0x3fff0000) | px[i1] | px[2] | px[1]) == 0) {
12925c28e8Piotr Jasiukajtis				return (zero);	/* log(1)= +0 */
13025c28e8Piotr Jasiukajtis			}
13125c28e8Piotr Jasiukajtis			s = f / (two + f);	/* |s|<2**-8 */
13225c28e8Piotr Jasiukajtis			z = s * s;
13325c28e8Piotr Jasiukajtis			return (f - s * (f - z * (B1 + z * (B2 + z * (B3 +
13425c28e8Piotr Jasiukajtis				z * (B4 + z * (B5 + z * (B6 + z * (B7 +
13525c28e8Piotr Jasiukajtis				z * (B8 + z * B9))))))))));
13625c28e8Piotr Jasiukajtis		}
13725c28e8Piotr Jasiukajtis		if (ix >= 0x7fff0000)
13825c28e8Piotr Jasiukajtis			return (x + x);	/* x is +inf or NaN */
13925c28e8Piotr Jasiukajtis		goto LARGE_N;
14025c28e8Piotr Jasiukajtis	}
14125c28e8Piotr Jasiukajtis	if (ix >= 0x00010000)
14225c28e8Piotr Jasiukajtis		goto LARGE_N;
14325c28e8Piotr Jasiukajtis	i = ix & 0x7fffffff;
14425c28e8Piotr Jasiukajtis	if ((i | px[i1] | px[2] | px[1]) == 0) {
14525c28e8Piotr Jasiukajtis		px[i0] |= 0x80000000;
14625c28e8Piotr Jasiukajtis		return (one / x);	/* log(0.0) = -inf */
14725c28e8Piotr Jasiukajtis	}
14825c28e8Piotr Jasiukajtis	if (ix < 0) {
14925c28e8Piotr Jasiukajtis		if ((unsigned) ix >= 0xffff0000)
15025c28e8Piotr Jasiukajtis			return (x - x);	/* x is -inf or NaN */
15125c28e8Piotr Jasiukajtis		return (zero / zero);	/* log(x<0) is NaN  */
15225c28e8Piotr Jasiukajtis	}
15325c28e8Piotr Jasiukajtis	/* subnormal x */
15425c28e8Piotr Jasiukajtis	x *= two113;
15525c28e8Piotr Jasiukajtis	n = -113;
15625c28e8Piotr Jasiukajtis	ix = px[i0];
15725c28e8Piotr JasiukajtisLARGE_N:
15825c28e8Piotr Jasiukajtis	n += ((ix + 0x200) >> 16) - 0x3fff;
15925c28e8Piotr Jasiukajtis	ix = (ix & 0x0000ffff) | 0x3fff0000;	/* scale x to [1,2] */
16025c28e8Piotr Jasiukajtis	px[i0] = ix;
16125c28e8Piotr Jasiukajtis	i = ix + 0x200;
16225c28e8Piotr Jasiukajtis	pz[i0] = i & 0xfffffc00;
16325c28e8Piotr Jasiukajtis	pz[i1] = pz[1] = pz[2] = 0;
16425c28e8Piotr Jasiukajtis	s = (x - z) / (x + z);
16525c28e8Piotr Jasiukajtis	j = (i >> 10) & 0x3f;
16625c28e8Piotr Jasiukajtis	z = s * s;
16725c28e8Piotr Jasiukajtis	qn = (long double) n;
16825c28e8Piotr Jasiukajtis	t = qn * ln2lo + _TBL_logl_lo[j];
16925c28e8Piotr Jasiukajtis	h = qn * ln2hi + _TBL_logl_hi[j];
17025c28e8Piotr Jasiukajtis	f = t + s * (A1 + z * (A2 + z * (A3 + z * (A4 + z * (A5 +
17125c28e8Piotr Jasiukajtis		z * (A6 + z * A7))))));
17225c28e8Piotr Jasiukajtis	return (h + f);
17325c28e8Piotr Jasiukajtis}
174