| /** | |
| * This file has no copyright assigned and is placed in the Public Domain. | |
| * This file is part of the w64 mingw-runtime package. | |
| * No warranty is given; refer to the file DISCLAIMER within this package. | |
| */ | |
| #include "cephes_mconf.h" | |
| #ifndef _SET_ERRNO | |
| #define _SET_ERRNO(x) | |
| #endif | |
| double __powi( x, nn ) | |
| double x; | |
| int nn; | |
| { | |
| int n, e, sign, asign, lx; | |
| double w, y, s; | |
| /* See pow.c for these tests. */ | |
| if( x == 0.0 ) | |
| { | |
| if( nn == 0 ) | |
| return( 1.0 ); | |
| else if( nn < 0 ) | |
| return( INFINITY ); | |
| else | |
| { | |
| if( nn & 1 ) | |
| return( x ); | |
| else | |
| return( 0.0 ); | |
| } | |
| } | |
| if( nn == 0 ) | |
| return( 1.0 ); | |
| if( nn == -1 ) | |
| return( 1.0/x ); | |
| if( x < 0.0 ) | |
| { | |
| asign = -1; | |
| x = -x; | |
| } | |
| else | |
| asign = 0; | |
| if( nn < 0 ) | |
| { | |
| sign = -1; | |
| n = -nn; | |
| } | |
| else | |
| { | |
| sign = 1; | |
| n = nn; | |
| } | |
| /* Even power will be positive. */ | |
| if( (n & 1) == 0 ) | |
| asign = 0; | |
| /* Overflow detection */ | |
| /* Calculate approximate logarithm of answer */ | |
| s = frexp( x, &lx ); | |
| e = (lx - 1)*n; | |
| if( (e == 0) || (e > 64) || (e < -64) ) | |
| { | |
| s = (s - 7.0710678118654752e-1) / (s + 7.0710678118654752e-1); | |
| s = (2.9142135623730950 * s - 0.5 + lx) * nn * LOGE2; | |
| } | |
| else | |
| { | |
| s = LOGE2 * e; | |
| } | |
| if( s > MAXLOG ) | |
| { | |
| mtherr( "powi", OVERFLOW ); | |
| _SET_ERRNO(ERANGE); | |
| y = INFINITY; | |
| goto done; | |
| } | |
| #if DENORMAL | |
| if( s < MINLOG ) | |
| { | |
| y = 0.0; | |
| goto done; | |
| } | |
| /* Handle tiny denormal answer, but with less accuracy | |
| * since roundoff error in 1.0/x will be amplified. | |
| * The precise demarcation should be the gradual underflow threshold. | |
| */ | |
| if( (s < (-MAXLOG+2.0)) && (sign < 0) ) | |
| { | |
| x = 1.0/x; | |
| sign = -sign; | |
| } | |
| #else | |
| /* do not produce denormal answer */ | |
| if( s < -MAXLOG ) | |
| return(0.0); | |
| #endif | |
| /* First bit of the power */ | |
| if( n & 1 ) | |
| y = x; | |
| else | |
| y = 1.0; | |
| w = x; | |
| n >>= 1; | |
| while( n ) | |
| { | |
| w = w * w; /* arg to the 2-to-the-kth power */ | |
| if( n & 1 ) /* if that bit is set, then include in product */ | |
| y *= w; | |
| n >>= 1; | |
| } | |
| if( sign < 0 ) | |
| y = 1.0/y; | |
| done: | |
| if( asign ) | |
| { | |
| /* odd power of negative number */ | |
| if( y == 0.0 ) | |
| y = NEGZERO; | |
| else | |
| y = -y; | |
| } | |
| return(y); | |
| } |