this repo has no description
at fixPythonPipStalling 199 lines 3.8 kB view raw
1/* 2 * fmod.c 3 * cLibm 4 * 5 * Written by Jon Okada, started on December 7th, 1992. 6 * Modified by Paul Finlayson (PAF) for MathLib v2. 7 * Modified by A. Sazegari (ali) for MathLib v3. 8 * Modified and ported by Robert A. Murley (ram) for Mac OS X. 9 * Modified for cLibm, fixed a few edge cases, rewrote local_ funcs by Ian Ollmann. 10 * Modified for armLibm, removed code to set flags as this is a soft-float fallback only. 11 * 12 * Copyright 2007 Apple Inc. All rights reserved. 13 * 14 */ 15 16#if defined(__SOFTFP__) 17 18 #include <math.h> 19 #include <float.h> 20 #include <stdint.h> 21 22static inline int local_ilogb( double x ) __attribute__ ((always_inline)); 23static inline int local_ilogb( double x ) 24{ 25 union{ double d; uint64_t u;}u = {x}; 26 27 u.u &= 0x7fffffffffffffffULL; 28 int32_t exp = (int32_t) (u.u >> 52); 29 30 if( __builtin_expect( (uint32_t) exp - 1U >= 2046, 0 ) ) 31 { // +-denorm, the other possibilities: +0 +-inf, NaN are screend out by caller 32 u.u |= 0x3ff0000000000000ULL; 33 u.d -= 1.0; 34 exp = (int32_t) (u.u >> 52); 35 36 return exp - (1023+1022); 37 } 38 39 return exp - 1023; 40} 41 42static inline double local_scalbn( double x, int n ); 43static inline double local_scalbn( double x, int n ) 44{ 45 union{ uint64_t u; double d;} u; 46 47 uint32_t absn = n >> (8*sizeof(n)-1); 48 absn = (n ^ absn) - absn; 49 50 if( absn > 1022 ) 51 { 52 // step = copysign( 1022, n ) 53 int signMask = n >> (8 * sizeof( int ) - 1); 54 int step = (1022 ^ signMask) - signMask; 55 56 u.u = ( (int64_t) step + 1023ULL) << 52; 57 58 if( n < 0 ) 59 { 60 do 61 { 62 x *= u.d; 63 n -= step; 64 }while( n < -1022 ); 65 } 66 else 67 { 68 do 69 { 70 x *= u.d; 71 n -= step; 72 }while( n > 1022 ); 73 } 74 } 75 76 //create 2**n in double 77 u.u = ( (int64_t) n + 1023ULL) << 52; 78 79 //scale by appropriate power of 2 80 x *= u.d; 81 82 //return result 83 return x; 84} 85 86 87double fmod( double x, double y ) 88{ 89 union{ double d; uint64_t u;}ux = {x}; 90 union{ double d; uint64_t u;}uy = {y}; 91 92 uint64_t absx = ux.u & ~0x8000000000000000ULL; 93 uint64_t absy = uy.u & ~0x8000000000000000ULL; 94 95 if( absx-1ULL >= 0x7fefffffffffffffULL || absy-1ULL >= 0x7fefffffffffffffULL ) 96 { 97 double fabsx = __builtin_fabs(x); 98 double fabsy = __builtin_fabs(y); 99 100 // deal with NaN 101 if( x != x || y != y ) 102 return x + y; 103 104 //x = Inf or y = 0, return Invalid per IEEE-754 105 if( fabsx == __builtin_inf() || 0.0 == y ) 106 { 107 return __builtin_nan(""); 108 } 109 110 //handle trivial case 111 if( fabsy == __builtin_inf() || 0.0 == x ) 112 { 113 return x; 114 } 115 } 116 117 if( absy >= absx ) 118 { 119 if( absy == absx ) 120 { 121 ux.u ^= absx; 122 return ux.d; 123 } 124 125 return x; 126 } 127 128 int32_t expx = absx >> 52; 129 int32_t expy = absy >> 52; 130 int64_t sx = absx & 0x000fffffffffffff; 131 int64_t sy = absy & 0x000fffffffffffff; 132 133 if( 0 == expx ) 134 { 135 uint32_t shift = __builtin_clzll( absx ) - (64-53); 136 sx <<= shift; 137 expx = 1 - shift; 138 } 139 140 if( 0 == expy ) 141 { 142 uint32_t shift = __builtin_clzll( absy ) - (64-53); 143 sy <<= shift; 144 expy = 1 - shift; 145 } 146 sx |= 0x0010000000000000ULL; 147 sy |= 0x0010000000000000ULL; 148 149 150 int32_t idiff = expx - expy; 151 int32_t shift = 0; 152 int64_t mask; 153 154 do 155 { 156 sx <<= shift; 157 idiff += ~shift; 158 sx -= sy; 159 mask = sx >> 63; 160 sx += sx; 161 sx += sy & mask; 162 shift = __builtin_clzll( sx ) - (64-53); 163 } 164 while( idiff >= shift && sx != 0LL ); 165 166 if( idiff < 0 ) 167 { 168 sx += sy & mask; 169 sx >>= 1; 170 idiff = 0; 171 } 172 173 sx <<= idiff; 174 175 if( 0 == sx ) 176 { 177 ux.u &= 0x8000000000000000; 178 return ux.d; 179 } 180 181 shift = __builtin_clzll( sx ) - (64-53); 182 sx <<= shift; 183 expy -= shift; 184 sx &= 0x000fffffffffffffULL; 185 sx |= ux.u & 0x8000000000000000ULL; 186 if( expy > 0 ) 187 { 188 ux.u = sx | ((int64_t) expy << 52); 189 return ux.d; 190 } 191 192 expy += 1022; 193 ux.u = sx | ((int64_t) expy << 52); 194 return ux.d * 0x1.0p-1022; 195 196} 197 198#endif 199