125c28e83SPiotr Jasiukajtis /* 225c28e83SPiotr Jasiukajtis * CDDL HEADER START 325c28e83SPiotr Jasiukajtis * 425c28e83SPiotr Jasiukajtis * The contents of this file are subject to the terms of the 525c28e83SPiotr Jasiukajtis * Common Development and Distribution License (the "License"). 625c28e83SPiotr Jasiukajtis * You may not use this file except in compliance with the License. 725c28e83SPiotr Jasiukajtis * 825c28e83SPiotr Jasiukajtis * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 925c28e83SPiotr Jasiukajtis * or http://www.opensolaris.org/os/licensing. 1025c28e83SPiotr Jasiukajtis * See the License for the specific language governing permissions 1125c28e83SPiotr Jasiukajtis * and limitations under the License. 1225c28e83SPiotr Jasiukajtis * 1325c28e83SPiotr Jasiukajtis * When distributing Covered Code, include this CDDL HEADER in each 1425c28e83SPiotr Jasiukajtis * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1525c28e83SPiotr Jasiukajtis * If applicable, add the following below this CDDL HEADER, with the 1625c28e83SPiotr Jasiukajtis * fields enclosed by brackets "[]" replaced with your own identifying 1725c28e83SPiotr Jasiukajtis * information: Portions Copyright [yyyy] [name of copyright owner] 1825c28e83SPiotr Jasiukajtis * 1925c28e83SPiotr Jasiukajtis * CDDL HEADER END 2025c28e83SPiotr Jasiukajtis */ 2125c28e83SPiotr Jasiukajtis /* 2225c28e83SPiotr Jasiukajtis * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 2325c28e83SPiotr Jasiukajtis */ 2425c28e83SPiotr Jasiukajtis /* 2525c28e83SPiotr Jasiukajtis * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 2625c28e83SPiotr Jasiukajtis * Use is subject to license terms. 2725c28e83SPiotr Jasiukajtis */ 2825c28e83SPiotr Jasiukajtis 29*ddc0e0b5SRichard Lowe #pragma weak __powf = powf 3025c28e83SPiotr Jasiukajtis 3125c28e83SPiotr Jasiukajtis #include "libm.h" 3225c28e83SPiotr Jasiukajtis #include "xpg6.h" /* __xpg6 */ 3325c28e83SPiotr Jasiukajtis #define _C99SUSv3_pow _C99SUSv3_pow_treats_Inf_as_an_even_int 3425c28e83SPiotr Jasiukajtis 3525c28e83SPiotr Jasiukajtis #if defined(__i386) && !defined(__amd64) 3625c28e83SPiotr Jasiukajtis extern int __swapRP(int); 3725c28e83SPiotr Jasiukajtis #endif 3825c28e83SPiotr Jasiukajtis 3925c28e83SPiotr Jasiukajtis /* INDENT OFF */ 4025c28e83SPiotr Jasiukajtis static const double 4125c28e83SPiotr Jasiukajtis ln2 = 6.93147180559945286227e-01, /* 0x3fe62e42, 0xfefa39ef */ 4225c28e83SPiotr Jasiukajtis invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */ 4325c28e83SPiotr Jasiukajtis dtwo = 2.0, 4425c28e83SPiotr Jasiukajtis done = 1.0, 4525c28e83SPiotr Jasiukajtis dhalf = 0.5, 4625c28e83SPiotr Jasiukajtis d32 = 32.0, 4725c28e83SPiotr Jasiukajtis d1_32 = 0.03125, 4825c28e83SPiotr Jasiukajtis A0 = 1.999999999813723303647511146995966439250e+0000, 4925c28e83SPiotr Jasiukajtis A1 = 6.666910817935858533770138657139665608610e-0001, 5025c28e83SPiotr Jasiukajtis t0 = 2.000000000004777489262405315073203746943e+0000, 5125c28e83SPiotr Jasiukajtis t1 = 1.666663408349926379873111932994250726307e-0001; 5225c28e83SPiotr Jasiukajtis 5325c28e83SPiotr Jasiukajtis static const double S[] = { 5425c28e83SPiotr Jasiukajtis 1.00000000000000000000e+00, /* 3FF0000000000000 */ 5525c28e83SPiotr Jasiukajtis 1.02189714865411662714e+00, /* 3FF059B0D3158574 */ 5625c28e83SPiotr Jasiukajtis 1.04427378242741375480e+00, /* 3FF0B5586CF9890F */ 5725c28e83SPiotr Jasiukajtis 1.06714040067682369717e+00, /* 3FF11301D0125B51 */ 5825c28e83SPiotr Jasiukajtis 1.09050773266525768967e+00, /* 3FF172B83C7D517B */ 5925c28e83SPiotr Jasiukajtis 1.11438674259589243221e+00, /* 3FF1D4873168B9AA */ 6025c28e83SPiotr Jasiukajtis 1.13878863475669156458e+00, /* 3FF2387A6E756238 */ 6125c28e83SPiotr Jasiukajtis 1.16372485877757747552e+00, /* 3FF29E9DF51FDEE1 */ 6225c28e83SPiotr Jasiukajtis 1.18920711500272102690e+00, /* 3FF306FE0A31B715 */ 6325c28e83SPiotr Jasiukajtis 1.21524735998046895524e+00, /* 3FF371A7373AA9CB */ 6425c28e83SPiotr Jasiukajtis 1.24185781207348400201e+00, /* 3FF3DEA64C123422 */ 6525c28e83SPiotr Jasiukajtis 1.26905095719173321989e+00, /* 3FF44E086061892D */ 6625c28e83SPiotr Jasiukajtis 1.29683955465100964055e+00, /* 3FF4BFDAD5362A27 */ 6725c28e83SPiotr Jasiukajtis 1.32523664315974132322e+00, /* 3FF5342B569D4F82 */ 6825c28e83SPiotr Jasiukajtis 1.35425554693689265129e+00, /* 3FF5AB07DD485429 */ 6925c28e83SPiotr Jasiukajtis 1.38390988196383202258e+00, /* 3FF6247EB03A5585 */ 7025c28e83SPiotr Jasiukajtis 1.41421356237309514547e+00, /* 3FF6A09E667F3BCD */ 7125c28e83SPiotr Jasiukajtis 1.44518080697704665027e+00, /* 3FF71F75E8EC5F74 */ 7225c28e83SPiotr Jasiukajtis 1.47682614593949934623e+00, /* 3FF7A11473EB0187 */ 7325c28e83SPiotr Jasiukajtis 1.50916442759342284141e+00, /* 3FF82589994CCE13 */ 7425c28e83SPiotr Jasiukajtis 1.54221082540794074411e+00, /* 3FF8ACE5422AA0DB */ 7525c28e83SPiotr Jasiukajtis 1.57598084510788649659e+00, /* 3FF93737B0CDC5E5 */ 7625c28e83SPiotr Jasiukajtis 1.61049033194925428347e+00, /* 3FF9C49182A3F090 */ 7725c28e83SPiotr Jasiukajtis 1.64575547815396494578e+00, /* 3FFA5503B23E255D */ 7825c28e83SPiotr Jasiukajtis 1.68179283050742900407e+00, /* 3FFAE89F995AD3AD */ 7925c28e83SPiotr Jasiukajtis 1.71861929812247793414e+00, /* 3FFB7F76F2FB5E47 */ 8025c28e83SPiotr Jasiukajtis 1.75625216037329945351e+00, /* 3FFC199BDD85529C */ 8125c28e83SPiotr Jasiukajtis 1.79470907500310716820e+00, /* 3FFCB720DCEF9069 */ 8225c28e83SPiotr Jasiukajtis 1.83400808640934243066e+00, /* 3FFD5818DCFBA487 */ 8325c28e83SPiotr Jasiukajtis 1.87416763411029996256e+00, /* 3FFDFC97337B9B5F */ 8425c28e83SPiotr Jasiukajtis 1.91520656139714740007e+00, /* 3FFEA4AFA2A490DA */ 8525c28e83SPiotr Jasiukajtis 1.95714412417540017941e+00, /* 3FFF50765B6E4540 */ 8625c28e83SPiotr Jasiukajtis }; 8725c28e83SPiotr Jasiukajtis 8825c28e83SPiotr Jasiukajtis static const double TBL[] = { 8925c28e83SPiotr Jasiukajtis 0.00000000000000000e+00, 9025c28e83SPiotr Jasiukajtis 3.07716586667536873e-02, 9125c28e83SPiotr Jasiukajtis 6.06246218164348399e-02, 9225c28e83SPiotr Jasiukajtis 8.96121586896871380e-02, 9325c28e83SPiotr Jasiukajtis 1.17783035656383456e-01, 9425c28e83SPiotr Jasiukajtis 1.45182009844497889e-01, 9525c28e83SPiotr Jasiukajtis 1.71850256926659228e-01, 9625c28e83SPiotr Jasiukajtis 1.97825743329919868e-01, 9725c28e83SPiotr Jasiukajtis 2.23143551314209765e-01, 9825c28e83SPiotr Jasiukajtis 2.47836163904581269e-01, 9925c28e83SPiotr Jasiukajtis 2.71933715483641758e-01, 10025c28e83SPiotr Jasiukajtis 2.95464212893835898e-01, 10125c28e83SPiotr Jasiukajtis 3.18453731118534589e-01, 10225c28e83SPiotr Jasiukajtis 3.40926586970593193e-01, 10325c28e83SPiotr Jasiukajtis 3.62905493689368475e-01, 10425c28e83SPiotr Jasiukajtis 3.84411698910332056e-01, 10525c28e83SPiotr Jasiukajtis 4.05465108108164385e-01, 10625c28e83SPiotr Jasiukajtis 4.26084395310900088e-01, 10725c28e83SPiotr Jasiukajtis 4.46287102628419530e-01, 10825c28e83SPiotr Jasiukajtis 4.66089729924599239e-01, 10925c28e83SPiotr Jasiukajtis 4.85507815781700824e-01, 11025c28e83SPiotr Jasiukajtis 5.04556010752395312e-01, 11125c28e83SPiotr Jasiukajtis 5.23248143764547868e-01, 11225c28e83SPiotr Jasiukajtis 5.41597282432744409e-01, 11325c28e83SPiotr Jasiukajtis 5.59615787935422659e-01, 11425c28e83SPiotr Jasiukajtis 5.77315365034823613e-01, 11525c28e83SPiotr Jasiukajtis 5.94707107746692776e-01, 11625c28e83SPiotr Jasiukajtis 6.11801541105992941e-01, 11725c28e83SPiotr Jasiukajtis 6.28608659422374094e-01, 11825c28e83SPiotr Jasiukajtis 6.45137961373584701e-01, 11925c28e83SPiotr Jasiukajtis 6.61398482245365016e-01, 12025c28e83SPiotr Jasiukajtis 6.77398823591806143e-01, 12125c28e83SPiotr Jasiukajtis }; 12225c28e83SPiotr Jasiukajtis 12325c28e83SPiotr Jasiukajtis static const float zero = 0.0F, one = 1.0F, huge = 1.0e25f, tiny = 1.0e-25f; 12425c28e83SPiotr Jasiukajtis /* INDENT ON */ 12525c28e83SPiotr Jasiukajtis 12625c28e83SPiotr Jasiukajtis float 12725c28e83SPiotr Jasiukajtis powf(float x, float y) { 12825c28e83SPiotr Jasiukajtis float fx = x, fy = y; 12925c28e83SPiotr Jasiukajtis float fz; 13025c28e83SPiotr Jasiukajtis int ix, iy, jx, jy, k, iw, yisint; 13125c28e83SPiotr Jasiukajtis 13225c28e83SPiotr Jasiukajtis ix = *(int *)&x; 13325c28e83SPiotr Jasiukajtis iy = *(int *)&y; 13425c28e83SPiotr Jasiukajtis jx = ix & ~0x80000000; 13525c28e83SPiotr Jasiukajtis jy = iy & ~0x80000000; 13625c28e83SPiotr Jasiukajtis 13725c28e83SPiotr Jasiukajtis if (jy == 0) 13825c28e83SPiotr Jasiukajtis return (one); /* x**+-0 = 1 */ 13925c28e83SPiotr Jasiukajtis else if (ix == 0x3f800000 && (__xpg6 & _C99SUSv3_pow) != 0) 14025c28e83SPiotr Jasiukajtis return (one); /* C99: 1**anything = 1 */ 14125c28e83SPiotr Jasiukajtis else if (((0x7f800000 - jx) | (0x7f800000 - jy)) < 0) 14225c28e83SPiotr Jasiukajtis return (fx * fy); /* at least one of x or y is NaN */ 14325c28e83SPiotr Jasiukajtis /* includes Sun: 1**NaN = NaN */ 14425c28e83SPiotr Jasiukajtis /* INDENT OFF */ 14525c28e83SPiotr Jasiukajtis /* 14625c28e83SPiotr Jasiukajtis * determine if y is an odd int 14725c28e83SPiotr Jasiukajtis * yisint = 0 ... y is not an integer 14825c28e83SPiotr Jasiukajtis * yisint = 1 ... y is an odd int 14925c28e83SPiotr Jasiukajtis * yisint = 2 ... y is an even int 15025c28e83SPiotr Jasiukajtis */ 15125c28e83SPiotr Jasiukajtis /* INDENT ON */ 15225c28e83SPiotr Jasiukajtis yisint = 0; 15325c28e83SPiotr Jasiukajtis if (ix < 0) { 15425c28e83SPiotr Jasiukajtis if (jy >= 0x4b800000) { 15525c28e83SPiotr Jasiukajtis yisint = 2; /* |y|>=2**24: y must be even */ 15625c28e83SPiotr Jasiukajtis } else if (jy >= 0x3f800000) { 15725c28e83SPiotr Jasiukajtis k = (jy >> 23) - 0x7f; /* exponent */ 15825c28e83SPiotr Jasiukajtis iw = jy >> (23 - k); 15925c28e83SPiotr Jasiukajtis if ((iw << (23 - k)) == jy) 16025c28e83SPiotr Jasiukajtis yisint = 2 - (iw & 1); 16125c28e83SPiotr Jasiukajtis } 16225c28e83SPiotr Jasiukajtis } 16325c28e83SPiotr Jasiukajtis 16425c28e83SPiotr Jasiukajtis /* special value of y */ 16525c28e83SPiotr Jasiukajtis if ((jy & ~0x7f800000) == 0) { 16625c28e83SPiotr Jasiukajtis if (jy == 0x7f800000) { /* y is +-inf */ 16725c28e83SPiotr Jasiukajtis if (jx == 0x3f800000) { 16825c28e83SPiotr Jasiukajtis if ((__xpg6 & _C99SUSv3_pow) != 0) 16925c28e83SPiotr Jasiukajtis fz = one; 17025c28e83SPiotr Jasiukajtis /* C99: (-1)**+-inf is 1 */ 17125c28e83SPiotr Jasiukajtis else 17225c28e83SPiotr Jasiukajtis fz = fy - fy; 17325c28e83SPiotr Jasiukajtis /* Sun: (+-1)**+-inf = NaN */ 17425c28e83SPiotr Jasiukajtis } else if (jx > 0x3f800000) { 17525c28e83SPiotr Jasiukajtis /* (|x|>1)**+,-inf = inf,0 */ 17625c28e83SPiotr Jasiukajtis if (iy > 0) 17725c28e83SPiotr Jasiukajtis fz = fy; 17825c28e83SPiotr Jasiukajtis else 17925c28e83SPiotr Jasiukajtis fz = zero; 18025c28e83SPiotr Jasiukajtis } else { /* (|x|<1)**-,+inf = inf,0 */ 18125c28e83SPiotr Jasiukajtis if (iy < 0) 18225c28e83SPiotr Jasiukajtis fz = -fy; 18325c28e83SPiotr Jasiukajtis else 18425c28e83SPiotr Jasiukajtis fz = zero; 18525c28e83SPiotr Jasiukajtis } 18625c28e83SPiotr Jasiukajtis return (fz); 18725c28e83SPiotr Jasiukajtis } else if (jy == 0x3f800000) { /* y is +-1 */ 18825c28e83SPiotr Jasiukajtis if (iy < 0) 18925c28e83SPiotr Jasiukajtis fx = one / fx; /* y is -1 */ 19025c28e83SPiotr Jasiukajtis return (fx); 19125c28e83SPiotr Jasiukajtis } else if (iy == 0x40000000) { /* y is 2 */ 19225c28e83SPiotr Jasiukajtis return (fx * fx); 19325c28e83SPiotr Jasiukajtis } else if (iy == 0x3f000000) { /* y is 0.5 */ 19425c28e83SPiotr Jasiukajtis if (jx != 0 && jx != 0x7f800000) 19525c28e83SPiotr Jasiukajtis return (sqrtf(x)); 19625c28e83SPiotr Jasiukajtis } 19725c28e83SPiotr Jasiukajtis } 19825c28e83SPiotr Jasiukajtis 19925c28e83SPiotr Jasiukajtis /* special value of x */ 20025c28e83SPiotr Jasiukajtis if ((jx & ~0x7f800000) == 0) { 20125c28e83SPiotr Jasiukajtis if (jx == 0x7f800000 || jx == 0 || jx == 0x3f800000) { 20225c28e83SPiotr Jasiukajtis /* x is +-0,+-inf,-1; set fz = |x|**y */ 20325c28e83SPiotr Jasiukajtis *(int *)&fz = jx; 20425c28e83SPiotr Jasiukajtis if (iy < 0) 20525c28e83SPiotr Jasiukajtis fz = one / fz; 20625c28e83SPiotr Jasiukajtis if (ix < 0) { 20725c28e83SPiotr Jasiukajtis if (jx == 0x3f800000 && yisint == 0) { 20825c28e83SPiotr Jasiukajtis /* (-1)**non-int is NaN */ 20925c28e83SPiotr Jasiukajtis fz = zero; 21025c28e83SPiotr Jasiukajtis fz /= fz; 21125c28e83SPiotr Jasiukajtis } else if (yisint == 1) { 21225c28e83SPiotr Jasiukajtis /* (x<0)**odd = -(|x|**odd) */ 21325c28e83SPiotr Jasiukajtis fz = -fz; 21425c28e83SPiotr Jasiukajtis } 21525c28e83SPiotr Jasiukajtis } 21625c28e83SPiotr Jasiukajtis return (fz); 21725c28e83SPiotr Jasiukajtis } 21825c28e83SPiotr Jasiukajtis } 21925c28e83SPiotr Jasiukajtis 22025c28e83SPiotr Jasiukajtis /* (x<0)**(non-int) is NaN */ 22125c28e83SPiotr Jasiukajtis if (ix < 0 && yisint == 0) { 22225c28e83SPiotr Jasiukajtis fz = zero; 22325c28e83SPiotr Jasiukajtis return (fz / fz); 22425c28e83SPiotr Jasiukajtis } 22525c28e83SPiotr Jasiukajtis 22625c28e83SPiotr Jasiukajtis /* 22725c28e83SPiotr Jasiukajtis * compute exp(y*log(|x|)) 22825c28e83SPiotr Jasiukajtis * fx = *(float *) &jx; 22925c28e83SPiotr Jasiukajtis * fz = (float) exp(((double) fy) * log((double) fx)); 23025c28e83SPiotr Jasiukajtis */ 23125c28e83SPiotr Jasiukajtis { 23225c28e83SPiotr Jasiukajtis double dx, dy, dz, ds; 23325c28e83SPiotr Jasiukajtis int *px = (int *)&dx, *pz = (int *)&dz, i, n, m; 23425c28e83SPiotr Jasiukajtis #if defined(__i386) && !defined(__amd64) 23525c28e83SPiotr Jasiukajtis int rp = __swapRP(fp_extended); 23625c28e83SPiotr Jasiukajtis #endif 23725c28e83SPiotr Jasiukajtis 23825c28e83SPiotr Jasiukajtis fx = *(float *)&jx; 23925c28e83SPiotr Jasiukajtis dx = (double)fx; 24025c28e83SPiotr Jasiukajtis 24125c28e83SPiotr Jasiukajtis /* compute log(x)/ln2 */ 24225c28e83SPiotr Jasiukajtis i = px[HIWORD] + 0x4000; 24325c28e83SPiotr Jasiukajtis n = (i >> 20) - 0x3ff; 24425c28e83SPiotr Jasiukajtis pz[HIWORD] = i & 0xffff8000; 24525c28e83SPiotr Jasiukajtis pz[LOWORD] = 0; 24625c28e83SPiotr Jasiukajtis ds = (dx - dz) / (dx + dz); 24725c28e83SPiotr Jasiukajtis i = (i >> 15) & 0x1f; 24825c28e83SPiotr Jasiukajtis dz = ds * ds; 24925c28e83SPiotr Jasiukajtis dy = invln2 * (TBL[i] + ds * (A0 + dz * A1)); 25025c28e83SPiotr Jasiukajtis if (n == 0) 25125c28e83SPiotr Jasiukajtis dz = (double)fy * dy; 25225c28e83SPiotr Jasiukajtis else 25325c28e83SPiotr Jasiukajtis dz = (double)fy * (dy + (double)n); 25425c28e83SPiotr Jasiukajtis 25525c28e83SPiotr Jasiukajtis /* compute exp2(dz=y*ln(x)) */ 25625c28e83SPiotr Jasiukajtis i = pz[HIWORD]; 25725c28e83SPiotr Jasiukajtis if ((i & ~0x80000000) >= 0x40640000) { /* |z| >= 160.0 */ 25825c28e83SPiotr Jasiukajtis fz = (i > 0)? huge : tiny; 25925c28e83SPiotr Jasiukajtis if (ix < 0 && yisint == 1) 26025c28e83SPiotr Jasiukajtis fz *= -fz; /* (-ve)**(odd int) */ 26125c28e83SPiotr Jasiukajtis else 26225c28e83SPiotr Jasiukajtis fz *= fz; 26325c28e83SPiotr Jasiukajtis #if defined(__i386) && !defined(__amd64) 26425c28e83SPiotr Jasiukajtis if (rp != fp_extended) 26525c28e83SPiotr Jasiukajtis (void) __swapRP(rp); 26625c28e83SPiotr Jasiukajtis #endif 26725c28e83SPiotr Jasiukajtis return (fz); 26825c28e83SPiotr Jasiukajtis } 26925c28e83SPiotr Jasiukajtis 27025c28e83SPiotr Jasiukajtis n = (int)(d32 * dz + (i > 0 ? dhalf : -dhalf)); 27125c28e83SPiotr Jasiukajtis i = n & 0x1f; 27225c28e83SPiotr Jasiukajtis m = n >> 5; 27325c28e83SPiotr Jasiukajtis dy = ln2 * (dz - d1_32 * (double)n); 27425c28e83SPiotr Jasiukajtis dx = S[i] * (done - (dtwo * dy) / (dy * (done - dy * t1) - t0)); 27525c28e83SPiotr Jasiukajtis if (m != 0) 27625c28e83SPiotr Jasiukajtis px[HIWORD] += m << 20; 27725c28e83SPiotr Jasiukajtis fz = (float)dx; 27825c28e83SPiotr Jasiukajtis #if defined(__i386) && !defined(__amd64) 27925c28e83SPiotr Jasiukajtis if (rp != fp_extended) 28025c28e83SPiotr Jasiukajtis (void) __swapRP(rp); 28125c28e83SPiotr Jasiukajtis #endif 28225c28e83SPiotr Jasiukajtis } 28325c28e83SPiotr Jasiukajtis 28425c28e83SPiotr Jasiukajtis /* end of computing exp(y*log(x)) */ 28525c28e83SPiotr Jasiukajtis if (ix < 0 && yisint == 1) 28625c28e83SPiotr Jasiukajtis fz = -fz; /* (-ve)**(odd int) */ 28725c28e83SPiotr Jasiukajtis return (fz); 28825c28e83SPiotr Jasiukajtis } 289