1*c2c66affSColin Finck /* 2*c2c66affSColin Finck * COPYRIGHT: BSD - See COPYING.ARM in the top level directory 3*c2c66affSColin Finck * PROJECT: ReactOS CRT library 4*c2c66affSColin Finck * PURPOSE: Portable implementation of sqrt 5*c2c66affSColin Finck * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) 6*c2c66affSColin Finck */ 7*c2c66affSColin Finck 8*c2c66affSColin Finck #include <math.h> 9*c2c66affSColin Finck #include <assert.h> 10*c2c66affSColin Finck 11*c2c66affSColin Finck double 12*c2c66affSColin Finck __cdecl sqrt(double x)13*c2c66affSColin Fincksqrt( 14*c2c66affSColin Finck double x) 15*c2c66affSColin Finck { 16*c2c66affSColin Finck const double threehalfs = 1.5; 17*c2c66affSColin Finck const double x2 = x * 0.5; 18*c2c66affSColin Finck long long bits; 19*c2c66affSColin Finck double inv, y; 20*c2c66affSColin Finck 21*c2c66affSColin Finck /* Handle special cases */ 22*c2c66affSColin Finck if (x == 0.0) 23*c2c66affSColin Finck { 24*c2c66affSColin Finck return x; 25*c2c66affSColin Finck } 26*c2c66affSColin Finck else if (x < 0.0) 27*c2c66affSColin Finck { 28*c2c66affSColin Finck return -NAN; 29*c2c66affSColin Finck } 30*c2c66affSColin Finck 31*c2c66affSColin Finck /* Convert into a 64 bit integer */ 32*c2c66affSColin Finck bits = *(long long *)&x; 33*c2c66affSColin Finck 34*c2c66affSColin Finck /* Check for !finite(x) */ 35*c2c66affSColin Finck if ((bits & 0x7ff7ffffffffffffLL) == 0x7ff0000000000000LL) 36*c2c66affSColin Finck { 37*c2c66affSColin Finck return x; 38*c2c66affSColin Finck } 39*c2c66affSColin Finck 40*c2c66affSColin Finck /* Step 1: quick approximation of 1/sqrt(x) with bit magic 41*c2c66affSColin Finck See http://en.wikipedia.org/wiki/Fast_inverse_square_root */ 42*c2c66affSColin Finck bits = 0x5fe6eb50c7b537a9ll - (bits >> 1); 43*c2c66affSColin Finck inv = *(double*)&bits; 44*c2c66affSColin Finck 45*c2c66affSColin Finck /* Step 2: 3 Newton iterations to approximate 1 / sqrt(x) */ 46*c2c66affSColin Finck inv = inv * (threehalfs - (x2 * inv * inv)); 47*c2c66affSColin Finck inv = inv * (threehalfs - (x2 * inv * inv)); 48*c2c66affSColin Finck inv = inv * (threehalfs - (x2 * inv * inv)); 49*c2c66affSColin Finck 50*c2c66affSColin Finck /* Step 3: 1 additional Heron iteration has shown to maximize the precision. 51*c2c66affSColin Finck Normally the formula would be: y = (y + (x / y)) * 0.5; 52*c2c66affSColin Finck Instead we use the inverse sqrt directly */ 53*c2c66affSColin Finck y = ((1 / inv) + (x * inv)) * 0.5; 54*c2c66affSColin Finck 55*c2c66affSColin Finck //assert(y == (double)((y + (x / y)) * 0.5)); 56*c2c66affSColin Finck /* GCC BUG: While the C-Standard requires that an explicit cast to 57*c2c66affSColin Finck double converts the result of a computation to the appropriate 58*c2c66affSColin Finck 64 bit value, our GCC ignores this and uses an 80 bit FPU register 59*c2c66affSColin Finck in an intermediate value, so we need to make sure it is stored in 60*c2c66affSColin Finck a memory location before comparison */ 61*c2c66affSColin Finck //#if DBG 62*c2c66affSColin Finck // { 63*c2c66affSColin Finck // volatile double y1 = y, y2; 64*c2c66affSColin Finck // y2 = (y + (x / y)) * 0.5; 65*c2c66affSColin Finck // assert(y1 == y2); 66*c2c66affSColin Finck // } 67*c2c66affSColin Finck //#endif 68*c2c66affSColin Finck 69*c2c66affSColin Finck return y; 70*c2c66affSColin Finck } 71