00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 static char *rcs_id = "$Source: /home/bos/bk/kpro64-pending/libm/mips/SCCS/s.powf.c $ $Revision: 1.5 $";
00060
00061 #ifdef _CALL_MATHERR
00062 #include <stdio.h>
00063 #include <math.h>
00064 #include <errno.h>
00065 #endif
00066
00067 #include "libm.h"
00068
00069 extern double __log(double);
00070 extern double __exp(double);
00071
00072 #if defined(mips) && !defined(__GNUC__)
00073 extern float fpow(float, float);
00074 extern float powf(float, float);
00075
00076 #pragma weak fpow = __powf
00077 #pragma weak powf = __powf
00078 #endif
00079
00080 #if defined(BUILD_OS_DARWIN)
00081 extern float __powf(float, float);
00082 #pragma weak powf
00083 float powf( float x, float y ) {
00084 return __powf( x, y );
00085 }
00086 #elif defined(__GNUC__)
00087 extern float __powf(float, float);
00088 float powf(float, float) __attribute__ ((weak, alias ("__powf")));
00089 #endif
00090
00091 static const du Neginf =
00092 {D(0xfff00000, 0x00000000)};
00093
00094 static const du Inf =
00095 {D(0x7ff00000, 0x00000000)};
00096
00097 static const du twopm25 =
00098 {D(0x3c800000, 0x00000000)};
00099
00100 static const du log2 =
00101 {D(0x3fe62e42, 0xfefa39ef)};
00102
00103 static const du ylimit =
00104 {D(0x41d9fe36, 0x60000000)};
00105
00106 static const du Ulimit =
00107 {D(0x40562e42, 0xfeda39ef)};
00108
00109 static const du Llimit =
00110 {D(0xc059fe36, 0x82cd3be4)};
00111
00112 static const du twopm128 =
00113 {D(0x37f00000, 0x00000000)};
00114
00115 static const du twopm75 =
00116 {D(0x3b400000, 0x00000000)};
00117
00118 static const du twop64 =
00119 {D(0x43f00000, 0x00000000)};
00120
00121 static const fu Qnan = {QNANF};
00122
00123 static const fu Neginf_s = {0x7f800000};
00124
00125 static const fu Inf_s = {0x7f800000};
00126
00127 static const fu twop23 = {0x4b000000};
00128
00129 static const fu twop24 = {0x4b800000};
00130
00131 static const fu Magic = {0x4b400000};
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 float
00144 __powf( float x, float y )
00145 {
00146 int iy, ix, xpty, xptx;
00147 int n;
00148 int i, j;
00149 int signx;
00150 float sign;
00151 float u;
00152 float fresult;
00153 double w;
00154 double dx, dy;
00155 double z;
00156 double result;
00157 #ifdef _CALL_MATHERR
00158 struct exception exstruct;
00159 #endif
00160
00161
00162
00163
00164 sign = 1.0f;
00165
00166 FLT2INT(x, ix);
00167 n = (ix >> MANTWIDTH);
00168 signx = ((n >> EXPWIDTH) & 1);
00169 xptx = (n & 0xff);
00170
00171 FLT2INT(y, iy);
00172 xpty = (iy >> MANTWIDTH);
00173 xpty &= 0xff;
00174
00175 dx = x;
00176 dy = y;
00177
00178
00179
00180
00181
00182 i = (dx == 0.0) | (xptx == 0xff) | (ix <= 0);
00183 j = (dy == 0.0) | (xpty == 0xff) | (fabs(dy) == 1.0);
00184
00185 if ( i + j != 0 )
00186 goto special;
00187
00188 L:
00189 if ( dx == 1.0 )
00190 goto xeqone;
00191
00192 if ( dx == 2.0 )
00193 goto xeqtwo;
00194
00195 if ( dy == 2.0 )
00196 goto yeqtwo;
00197
00198 if ( fabs(dy) > ylimit.d )
00199 goto overunder;
00200
00201 w = __log( dx );
00202
00203 z = dy*w;
00204
00205 if ( fabs(z) < twopm25.d )
00206 {
00207 return ( sign*1.0f );
00208 }
00209
00210
00211
00212 if ( z < Llimit.d )
00213 {
00214
00215
00216 #ifdef _CALL_MATHERR
00217
00218 exstruct.type = UNDERFLOW;
00219 exstruct.name = "powf";
00220 exstruct.arg1 = x;
00221 exstruct.arg2 = y;
00222 exstruct.retval = sign*0.0f;
00223
00224 if ( matherr( &exstruct ) == 0 )
00225 {
00226 fprintf(stderr, "underflow range error in powf\n");
00227 SETERRNO(ERANGE);
00228 }
00229
00230 return ( exstruct.retval );
00231 #else
00232
00233 SETERRNO(ERANGE);
00234
00235 return ( sign*0.0f );
00236 #endif
00237 }
00238
00239 if ( z > Ulimit.d )
00240 {
00241
00242
00243 #ifdef _CALL_MATHERR
00244
00245 exstruct.type = OVERFLOW;
00246 exstruct.name = "powf";
00247 exstruct.arg1 = x;
00248 exstruct.arg2 = y;
00249 exstruct.retval = (sign > 0.0f) ? Inf_s.f : Neginf_s.f;
00250
00251 if ( matherr( &exstruct ) == 0 )
00252 {
00253 fprintf(stderr, "overflow range error in powf\n");
00254 SETERRNO(ERANGE);
00255 }
00256
00257 return ( exstruct.retval );
00258 #else
00259
00260 SETERRNO(ERANGE);
00261
00262 return ( (sign > 0.0f) ? Inf_s.f : Neginf_s.f );
00263 #endif
00264 }
00265
00266 result = sign*__exp(z);
00267
00268 return ( (float)result );
00269
00270 special:
00271 if ( dy == 0.0 )
00272 return ( 1.0f );
00273
00274 if ( dy == 1.0 )
00275 return ( x );
00276
00277 if ( (y != y) || (x != x) )
00278 {
00279
00280
00281 #ifdef _CALL_MATHERR
00282
00283 exstruct.type = DOMAIN;
00284 exstruct.name = "powf";
00285 exstruct.arg1 = x;
00286 exstruct.arg2 = y;
00287 exstruct.retval = Qnan.f;
00288
00289 if ( matherr( &exstruct ) == 0 )
00290 {
00291 fprintf(stderr, "domain error in powf\n");
00292 SETERRNO(EDOM);
00293 }
00294
00295 return ( exstruct.retval );
00296 #else
00297 NAN_SETERRNO(EDOM);
00298
00299 return ( Qnan.f );
00300 #endif
00301 }
00302
00303 if ( (dy == Inf.d) && (dx != 0.0) )
00304 {
00305 if ( fabs(dx) > 1.0 )
00306 {
00307
00308
00309 #ifdef _CALL_MATHERR
00310
00311 exstruct.type = OVERFLOW;
00312 exstruct.name = "powf";
00313 exstruct.arg1 = x;
00314 exstruct.arg2 = y;
00315 exstruct.retval = Inf_s.f;
00316
00317 if ( matherr( &exstruct ) == 0 )
00318 {
00319 fprintf(stderr, "overflow range error in powf\n");
00320 SETERRNO(ERANGE);
00321 }
00322
00323 return ( exstruct.retval );
00324 #else
00325
00326 SETERRNO(ERANGE);
00327
00328 return ( Inf_s.f );
00329 #endif
00330 }
00331
00332 if ( fabs(dx) < 1.0 )
00333 {
00334
00335
00336 #ifdef _CALL_MATHERR
00337
00338 exstruct.type = UNDERFLOW;
00339 exstruct.name = "powf";
00340 exstruct.arg1 = x;
00341 exstruct.arg2 = y;
00342 exstruct.retval = 0.0f;
00343
00344 if ( matherr( &exstruct ) == 0 )
00345 {
00346 fprintf(stderr, "underflow range error in powf\n");
00347 SETERRNO(ERANGE);
00348 }
00349
00350 return ( exstruct.retval );
00351 #else
00352
00353 SETERRNO(ERANGE);
00354
00355 return ( 0.0f );
00356 #endif
00357 }
00358 }
00359
00360 if ( (dy == Neginf.d) && (dx != 0.0) )
00361 {
00362 if ( fabs(dx) < 1.0 )
00363 {
00364
00365
00366 #ifdef _CALL_MATHERR
00367
00368 exstruct.type = OVERFLOW;
00369 exstruct.name = "powf";
00370 exstruct.arg1 = x;
00371 exstruct.arg2 = y;
00372 exstruct.retval = Inf_s.f;
00373
00374 if ( matherr( &exstruct ) == 0 )
00375 {
00376 fprintf(stderr, "overflow range error in powf\n");
00377 SETERRNO(ERANGE);
00378 }
00379
00380 return ( exstruct.retval );
00381 #else
00382
00383 SETERRNO(ERANGE);
00384
00385 return ( Inf_s.f );
00386 #endif
00387 }
00388
00389 if ( fabs(dx) > 1.0 )
00390 {
00391
00392
00393 #ifdef _CALL_MATHERR
00394
00395 exstruct.type = UNDERFLOW;
00396 exstruct.name = "powf";
00397 exstruct.arg1 = x;
00398 exstruct.arg2 = y;
00399 exstruct.retval = 0.0f;
00400
00401 if ( matherr( &exstruct ) == 0 )
00402 {
00403 fprintf(stderr, "underflow range error in powf\n");
00404 SETERRNO(ERANGE);
00405 }
00406
00407 return ( exstruct.retval );
00408 #else
00409
00410 SETERRNO(ERANGE);
00411
00412 return ( 0.0f );
00413 #endif
00414 }
00415 }
00416
00417 if ( (dx == 1.0) && (fabs(dy) == Inf.d) )
00418 return ( 1.0f );
00419
00420 if ( (dx == -1.0) && (fabs(dy) == Inf.d) )
00421 {
00422
00423
00424 #ifdef _CALL_MATHERR
00425
00426 exstruct.type = DOMAIN;
00427 exstruct.name = "powf";
00428 exstruct.arg1 = x;
00429 exstruct.arg2 = y;
00430 exstruct.retval = Qnan.f;
00431
00432 if ( matherr( &exstruct ) == 0 )
00433 {
00434 fprintf(stderr, "domain error in powf\n");
00435 SETERRNO(ERANGE);
00436 }
00437
00438 return ( exstruct.retval );
00439 #else
00440
00441 SETERRNO(ERANGE);
00442
00443 return ( Qnan.f );
00444 #endif
00445 }
00446
00447 if ( (dx == 0.0) && (signx == 0) )
00448 {
00449 if ( dy > 0.0 )
00450 return ( 0.0f );
00451
00452 if ( dy < 0.0 )
00453 {
00454
00455
00456 #ifdef _CALL_MATHERR
00457
00458 exstruct.type = OVERFLOW;
00459 exstruct.name = "powf";
00460 exstruct.arg1 = x;
00461 exstruct.arg2 = y;
00462 exstruct.retval = Inf_s.f;
00463
00464 if ( matherr( &exstruct ) == 0 )
00465 {
00466 fprintf(stderr, "overflow range error in powf\n");
00467 SETERRNO(ERANGE);
00468 }
00469
00470 return ( exstruct.retval );
00471 #else
00472
00473 SETERRNO(ERANGE);
00474
00475 return ( Inf_s.f );
00476 #endif
00477 }
00478 }
00479
00480 if ( dy == -1.0 )
00481 {
00482 if ( fabs(dx) > twopm128.d )
00483 {
00484 return ( 1/x );
00485 }
00486
00487
00488
00489 #ifdef _CALL_MATHERR
00490
00491 exstruct.type = OVERFLOW;
00492 exstruct.name = "powf";
00493 exstruct.arg1 = x;
00494 exstruct.arg2 = y;
00495 exstruct.retval = (dx > 0.0) ? Inf_s.f : Neginf_s.f;
00496
00497 if ( matherr( &exstruct ) == 0 )
00498 {
00499 fprintf(stderr, "overflow range error in powf\n");
00500 SETERRNO(ERANGE);
00501 }
00502
00503 return ( exstruct.retval );
00504 #else
00505
00506 SETERRNO(ERANGE);
00507
00508 if ( dx > 0.0 )
00509 return ( Inf_s.f );
00510 else
00511 return ( Neginf_s.f );
00512 #endif
00513 }
00514
00515 if ( (x == 0.0) && (signx != 0) )
00516 {
00517
00518
00519 if ( fabsf(y) >= twop24.f )
00520 {
00521 goto next;
00522 }
00523 else if ( fabsf(y) >= twop23.f )
00524 {
00525
00526
00527 n = y;
00528 }
00529 else
00530 {
00531 u = y + Magic.f;
00532
00533 u = u - Magic.f;
00534
00535 if ( u != y )
00536 {
00537
00538
00539 goto next;
00540 }
00541
00542 n = y;
00543
00544 }
00545
00546 if ( (n&1) == 1 )
00547 {
00548 if ( dy > 0.0 )
00549 return ( -0.0f );
00550 else
00551 {
00552
00553
00554 #ifdef _CALL_MATHERR
00555
00556 exstruct.type = OVERFLOW;
00557 exstruct.name = "powf";
00558 exstruct.arg1 = x;
00559 exstruct.arg2 = y;
00560 exstruct.retval = Neginf_s.f;
00561
00562 if ( matherr( &exstruct ) == 0 )
00563 {
00564 fprintf(stderr, "overflow range error in powf\n");
00565 SETERRNO(ERANGE);
00566 }
00567
00568 return ( exstruct.retval );
00569 #else
00570
00571 SETERRNO(ERANGE);
00572
00573 return ( Neginf_s.f );
00574 #endif
00575 }
00576
00577 }
00578
00579 next:
00580 if ( dy > 0.0 )
00581 return ( 0.0f );
00582
00583 if ( dy < 0.0 )
00584 {
00585
00586
00587 #ifdef _CALL_MATHERR
00588
00589 exstruct.type = OVERFLOW;
00590 exstruct.name = "powf";
00591 exstruct.arg1 = x;
00592 exstruct.arg2 = y;
00593 exstruct.retval = Inf_s.f;
00594
00595 if ( matherr( &exstruct ) == 0 )
00596 {
00597 fprintf(stderr, "overflow range error in powf\n");
00598 SETERRNO(ERANGE);
00599 }
00600
00601 return ( exstruct.retval );
00602 #else
00603
00604 SETERRNO(ERANGE);
00605
00606 return ( Inf_s.f );
00607 #endif
00608 }
00609 }
00610
00611 if ( dx == Inf.d )
00612 {
00613 if ( dy > 0.0 )
00614 return ( Inf_s.f );
00615
00616 if ( dy < 0.0 )
00617 return ( 0.0f );
00618 }
00619
00620 if ( dx == Neginf.d )
00621 {
00622
00623
00624 if ( fabsf(y) >= twop24.f )
00625 {
00626 goto next_2;
00627 }
00628 else if ( fabsf(y) >= twop23.f )
00629 {
00630
00631
00632 n = y;
00633 }
00634 else
00635 {
00636 u = y + Magic.f;
00637
00638 u = u - Magic.f;
00639
00640 if ( u != y )
00641 {
00642
00643
00644 goto next_2;
00645 }
00646
00647 n = y;
00648 }
00649
00650 if ( (n&1) == 1 )
00651 {
00652 if ( dy > 0.0 )
00653 return ( Neginf_s.f );
00654 else
00655 return ( -0.0f );
00656
00657 }
00658
00659 next_2:
00660 if ( dy > 0.0 )
00661 return ( Inf_s.f );
00662
00663 if ( dy < 0.0 )
00664 return ( 0.0f );
00665 }
00666
00667 if ( dx < 0.0 )
00668 {
00669
00670
00671 if ( fabsf(y) >= twop24.f )
00672 {
00673 sign = 1.0f;
00674 }
00675 else if ( fabsf(y) >= twop23.f )
00676 {
00677
00678
00679 n = y;
00680
00681 if ( n%2 == 0 )
00682 {
00683 sign = 1.0f;
00684 }
00685 else
00686 {
00687 sign = -1.0f;
00688 }
00689 }
00690 else
00691 {
00692
00693
00694 u = y + Magic.f;
00695 u = u - Magic.f;
00696 n = u;
00697
00698 if ( u != y )
00699 {
00700
00701
00702 #ifdef _CALL_MATHERR
00703
00704 exstruct.type = DOMAIN;
00705 exstruct.name = "powf";
00706 exstruct.arg1 = x;
00707 exstruct.arg2 = y;
00708 exstruct.retval = Qnan.f;
00709
00710 if ( matherr( &exstruct ) == 0 )
00711 {
00712 fprintf(stderr, "domain error in powf\n");
00713 SETERRNO(EDOM);
00714 }
00715
00716 return ( exstruct.retval );
00717 #else
00718
00719 SETERRNO(EDOM);
00720
00721 return ( Qnan.f );
00722 #endif
00723 }
00724
00725 if ( n%2 == 0 )
00726 {
00727 sign = 1.0f;
00728 }
00729 else
00730 {
00731 sign = -1.0f;
00732 }
00733 }
00734
00735 dx = fabs(dx);
00736 }
00737
00738 goto L;
00739
00740 xeqone:
00741 return ( sign );
00742
00743 xeqtwo:
00744 w = log2.d;
00745
00746 if ( fabs(dy) < twopm25.d )
00747 {
00748 return ( sign*1.0f );
00749 }
00750
00751
00752
00753 if ( dy <= -150.0 )
00754 {
00755
00756
00757 #ifdef _CALL_MATHERR
00758
00759 exstruct.type = UNDERFLOW;
00760 exstruct.name = "powf";
00761 exstruct.arg1 = x;
00762 exstruct.arg2 = y;
00763 exstruct.retval = sign*0.0f;
00764
00765 if ( matherr( &exstruct ) == 0 )
00766 {
00767 fprintf(stderr, "underflow range error in powf\n");
00768 SETERRNO(ERANGE);
00769 }
00770
00771 return ( exstruct.retval );
00772 #else
00773
00774 SETERRNO(ERANGE);
00775
00776 return ( sign*0.0f );
00777 #endif
00778 }
00779
00780 if ( dy >= 1024.0 )
00781 {
00782
00783
00784 #ifdef _CALL_MATHERR
00785
00786 exstruct.type = OVERFLOW;
00787 exstruct.name = "powf";
00788 exstruct.arg1 = x;
00789 exstruct.arg2 = y;
00790 exstruct.retval = (sign > 0.0f) ? Inf_s.f : Neginf_s.f;
00791
00792 if ( matherr( &exstruct ) == 0 )
00793 {
00794 fprintf(stderr, "overflow range error in powf\n");
00795 SETERRNO(ERANGE);
00796 }
00797
00798 return ( exstruct.retval );
00799 #else
00800
00801 SETERRNO(ERANGE);
00802
00803 return ( (sign > 0.0f) ? Inf_s.f : Neginf_s.f );
00804 #endif
00805 }
00806
00807 z = dy*w;
00808
00809 fresult = sign*__exp(z);
00810
00811 if ( fresult == 0.0f )
00812 {
00813
00814
00815 #ifdef _CALL_MATHERR
00816
00817 exstruct.type = UNDERFLOW;
00818 exstruct.name = "powf";
00819 exstruct.arg1 = x;
00820 exstruct.arg2 = y;
00821 exstruct.retval = fresult;
00822
00823 if ( matherr( &exstruct ) == 0 )
00824 {
00825 fprintf(stderr, "underflow range error in powf\n");
00826 SETERRNO(ERANGE);
00827 }
00828
00829 return ( exstruct.retval );
00830 #else
00831
00832 SETERRNO(ERANGE);
00833
00834 return ( fresult );
00835 #endif
00836 }
00837
00838 return ( fresult );
00839
00840 yeqtwo:
00841 if ( fabs(dx) >= twop64.d )
00842 {
00843
00844
00845 #ifdef _CALL_MATHERR
00846
00847 exstruct.type = OVERFLOW;
00848 exstruct.name = "powf";
00849 exstruct.arg1 = x;
00850 exstruct.arg2 = y;
00851 exstruct.retval = Inf_s.f;
00852
00853 if ( matherr( &exstruct ) == 0 )
00854 {
00855 fprintf(stderr, "overflow range error in powf\n");
00856 SETERRNO(ERANGE);
00857 }
00858
00859 return ( exstruct.retval );
00860 #else
00861
00862 SETERRNO(ERANGE);
00863
00864 return ( Inf_s.f );
00865 #endif
00866 }
00867
00868 if ( fabs(dx) < twopm75.d )
00869 {
00870
00871
00872 #ifdef _CALL_MATHERR
00873
00874 exstruct.type = UNDERFLOW;
00875 exstruct.name = "powf";
00876 exstruct.arg1 = x;
00877 exstruct.arg2 = y;
00878 exstruct.retval = 0.0f;
00879
00880 if ( matherr( &exstruct ) == 0 )
00881 {
00882 fprintf(stderr, "underflow range error in powf\n");
00883 SETERRNO(ERANGE);
00884 }
00885
00886 return ( exstruct.retval );
00887 #else
00888
00889 SETERRNO(ERANGE);
00890
00891 return ( 0.0f );
00892 #endif
00893 }
00894
00895 return ( x*x );
00896
00897 overunder:
00898
00899
00900
00901
00902
00903 if ( ((dx > 1.0) && (dy > 0.0)) ||
00904 ((dx < 1.0) && (dy < 0.0))
00905 )
00906 {
00907
00908
00909 #ifdef _CALL_MATHERR
00910
00911 exstruct.type = OVERFLOW;
00912 exstruct.name = "powf";
00913 exstruct.arg1 = x;
00914 exstruct.arg2 = y;
00915 exstruct.retval = (sign > 0.0f) ? Inf_s.f : Neginf_s.f;
00916 if ( matherr( &exstruct ) == 0 )
00917 {
00918 fprintf(stderr, "overflow error in powf\n");
00919 SETERRNO(ERANGE);
00920 }
00921
00922 return ( exstruct.retval );
00923 #else
00924
00925 SETERRNO(ERANGE);
00926
00927 return ( (sign > 0.0f) ? Inf_s.f : Neginf_s.f );
00928 #endif
00929 }
00930
00931
00932
00933 #ifdef _CALL_MATHERR
00934
00935 exstruct.type = UNDERFLOW;
00936 exstruct.name = "powf";
00937 exstruct.arg1 = x;
00938 exstruct.arg2 = y;
00939 exstruct.retval = sign*0.0f;
00940
00941 if ( matherr( &exstruct ) == 0 )
00942 {
00943 fprintf(stderr, "underflow error in powf\n");
00944 SETERRNO(ERANGE);
00945 }
00946
00947 return ( exstruct.retval );
00948 #else
00949
00950 SETERRNO(ERANGE);
00951
00952 return ( sign*0.0f );
00953 #endif
00954
00955 }
00956