summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2017-08-17 17:14:21 -0400
committerFranklin Wei <git@fwei.tk>2017-08-23 14:22:09 -0400
commitec1a74a37c43763e9d24f6dbb578811a7947d5c5 (patch)
tree88ea724d1553442f761e43318d392fabd7f11d92
parentf2f1889b108ad85ccfeedff6afcb4a98e06c5580 (diff)
downloadrockbox-ec1a74a37c43763e9d24f6dbb578811a7947d5c5.tar.gz
rockbox-ec1a74a37c43763e9d24f6dbb578811a7947d5c5.tar.bz2
rockbox-ec1a74a37c43763e9d24f6dbb578811a7947d5c5.zip
puzzles: faster, smaller sqrt()
Change-Id: I18e170ee49bff131fe76fa4bb1b9e0f120818b82
-rw-r--r--apps/plugins/puzzles/rbwrappers.c70
1 files changed, 8 insertions, 62 deletions
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 */