From ec1a74a37c43763e9d24f6dbb578811a7947d5c5 Mon Sep 17 00:00:00 2001 From: Franklin Wei Date: Thu, 17 Aug 2017 17:14:21 -0400 Subject: puzzles: faster, smaller sqrt() Change-Id: I18e170ee49bff131fe76fa4bb1b9e0f120818b82 --- apps/plugins/puzzles/rbwrappers.c | 70 +++++---------------------------------- 1 file changed, 8 insertions(+), 62 deletions(-) (limited to 'apps/plugins') diff --git a/apps/plugins/puzzles/rbwrappers.c b/apps/plugins/puzzles/rbwrappers.c index 2d857c1cc9..feb1bf79de 100644 --- a/apps/plugins/puzzles/rbwrappers.c +++ b/apps/plugins/puzzles/rbwrappers.c @@ -984,70 +984,16 @@ float atan2_wrapper(float y, float x) } } -/* Square root function, original. */ float sqrt_wrapper(float x) { - float z; - int32_t sign = (int)0x80000000; - int32_t ix,s,q,m,t,i; - uint32_t r; - - GET_FLOAT_WORD(ix,x); - - /* take care of Inf and NaN */ - if((ix&0x7f800000)==0x7f800000) { - return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf - sqrt(-inf)=sNaN */ - } - /* take care of zero */ - if(ix<=0) { - if((ix&(~sign))==0) return x;/* sqrt(+-0) = +-0 */ - else if(ix<0) - return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ - } - /* normalize x */ - m = (ix>>23); - if(m==0) { /* subnormal x */ - for(i=0;(ix&0x00800000)==0;i++) ix<<=1; - m -= i-1; - } - m -= 127; /* unbias exponent */ - ix = (ix&0x007fffff)|0x00800000; - if(m&1) /* odd m, double x to make it even */ - ix += ix; - m >>= 1; /* m = [m/2] */ - - /* generate sqrt(x) bit by bit */ - ix += ix; - q = s = 0; /* q = sqrt(x) */ - r = 0x01000000; /* r = moving bit from right to left */ - - while(r!=0) { - t = s+r; - if(t<=ix) { - s = t+r; - ix -= t; - q += r; - } - ix += ix; - r>>=1; - } - - /* use floating add to find out rounding direction */ - if(ix!=0) { - z = one-tiny; /* trigger inexact flag */ - if (z>=one) { - z = one+tiny; - if (z>one) - q += 2; - else - q += (q&1); - } - } - ix = (q>>1)+0x3f000000; - ix += (m <<23); - SET_FLOAT_WORD(z,ix); - return z; + /* find inverse, Quake-style */ + float xhalf = .5f * x; + int i = *(int*)&x; + i = 0x5f3759df - (i >> 1); + x = *(float*)&i; + x = x * (1.5f - (xhalf * x * x)); + + return 1.0f / x; } /* hack, simple trig */ -- cgit v1.2.3