this repo has no description
at fixPythonPipStalling 183 lines 3.8 kB view raw
1/* 2 * tgamma.c 3 * 4 * by Ian Ollmann, drawing heavily from work by Steve Peters, Jeff Kidder, and Ali Sazegari. 5 * 6 * Copyright (c) 2007 Apple Inc. All Rights Resterved. 7 */ 8 9#include <math.h> 10#include <stdint.h> 11 12#ifdef ARMLIBM_SET_FLAGS 13#include "required_arithmetic.h" 14#endif 15 16static const double LogSqrt2pi = 0.9189385332046727417803297e+0; 17static const double pi = 3.1415926535897932384626434e+0; 18static const double eps = 0x1.0p-52; 19static const double xbig = 171.624e+0; 20 21 22static const double p[8] = { -1.71618513886549492533811e+0, 23 2.47656508055759199108314e+1, 24 -3.79804256470945635097577e+2, 25 6.29331155312818442661052e+2, 26 8.66966202790413211295064e+2, 27 -3.14512729688483675254357e+4, 28 -3.61444134186911729807069e+4, 29 6.64561438202405440627855e+4 }; 30 31static const double q[8] = { -3.08402300119738975254353e+1, 32 3.15350626979604161529144e+2, 33 -1.01515636749021914166146e+3, 34 -3.10777167157231109440444e+3, 35 2.25381184209801510330112e+4, 36 4.75584627752788110767815e+3, 37 -1.34659959864969306392456e+5, 38 -1.15132259675553483497211e+5 }; 39 40static const double c[7] = { 0xa.aaaaaaaaaaaaaabp-7, 41 -0xb.60b60b60b60b60bp-12, 42 0xd.00d00d00d00d00dp-14, 43 -0x9.c09c09c09c09c0ap-14, 44 0xd.ca8f158c7f91ab8p-14, 45 -0xf.b5586ccc9e3e41p-13, 46 0xd.20d20d20d20d20dp-11 }; 47 48double tgamma( double x ) 49{ 50 union{ double d; uint64_t u; }u = {x}; 51 52 // deal with 0, NaN, Inf 53 if( (u.u & 0x7fffffffffffffffULL) -1ULL >= 0x7ff0000000000000ULL -1ULL ) 54 { 55 // 0 56 if( x == 0.0 ) { 57#ifdef ARMLIBM_SET_FLAGS 58 return required_divide_double( 1.0, x ); 59#else 60 return __builtin_copysign(__builtin_inf(), x); 61#endif 62 } 63 64 //NaN 65 if( x != x ) 66 return x + x; 67 68 //Inf 69 if( x < 0.0 ) { 70#ifdef ARMLIBM_SET_FLAGS 71 return required_multiply_double( x, 0.0 ); // -Inf: set invalid, return NaN 72#else 73 return __builtin_nan(""); 74#endif 75 } 76 77 return x; // Inf 78 } 79 80 int n = 0; 81 int parity = 0; 82 double y = x; 83 double fact = 1.0; 84 85 // negative x 86 if( x <= 0.0 ) 87 { 88 y = -x; 89 if( y < 0x1.0p-1022 ) 90 return 1.0 / x; 91 92 // y1 = trunc ( y ); //fast trunc, no edge cases 93 double iy = y; 94 int64_t ll = 0; 95 if( y < 0x1.0p54 ) 96 { 97 ll = y; 98 iy = ll; 99 } 100 101 double fraction = y - iy; 102 103 if( fraction != 0.0 ) 104 { 105 parity = (int) (ll & 1); 106 fact = -pi / sin( pi * fraction ); 107 y += 1.0; 108 } 109 else { 110#ifdef ARMLIBM_SET_FLAGS 111 return required_add_double( -__builtin_inf(), __builtin_inf() ); // set invalid, return NaN 112#else 113 return __builtin_nan(""); 114#endif 115 } 116 } 117 118 double result; 119 int i; 120 121 if( y < eps ) 122 { 123 result = 1.0 / y; 124 } 125 else if( y < 12.0 ) 126 { 127 double y1 = y; 128 double z; 129 if( y < 1.0) 130 { 131 z = y; 132 y += 1.0; 133 } 134 else 135 { 136 n = (int)y - 1; 137 y -= (double) n; 138 z = y - 1.0; 139 } 140 141 double numerator = 0.0; 142 double denomenator = 1.0; 143 for( i = 0; i < 8; i++ ) 144 { 145 numerator = (numerator + p[i]) * z; 146 denomenator = denomenator * z + q[i]; 147 } 148 result = numerator / denomenator + 1.0; 149 if( y1 < y ) 150 result /= y1; 151 else if( y1 > y ) 152 { 153 for( i = 0; i < n; i++ ) 154 { 155 result *= y; 156 y += 1.0; 157 } 158 } 159 } 160 else 161 { // y large 162 if( x < xbig ) 163 { 164 double yy = y * y; 165 double sum = c[6]; 166 for( i = 5; i >= 0; i-- ) 167 sum = sum / yy + c[i]; 168 sum = sum / y - y + LogSqrt2pi; 169 sum += (y - 0.5) * log( y ); 170 result = exp( sum ); 171 } 172 else 173 return x * 0x1.0p1023; //set overflow, return inf 174 } 175 176 if( parity ) 177 result = -result; 178 179 if( fact != 1.0 ) 180 result = fact / result; 181 182 return result; 183}