pow.c revision 1ec68d336ba97cd53f46053ac10401d16014d075
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * CDDL HEADER START
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * The contents of this file are subject to the terms of the
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * Common Development and Distribution License (the "License").
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * You may not use this file except in compliance with the License.
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * See the License for the specific language governing permissions
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * and limitations under the License.
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * When distributing Covered Code, include this CDDL HEADER in each
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * If applicable, add the following below this CDDL HEADER, with the
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * fields enclosed by brackets "[]" replaced with your own identifying
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * information: Portions Copyright [yyyy] [name of copyright owner]
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * CDDL HEADER END
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * Use is subject to license terms.
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * pow(x,y) return x**y
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * Method: Let x = 2 * (1+f)
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * 1. Compute and return log2(x) in two pieces:
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * log2(x) = w1 + w2,
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * where w1 has 24 bits trailing zero.
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra * 2. Perform y*log2(x) by simulating muti-precision arithmetic
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * 3. Return x**y = exp2(y*log(x))
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * Special cases:
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * 1. (anything) ** +-0 is 1
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * 1'. 1 ** (anything) is 1 (C99; 1 ** +-INF/NAN used to be NAN)
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * 2. (anything) ** 1 is itself
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * 3. (anything except 1) ** NAN is NAN ("except 1" is C99)
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * 4. NAN ** (anything except 0) is NAN
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * 5. +-(|x| > 1) ** +INF is +INF
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * 6. +-(|x| > 1) ** -INF is +0
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * 7. +-(|x| < 1) ** +INF is +0
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * 8. +-(|x| < 1) ** -INF is +INF
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra * 9. -1 ** +-INF is 1 (C99; -1 ** +-INF used to be NAN)
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * 10. +0 ** (+anything except 0, NAN) is +0
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra * 11. -0 ** (+anything except 0, NAN, odd integer) is +0
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * 12. +0 ** (-anything except 0, NAN) is +INF
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * 14. -0 ** (odd integer) = -( +0 ** (odd integer) )
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * 15. +INF ** (+anything except 0,NAN) is +INF
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * 16. +INF ** (-anything except 0,NAN) is +0
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra * 17. -INF ** (anything) = -0 ** (-anything)
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer)
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * 19. (-anything except 0 and inf) ** (non-integer) is NAN
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * Accuracy:
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * pow(x,y) returns x**y nearly rounded. In particular
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * pow(integer,integer)
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * always returns the correct integer provided it is representable.
b6917abefc343244b784f0cc34bc65b01469c3bfmishra#define _C99SUSv3_pow _C99SUSv3_pow_treats_Inf_as_an_even_int
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misraextern const double _TBL_log2_hi[], _TBL_log2_lo[];
b6917abefc343244b784f0cc34bc65b01469c3bfmishrastatic const double
b6917abefc343244b784f0cc34bc65b01469c3bfmishra A1 = 2.885390081777926817222541963606002026086e+0000,
b6917abefc343244b784f0cc34bc65b01469c3bfmishra A2 = 9.617966939207270828380543979852286255862e-0001,
b6917abefc343244b784f0cc34bc65b01469c3bfmishra A3 = 5.770807680887875964868853124873696201995e-0001,
4c1c9391ff5b1b69f6fc02ce905b96759cc50fc0Joe Bonasera B0 = 2.885390081777926814720293056374320585689e+0000,
b6917abefc343244b784f0cc34bc65b01469c3bfmishra B1 = 9.617966939259755138949202350396200257632e-0001,
b6917abefc343244b784f0cc34bc65b01469c3bfmishra B2 = 5.770780163585687000782112776448797953382e-0001,
b6917abefc343244b784f0cc34bc65b01469c3bfmishra B3 = 4.121985488948771523290174512461778354953e-0001,
b6917abefc343244b784f0cc34bc65b01469c3bfmishra B4 = 3.207590534812432970433641789022666850193e-0001;
b6917abefc343244b784f0cc34bc65b01469c3bfmishrastatic double
b6917abefc343244b784f0cc34bc65b01469c3bfmishralog2_x(double x, double *w) {
b6917abefc343244b784f0cc34bc65b01469c3bfmishra double f, s, z, qn, h, t;
b6917abefc343244b784f0cc34bc65b01469c3bfmishra int *px = (int *) &x;
b6917abefc343244b784f0cc34bc65b01469c3bfmishra int *pz = (int *) &z;
b6917abefc343244b784f0cc34bc65b01469c3bfmishra int i, j, ix, n;
b6917abefc343244b784f0cc34bc65b01469c3bfmishra if (ix >= 0x3fef03f1 && ix < 0x3ff08208) { /* 65/63 > x > 63/65 */
b6917abefc343244b784f0cc34bc65b01469c3bfmishra double f1, v;
b6917abefc343244b784f0cc34bc65b01469c3bfmishra h = (double) ((float) s);
b6917abefc343244b784f0cc34bc65b01469c3bfmishra f1 = (double) ((float) f);
b6917abefc343244b784f0cc34bc65b01469c3bfmishra /* s = h+t */
b6917abefc343244b784f0cc34bc65b01469c3bfmishra f1 = h * B0_lo + s * (v * (B1 + v * (B2 + v * (B3 + v * B4))));
b6917abefc343244b784f0cc34bc65b01469c3bfmishra s = (double) ((float) (h + t));
b6917abefc343244b784f0cc34bc65b01469c3bfmishra *w = t - (s - h);
b6917abefc343244b784f0cc34bc65b01469c3bfmishra return (s);
b6917abefc343244b784f0cc34bc65b01469c3bfmishra /* LARGE N */
b6917abefc343244b784f0cc34bc65b01469c3bfmishra ix = (ix & 0x000fffff) | 0x3ff00000; /* scale x to [1,2] */
b6917abefc343244b784f0cc34bc65b01469c3bfmishra h = (double) ((float) s);
b6917abefc343244b784f0cc34bc65b01469c3bfmishra t = qn * ((f - (h + h) * z) - h * f);
b6917abefc343244b784f0cc34bc65b01469c3bfmishra f = (double) ((float) (h + t));
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra *w = t - (f - h);
b6917abefc343244b784f0cc34bc65b01469c3bfmishra return (f);
b6917abefc343244b784f0cc34bc65b01469c3bfmishrastatic const double /* poly app of 2^x-1 on [-1e-10,2^-7+1e-10] */
b6917abefc343244b784f0cc34bc65b01469c3bfmishra E1 = 6.931471805599453100674958533810346197328e-0001,
b6917abefc343244b784f0cc34bc65b01469c3bfmishra E2 = 2.402265069587779347846769151717493815979e-0001,
b6917abefc343244b784f0cc34bc65b01469c3bfmishra E3 = 5.550410866475410512631124892773937864699e-0002,
b6917abefc343244b784f0cc34bc65b01469c3bfmishra E4 = 9.618143209991026824853712740162451423355e-0003,
b6917abefc343244b784f0cc34bc65b01469c3bfmishra E5 = 1.333357676549940345096774122231849082991e-0003;
b6917abefc343244b784f0cc34bc65b01469c3bfmishrapow(double x, double y) {
b6917abefc343244b784f0cc34bc65b01469c3bfmishra double z, ax;
f9c480cd662f42d54475b87370bc2f4811ec0679Saurabh Misra int *pz = (int *) &z;
b6917abefc343244b784f0cc34bc65b01469c3bfmishra else if ((ahx | (((lx | -lx) >> 31) & 1)) > 0x7ff00000)
b6917abefc343244b784f0cc34bc65b01469c3bfmishra return (z);
b6917abefc343244b784f0cc34bc65b01469c3bfmishra else if (ahx > 0x7ff00000 || (ahx == 0x7ff00000 && lx != 0) ||
b6917abefc343244b784f0cc34bc65b01469c3bfmishra return (x * y); /* +-NaN return x*y; + -> * for Cheetah */
b6917abefc343244b784f0cc34bc65b01469c3bfmishra /* includes Sun: 1**NaN = NaN */
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * determine if y is an odd int when x < 0
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * yisint = 0 ... y is not an integer
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * yisint = 1 ... y is an odd int
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * yisint = 2 ... y is an even int
b6917abefc343244b784f0cc34bc65b01469c3bfmishra if (k > 20) {
b6917abefc343244b784f0cc34bc65b01469c3bfmishra } else if (ly == 0) {
d23e508cd51e6b3ec3f10a427259d7dd2592fa94Edward Gillett /* special value of y */
b6917abefc343244b784f0cc34bc65b01469c3bfmishra /* C99: (-1)**+-inf = 1 */
b6917abefc343244b784f0cc34bc65b01469c3bfmishra return (y - y);
b6917abefc343244b784f0cc34bc65b01469c3bfmishra /* Sun: (+-1)**+-inf = NaN */
b6917abefc343244b784f0cc34bc65b01469c3bfmishra /* (|x|>1)**+,-inf = inf,0 */
b6917abefc343244b784f0cc34bc65b01469c3bfmishra else /* (|x|<1)**-,+inf = inf,0 */
b6917abefc343244b784f0cc34bc65b01469c3bfmishra return (one / x);
b6917abefc343244b784f0cc34bc65b01469c3bfmishra return (x);
b6917abefc343244b784f0cc34bc65b01469c3bfmishra /* x*x overflow */
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra /* x*x underflow */
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra return (x * x);
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra if (!((ahx | lx) == 0 || ((ahx - 0x7ff00000) | lx) ==
b6917abefc343244b784f0cc34bc65b01469c3bfmishra /* special value of x */
b6917abefc343244b784f0cc34bc65b01469c3bfmishra if (lx == 0) {
b6917abefc343244b784f0cc34bc65b01469c3bfmishra if (ahx == 0x7ff00000 || ahx == 0 || ahx == 0x3ff00000) {
b6917abefc343244b784f0cc34bc65b01469c3bfmishra /* x is +-0,+-inf,-1 */
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra /* neg**non-integral is NaN + invalid */
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra z = -z; /* (x<0)**odd = -(|x|**odd) */
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra /* (x<0)**(non-int) is NaN */
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra /* Now ax is finite, y is finite */
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra /* first compute log2(ax) = w1+w2, with 24 bits w1 */
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra /* split up y into y1+y2 and compute (y1+y2)*(w1+w2) */
e511d54dfc1c7eb3aea1a9125b54791fc2f23d42Saurabh Misra if (((ly & 0x07ffffff) == 0) || ahy >= 0x47e00000 ||
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra /* no need to split if y is short or too large or too small */
e511d54dfc1c7eb3aea1a9125b54791fc2f23d42Saurabh Misra y1 = (double) ((float) y);
e511d54dfc1c7eb3aea1a9125b54791fc2f23d42Saurabh Misra if (!(j == 0x40900000 && pz[LOWORD] == 0)) /* z > 1024 */
e511d54dfc1c7eb3aea1a9125b54791fc2f23d42Saurabh Misra return (_SVID_libm_err(x, y, 21)); /* overflow */
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra /* rounded to inf */
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra /* overflow */
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra } else if ((j & ~0x80000000) >= 0x4090cc00) { /* z <= -1075 */
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra if (!(j == 0xc090cc00 && pz[LOWORD] == 0)) /* z < -1075 */
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra return (_SVID_libm_err(x, y, 22)); /* underflow */
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * compute 2**(k+f[j]+g)
b6917abefc343244b784f0cc34bc65b01469c3bfmishra k = (int) (z * 64.0 + (((hy ^ (ahx - 0x3ff00000)) > 0) ? 0.5 : -0.5));
b6917abefc343244b784f0cc34bc65b01469c3bfmishra j = k & 63;
87cc626978cedbea111888dba5e4042df5cf532cSaurabh Misra z = _TBL_exp2_lo[j] + (w2 * w1) * (E1 + w1 * (E2 + w1 * (E3 + w1 *
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra if (k < -1021)
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra else /* subnormal output */
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra z = -z; /* (-ve)**(odd int) */