1*c9945492SAndroid Build Coastguard Worker #include <math.h> 2*c9945492SAndroid Build Coastguard Worker #include <stdint.h> 3*c9945492SAndroid Build Coastguard Worker fmod(double x,double y)4*c9945492SAndroid Build Coastguard Workerdouble fmod(double x, double y) 5*c9945492SAndroid Build Coastguard Worker { 6*c9945492SAndroid Build Coastguard Worker union {double f; uint64_t i;} ux = {x}, uy = {y}; 7*c9945492SAndroid Build Coastguard Worker int ex = ux.i>>52 & 0x7ff; 8*c9945492SAndroid Build Coastguard Worker int ey = uy.i>>52 & 0x7ff; 9*c9945492SAndroid Build Coastguard Worker int sx = ux.i>>63; 10*c9945492SAndroid Build Coastguard Worker uint64_t i; 11*c9945492SAndroid Build Coastguard Worker 12*c9945492SAndroid Build Coastguard Worker /* in the followings uxi should be ux.i, but then gcc wrongly adds */ 13*c9945492SAndroid Build Coastguard Worker /* float load/store to inner loops ruining performance and code size */ 14*c9945492SAndroid Build Coastguard Worker uint64_t uxi = ux.i; 15*c9945492SAndroid Build Coastguard Worker 16*c9945492SAndroid Build Coastguard Worker if (uy.i<<1 == 0 || isnan(y) || ex == 0x7ff) 17*c9945492SAndroid Build Coastguard Worker return (x*y)/(x*y); 18*c9945492SAndroid Build Coastguard Worker if (uxi<<1 <= uy.i<<1) { 19*c9945492SAndroid Build Coastguard Worker if (uxi<<1 == uy.i<<1) 20*c9945492SAndroid Build Coastguard Worker return 0*x; 21*c9945492SAndroid Build Coastguard Worker return x; 22*c9945492SAndroid Build Coastguard Worker } 23*c9945492SAndroid Build Coastguard Worker 24*c9945492SAndroid Build Coastguard Worker /* normalize x and y */ 25*c9945492SAndroid Build Coastguard Worker if (!ex) { 26*c9945492SAndroid Build Coastguard Worker for (i = uxi<<12; i>>63 == 0; ex--, i <<= 1); 27*c9945492SAndroid Build Coastguard Worker uxi <<= -ex + 1; 28*c9945492SAndroid Build Coastguard Worker } else { 29*c9945492SAndroid Build Coastguard Worker uxi &= -1ULL >> 12; 30*c9945492SAndroid Build Coastguard Worker uxi |= 1ULL << 52; 31*c9945492SAndroid Build Coastguard Worker } 32*c9945492SAndroid Build Coastguard Worker if (!ey) { 33*c9945492SAndroid Build Coastguard Worker for (i = uy.i<<12; i>>63 == 0; ey--, i <<= 1); 34*c9945492SAndroid Build Coastguard Worker uy.i <<= -ey + 1; 35*c9945492SAndroid Build Coastguard Worker } else { 36*c9945492SAndroid Build Coastguard Worker uy.i &= -1ULL >> 12; 37*c9945492SAndroid Build Coastguard Worker uy.i |= 1ULL << 52; 38*c9945492SAndroid Build Coastguard Worker } 39*c9945492SAndroid Build Coastguard Worker 40*c9945492SAndroid Build Coastguard Worker /* x mod y */ 41*c9945492SAndroid Build Coastguard Worker for (; ex > ey; ex--) { 42*c9945492SAndroid Build Coastguard Worker i = uxi - uy.i; 43*c9945492SAndroid Build Coastguard Worker if (i >> 63 == 0) { 44*c9945492SAndroid Build Coastguard Worker if (i == 0) 45*c9945492SAndroid Build Coastguard Worker return 0*x; 46*c9945492SAndroid Build Coastguard Worker uxi = i; 47*c9945492SAndroid Build Coastguard Worker } 48*c9945492SAndroid Build Coastguard Worker uxi <<= 1; 49*c9945492SAndroid Build Coastguard Worker } 50*c9945492SAndroid Build Coastguard Worker i = uxi - uy.i; 51*c9945492SAndroid Build Coastguard Worker if (i >> 63 == 0) { 52*c9945492SAndroid Build Coastguard Worker if (i == 0) 53*c9945492SAndroid Build Coastguard Worker return 0*x; 54*c9945492SAndroid Build Coastguard Worker uxi = i; 55*c9945492SAndroid Build Coastguard Worker } 56*c9945492SAndroid Build Coastguard Worker for (; uxi>>52 == 0; uxi <<= 1, ex--); 57*c9945492SAndroid Build Coastguard Worker 58*c9945492SAndroid Build Coastguard Worker /* scale result */ 59*c9945492SAndroid Build Coastguard Worker if (ex > 0) { 60*c9945492SAndroid Build Coastguard Worker uxi -= 1ULL << 52; 61*c9945492SAndroid Build Coastguard Worker uxi |= (uint64_t)ex << 52; 62*c9945492SAndroid Build Coastguard Worker } else { 63*c9945492SAndroid Build Coastguard Worker uxi >>= -ex + 1; 64*c9945492SAndroid Build Coastguard Worker } 65*c9945492SAndroid Build Coastguard Worker uxi |= (uint64_t)sx << 63; 66*c9945492SAndroid Build Coastguard Worker ux.i = uxi; 67*c9945492SAndroid Build Coastguard Worker return ux.f; 68*c9945492SAndroid Build Coastguard Worker } 69