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
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 #ifdef _CALL_MATHERR
00073 #include <stdio.h>
00074 #include <math.h>
00075 #endif
00076
00077 #include <errno.h>
00078 #include "libm.h"
00079
00080 #if defined(mips) && !defined(__GNUC__)
00081 extern int signgam;
00082 extern double gamma(double);
00083 extern double lgamma(double);
00084
00085 #pragma weak signgam = __signgam
00086 #pragma weak gamma = __gamma
00087 #pragma weak lgamma = __lgamma
00088 #endif
00089
00090 #if defined(BUILD_OS_DARWIN)
00091 extern double __gamma(double);
00092 extern double __lgamma(double);
00093 #pragma weak gamma
00094 #pragma weak lgamma
00095 #pragma weak signgam
00096 double gamma(double arg) {
00097 return __gamma(arg);
00098 }
00099 double lgamma( double arg ) {
00100 return __lgamma( arg );
00101 }
00102 int signgam = 0;
00103 #elif defined(__GNUC__)
00104 extern double __gamma(double);
00105
00106 double gamma() __attribute__ ((weak, alias ("__gamma")));
00107
00108 extern double __lgamma(double);
00109
00110 double lgamma() __attribute__ ((weak, alias ("__lgamma")));
00111
00112 extern int __signgam;
00113
00114 extern int signgam __attribute__ ((weak, alias ("__signgam")));
00115
00116 #endif
00117
00118 extern double __floor(double);
00119 extern double __log(double);
00120 extern double __log1p(double);
00121
00122 extern const du __P4[4][2];
00123 extern const du __P5[4][3];
00124 extern const du __P6[4][4];
00125 extern const du __P7[4][5];
00126 extern const du __P8[6];
00127
00128 extern const du __S0[8][8];
00129 extern const du __T0[8][7];
00130
00131 extern const du __S1[7];
00132 extern const du __T1[8];
00133
00134 int __signgam = 0;
00135
00136 double __lgamma(double);
00137
00138 static const du Qnan =
00139 {D(QNANHI, QNANLO)};
00140
00141 static const du Inf = {D(0x7ff00000, 0x00000000)};
00142
00143 static const du twopm54 = {D(0x3c900000, 0x00000000)};
00144
00145 static const du twop100 = {D(0x46300000, 0x00000000)};
00146
00147 static const du twop1000 = {D(0x7e700000, 0x00000000)};
00148
00149 static const du maxarg = {D(0x7f5754d9, 0x278b51a7)};
00150
00151 static const du halfln2pi = {D(0x3fed67f1, 0xc864beb5)};
00152
00153 static const double p1[] = {
00154 0.83333333333333101837e-1,
00155 -.277777777735865004e-2,
00156 0.793650576493454e-3,
00157 -.5951896861197e-3,
00158 0.83645878922e-3,
00159 -.1633436431e-2,
00160 };
00161
00162
00163
00164 static const du p2[] =
00165 {
00166 D(0x3ff00000, 0x00000000),
00167 D(0xbffa51a6, 0x625307d3),
00168 D(0x3fe9f9cb, 0x402bc3f2),
00169 D(0xbfc86a8e, 0x47208961),
00170 D(0x3f9ac680, 0x5cbdb251),
00171 D(0xbf633816, 0x96cdf74f),
00172 D(0x3f237469, 0x5b384e5f),
00173 D(0xbedd3e33, 0x5e638a70),
00174 D(0x3e9070f4, 0x7be9b968),
00175 };
00176
00177 double
00178 __gamma(double arg)
00179 {
00180 double result;
00181
00182 result = __lgamma(arg);
00183
00184 return result;
00185 }
00186
00187
00188 static double asym(double), neg(double), pos(double), lgmapp(int, double);
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 double
00204 __lgamma( double arg )
00205 {
00206 #ifdef _CALL_MATHERR
00207 struct exception exstruct;
00208 #endif
00209
00210 signgam = 1;
00211 #if defined(BUILD_OS_DARWIN)
00212 __signgam = signgam;
00213 #endif
00214
00215 if ( arg != arg )
00216 {
00217
00218
00219 #ifdef _CALL_MATHERR
00220
00221 exstruct.type = DOMAIN;
00222 exstruct.name = "lgamma";
00223 exstruct.arg1 = arg;
00224 exstruct.retval = Qnan.d;
00225
00226 if ( matherr( &exstruct ) == 0 )
00227 {
00228 fprintf(stderr, "domain error in lgamma\n");
00229 SETERRNO(EDOM);
00230 }
00231
00232 return ( exstruct.retval );
00233 #else
00234 NAN_SETERRNO(EDOM);
00235
00236 return ( Qnan.d );
00237 #endif
00238 }
00239
00240 if ( arg <= 0.0 )
00241 return ( neg(arg) );
00242 else
00243 return ( pos(arg) );
00244 }
00245
00246 static
00247 double
00248 pos( double arg )
00249 {
00250 int j, j1, k;
00251 double x0, h;
00252 double result;
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 if ( arg > 8.0 )
00268 return ( asym(arg) );
00269
00270
00271
00272 if ( arg < twopm54.d )
00273 {
00274 return ( -__log(arg) );
00275 }
00276
00277 if ( arg < .875 )
00278 {
00279
00280
00281 j = ROUND(4.0*arg);
00282
00283 x0 = j/4.0;
00284
00285 h = arg - x0;
00286
00287 return ( lgmapp(j+4, h) - __log(arg) );
00288 }
00289
00290 if ( (.875 <= arg) && (arg < 3.125) )
00291 {
00292
00293
00294 if ( (1.875 <= arg) && (arg < 2.1875) )
00295 {
00296
00297
00298 j = 8;
00299 x0 = 2.0;
00300 }
00301 else
00302 {
00303 j = ROUND(4.0*arg);
00304
00305 x0 = j/4.0;
00306 }
00307
00308 h = arg - x0;
00309
00310 return ( lgmapp(j, h) );
00311 }
00312
00313
00314
00315 j = ROUND(4.0*arg);
00316 k = j/4;
00317 x0 = j/4.0;
00318
00319 h = arg - x0;
00320
00321 j1 = j%4;
00322
00323
00324 switch( k )
00325 {
00326 case 3:
00327 result = __log(arg - 1.0) +
00328 lgmapp(j-4, h);
00329 break;
00330
00331 case 4:
00332 result = __log((h + __P4[j1][1].d)*h + __P4[j1][0].d) +
00333 lgmapp(j-8, h);
00334
00335 break;
00336
00337 case 5:
00338 result = __log(((h + __P5[j1][2].d)*h +
00339 __P5[j1][1].d)*h + __P5[j1][0].d) +
00340 lgmapp(j-12, h);
00341
00342 break;
00343
00344 case 6:
00345 result = __log((((h + __P6[j1][3].d)*h +
00346 __P6[j1][2].d)*h + __P6[j1][1].d)*h +
00347 __P6[j1][0].d) +
00348 lgmapp(j-16, h);
00349 break;
00350
00351 case 7:
00352 result = __log(((((h + __P7[j1][4].d)*h +
00353 __P7[j1][3].d)*h + __P7[j1][2].d)*h +
00354 __P7[j1][1].d)*h + __P7[j1][0].d) +
00355 lgmapp(j-20, h);
00356 break;
00357
00358 case 8:
00359 result = __log((((((h + __P8[5].d)*h +
00360 __P8[4].d)*h + __P8[3].d)*h +
00361 __P8[2].d)*h + __P8[1].d)*h +
00362 __P8[0].d) +
00363 lgmapp(j-24, h);
00364 break;
00365 }
00366
00367 return ( result );
00368 }
00369
00370 static
00371 double
00372 neg( double arg )
00373 {
00374 double z, h;
00375 double hsq, result;
00376 double sinpoly;
00377 long n;
00378 #ifdef _CALL_MATHERR
00379 struct exception exstruct;
00380 #endif
00381
00382
00383
00384
00385
00386 z = __floor(arg);
00387
00388 if ( z == arg )
00389 {
00390
00391
00392
00393
00394 #ifdef _CALL_MATHERR
00395
00396 exstruct.type = SING;
00397 exstruct.name = "lgamma";
00398 exstruct.arg1 = arg;
00399 exstruct.retval = Inf.d;
00400
00401 if ( matherr( &exstruct ) == 0 )
00402 {
00403 fprintf(stderr, "singularity error in lgamma\n");
00404 SETERRNO(EDOM);
00405 }
00406
00407 return ( exstruct.retval );
00408 #else
00409 SETERRNO(EDOM);
00410
00411 return ( Inf.d );
00412 #endif
00413 }
00414
00415 n = z;
00416
00417
00418
00419 if ( n&1 ) {
00420 signgam = -1;
00421 #if defined(BUILD_OS_DARWIN)
00422 __signgam = signgam;
00423 #endif
00424 }
00425
00426 h = arg - z;
00427
00428
00429
00430 if ( h > 0.5 )
00431 h = 1.0 - h;
00432
00433
00434
00435 if ( arg > -0.5 )
00436 h = -arg;
00437
00438
00439
00440 hsq = h*h;
00441
00442 sinpoly = (((((((p2[8].d*hsq + p2[7].d)*hsq + p2[6].d)*hsq +
00443 p2[5].d)*hsq + p2[4].d)*hsq + p2[3].d)*hsq +
00444 p2[2].d)*hsq + p2[1].d)*hsq*h + h;
00445
00446 result = -__log(fabs(arg*sinpoly)) - pos(-arg);
00447
00448 return ( result );
00449 }
00450
00451 static
00452 double
00453 asym( double x )
00454 {
00455 double xsq;
00456 double y, num, denom;
00457 double phi, result;
00458 #ifdef _CALL_MATHERR
00459 struct exception exstruct;
00460 #endif
00461
00462 if ( x < 1024.0 )
00463 {
00464
00465
00466
00467
00468 xsq = 1.0/(x*x);
00469
00470 phi = (((((p1[5]*xsq + p1[4])*xsq + p1[3])*xsq + p1[2])*xsq +
00471 p1[1])*xsq + p1[0])/x;
00472
00473 }
00474 else if ( x < twop100.d )
00475 {
00476
00477
00478 y = x*x;
00479 num = x*(11130.0*y + 8659.0);
00480 denom = y*(133560.0*y + 108360.0) + 2340.0;
00481 phi = num/denom;
00482 }
00483 else if ( x < twop1000.d )
00484 {
00485
00486
00487 phi = 1.0/(12.0*x);
00488 }
00489 else if ( x <= maxarg.d )
00490 {
00491
00492
00493
00494
00495 return ( x*(__log(x) - 1.0) );
00496 }
00497 else
00498 {
00499 #ifdef _CALL_MATHERR
00500
00501 exstruct.type = OVERFLOW;
00502 exstruct.name = "lgamma";
00503 exstruct.arg1 = x;
00504 exstruct.retval = Inf.d;
00505
00506 if ( matherr( &exstruct ) == 0 )
00507 {
00508 fprintf(stderr, "overflow error in lgamma\n");
00509 SETERRNO(ERANGE);
00510 }
00511
00512 return ( exstruct.retval );
00513 #else
00514 SETERRNO(ERANGE);
00515
00516 return ( Inf.d );
00517 #endif
00518 }
00519
00520
00521
00522 result = (x - 0.5)*__log(x) - x + halfln2pi.d + phi;
00523
00524 return ( result );
00525 }
00526
00527 static
00528 double
00529 lgmapp( int j, double h )
00530 {
00531 double n, d;
00532 double result;
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545 if ( j == 4 )
00546 {
00547 n = (((((__S1[6].d*h + __S1[5].d)*h + __S1[4].d)*h +
00548 __S1[3].d)*h + __S1[2].d)*h + __S1[1].d)*h + __S1[0].d;
00549
00550 d = ((((((__T1[7].d*h + __T1[6].d)*h + __T1[5].d)*h +
00551 __T1[4].d)*h + __T1[3].d)*h + __T1[2].d)*h +
00552 __T1[1].d)*h + __T1[0].d;
00553
00554 result = h*n/d;
00555
00556 return ( __log1p(result) );
00557 }
00558
00559 n = ((((__S0[j-5][7].d*h + __S0[j-5][6].d)*h + __S0[j-5][5].d)*h +
00560 __S0[j-5][4].d)*h + __S0[j-5][3].d)*h + __S0[j-5][2].d;
00561
00562 d = (((((__T0[j-5][6].d*h + __T0[j-5][5].d)*h + __T0[j-5][4].d)*h +
00563 __T0[j-5][3].d)*h + __T0[j-5][2].d)*h + __T0[j-5][1].d)*h +
00564 __T0[j-5][0].d;
00565
00566 result = __S0[j-5][0].d + (__S0[j-5][1].d + h*n/d);
00567
00568 return ( __log1p(result) );
00569 }
00570
00571 #ifdef NO_LONG_DOUBLE
00572
00573 #if defined(BUILD_OS_DARWIN)
00574 extern long double __gammal(long double);
00575 extern long double __lgammal(long double);
00576 #pragma weak gammal
00577 #pragma weak lgammal
00578 #pragma weak signgaml
00579 long double gammal(long double arg) {
00580 return __gammal(arg);
00581 }
00582 long double lgammal( long double arg ) {
00583 return __lgammal( arg );
00584 }
00585 #elif defined(__GNUC__)
00586 extern long double __gammal(long double);
00587
00588 long double gammal() __attribute__ ((weak, alias ("__gammal")));
00589
00590 extern long double __lgammal(long double);
00591
00592 long double lgammal() __attribute__ ((weak, alias ("__lgammal")));
00593
00594 extern int __signgaml;
00595
00596 extern int signgaml __attribute__ ((weak, alias ("__signgaml")));
00597
00598 #endif
00599
00600 #if defined(BUILD_OS_DARWIN)
00601 int __signgaml = 0;
00602 int signgaml = 0;
00603 #elif (__GNUC__ > 3)
00604 int __signgaml = 0;
00605 #else
00606 int signgaml = 0;
00607 #endif
00608
00609 long double
00610 __gammal(long double arg)
00611 {
00612 double result;
00613
00614 result = __gamma((double)arg);
00615 #ifdef KEY
00616
00617 signgaml = __signgaml = __signgam;
00618 #endif
00619
00620 return (long double)result;
00621 }
00622
00623
00624 long double
00625 __lgammal( long double arg )
00626 {
00627 long double result = (long double)__lgamma((double)arg);
00628 #ifdef KEY
00629
00630 signgaml = __signgaml = __signgam;
00631 #endif
00632 return result;
00633 }
00634
00635 #endif
00636