|
| 1 | +/* |
| 2 | + * This file is part of the MicroPython project, http://micropython.org/ |
| 3 | + * |
| 4 | + * These math functions are taken from newlib-nano-2, the newlib/libm/math |
| 5 | + * directory, available from https://github.com/32bitmicro/newlib-nano-2. |
| 6 | + * |
| 7 | + * Appropriate copyright headers are reproduced below. |
| 8 | + */ |
| 9 | + |
| 10 | +/* ef_sqrtf.c -- float version of e_sqrt.c. |
| 11 | + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. |
| 12 | + */ |
| 13 | + |
| 14 | +/* |
| 15 | + * ==================================================== |
| 16 | + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. |
| 17 | + * |
| 18 | + * Developed at SunPro, a Sun Microsystems, Inc. business. |
| 19 | + * Permission to use, copy, modify, and distribute this |
| 20 | + * software is freely granted, provided that this notice |
| 21 | + * is preserved. |
| 22 | + * ==================================================== |
| 23 | + */ |
| 24 | + |
| 25 | +#include "fdlibm.h" |
| 26 | + |
| 27 | +#ifdef __STDC__ |
| 28 | +static const float one = 1.0, tiny=1.0e-30; |
| 29 | +#else |
| 30 | +static float one = 1.0, tiny=1.0e-30; |
| 31 | +#endif |
| 32 | + |
| 33 | +// sqrtf is exactly __ieee754_sqrtf when _IEEE_LIBM defined |
| 34 | +float sqrtf(float x) |
| 35 | +/* |
| 36 | +#ifdef __STDC__ |
| 37 | + float __ieee754_sqrtf(float x) |
| 38 | +#else |
| 39 | + float __ieee754_sqrtf(x) |
| 40 | + float x; |
| 41 | +#endif |
| 42 | +*/ |
| 43 | +{ |
| 44 | + float z; |
| 45 | + __uint32_t r,hx; |
| 46 | + __int32_t ix,s,q,m,t,i; |
| 47 | + |
| 48 | + GET_FLOAT_WORD(ix,x); |
| 49 | + hx = ix&0x7fffffff; |
| 50 | + |
| 51 | + /* take care of Inf and NaN */ |
| 52 | + if(!FLT_UWORD_IS_FINITE(hx)) |
| 53 | + return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf |
| 54 | + sqrt(-inf)=sNaN */ |
| 55 | + /* take care of zero and -ves */ |
| 56 | + if(FLT_UWORD_IS_ZERO(hx)) return x;/* sqrt(+-0) = +-0 */ |
| 57 | + if(ix<0) return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ |
| 58 | + |
| 59 | + /* normalize x */ |
| 60 | + m = (ix>>23); |
| 61 | + if(FLT_UWORD_IS_SUBNORMAL(hx)) { /* subnormal x */ |
| 62 | + for(i=0;(ix&0x00800000L)==0;i++) ix<<=1; |
| 63 | + m -= i-1; |
| 64 | + } |
| 65 | + m -= 127; /* unbias exponent */ |
| 66 | + ix = (ix&0x007fffffL)|0x00800000L; |
| 67 | + if(m&1) /* odd m, double x to make it even */ |
| 68 | + ix += ix; |
| 69 | + m >>= 1; /* m = [m/2] */ |
| 70 | + |
| 71 | + /* generate sqrt(x) bit by bit */ |
| 72 | + ix += ix; |
| 73 | + q = s = 0; /* q = sqrt(x) */ |
| 74 | + r = 0x01000000L; /* r = moving bit from right to left */ |
| 75 | + |
| 76 | + while(r!=0) { |
| 77 | + t = s+r; |
| 78 | + if(t<=ix) { |
| 79 | + s = t+r; |
| 80 | + ix -= t; |
| 81 | + q += r; |
| 82 | + } |
| 83 | + ix += ix; |
| 84 | + r>>=1; |
| 85 | + } |
| 86 | + |
| 87 | + /* use floating add to find out rounding direction */ |
| 88 | + if(ix!=0) { |
| 89 | + z = one-tiny; /* trigger inexact flag */ |
| 90 | + if (z>=one) { |
| 91 | + z = one+tiny; |
| 92 | + if (z>one) |
| 93 | + q += 2; |
| 94 | + else |
| 95 | + q += (q&1); |
| 96 | + } |
| 97 | + } |
| 98 | + ix = (q>>1)+0x3f000000L; |
| 99 | + ix += (m <<23); |
| 100 | + SET_FLOAT_WORD(z,ix); |
| 101 | + return z; |
| 102 | +} |
0 commit comments