Changeset 816
- Timestamp:
- Apr 28, 2016, 1:12:20 PM (9 years ago)
- Location:
- soft/giet_vm
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/giet_config.h
r791 r816 61 61 #define GIET_SDC_PERIOD 2 /* number of cycles in SDC period */ 62 62 #define GIET_SR_INIT_VALUE 0x2000FF13 /* SR initial value (before eret) */ 63 #define GIET_USE_HARD_FLOAT 0 /* hard float supported */ 63 64 64 65 #endif -
soft/giet_vm/giet_libs/math/sqrt.c
r581 r816 1 #include "../math.h" 2 #include "math_private.h" 3 4 static const double one = 1.0, tiny = 1.0e-300; 5 6 /* this function was taken from the uCLibc library 7 * Return correctly rounded sqrt. 8 * Method: 9 * Bit by bit method using integer arithmetic. (Slow, but portable) 10 * 1. Normalization 11 * Scale x to y in [1,4) with even powers of 2: 12 * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then 13 * sqrt(x) = 2^k * sqrt(y) 14 * 2. Bit by bit computation 15 * Let q = sqrt(y) truncated to i bit after binary point (q = 1), 16 * i 0 17 * i+1 2 18 * s = 2*q , and y = 2 * ( y - q ). (1) 19 * i i i i 20 * 21 * To compute q from q , one checks whether 22 * i+1 i 23 * 24 * -(i+1) 2 25 * (q + 2 ) <= y. (2) 26 * i 27 * -(i+1) 28 * If (2) is false, then q = q ; otherwise q = q + 2 . 29 * i+1 i i+1 i 30 * 31 * With some algebric manipulation, it is not difficult to see 32 * that (2) is equivalent to 33 * -(i+1) 34 * s + 2 <= y (3) 35 * i i 36 * 37 * The advantage of (3) is that s and y can be computed by 38 * i i 39 * the following recurrence formula: 40 * if (3) is false 41 * 42 * s = s , y = y ; (4) 43 * i+1 i i+1 i 44 * 45 * otherwise, 46 * -i -(i+1) 47 * s = s + 2 , y = y - s - 2 (5) 48 * i+1 i i+1 i i 49 * 50 * One may easily use induction to prove (4) and (5). 51 * Note. Since the left hand side of (3) contain only i+2 bits, 52 * it does not necessary to do a full (53-bit) comparison 53 * in (3). 54 * 3. Final rounding 55 * After generating the 53 bits result, we compute one more bit. 56 * Together with the remainder, we can decide whether the 57 * result is exact, bigger than 1/2ulp, or less than 1/2ulp 58 * (it will never equal to 1/2ulp). 59 * The rounding mode can be detected by checking whether 60 * huge + tiny is equal to huge, and whether huge - tiny is 61 * equal to huge for some floating point number "huge" and "tiny". 62 * 63 * Special cases: 64 * sqrt(+-0) = +-0 ... exact 65 * sqrt(inf) = inf 66 * sqrt(-ve) = NaN ... with invalid signal 67 * sqrt(NaN) = NaN ... with invalid signal for signaling NaN 68 * 69 * Other methods : see the appended file at the end of the program below. 70 *--------------- 71 */ 72 static double __ieee754_sqrt(double x) 73 { 74 double z; 75 int32_t sign = (int)0x80000000; 76 int32_t ix0,s0,q,m,t,i; 77 uint32_t r,t1,s1,ix1,q1; 78 79 EXTRACT_WORDS(ix0,ix1,x); 80 81 /* take care of Inf and NaN */ 82 if((ix0&0x7ff00000)==0x7ff00000) { 83 return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf 84 sqrt(-inf)=sNaN */ 85 } 86 /* take care of zero */ 87 if(ix0<=0) { 88 if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */ 89 else if(ix0<0) 90 return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ 91 } 92 /* normalize x */ 93 m = (ix0>>20); 94 if(m==0) { /* subnormal x */ 95 while(ix0==0) { 96 m -= 21; 97 ix0 |= (ix1>>11); ix1 <<= 21; 98 } 99 for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1; 100 m -= i-1; 101 ix0 |= (ix1>>(32-i)); 102 ix1 <<= i; 103 } 104 m -= 1023; /* unbias exponent */ 105 ix0 = (ix0&0x000fffff)|0x00100000; 106 if(m&1){ /* odd m, double x to make it even */ 107 ix0 += ix0 + ((ix1&sign)>>31); 108 ix1 += ix1; 109 } 110 m >>= 1; /* m = [m/2] */ 111 112 /* generate sqrt(x) bit by bit */ 113 ix0 += ix0 + ((ix1&sign)>>31); 114 ix1 += ix1; 115 q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ 116 r = 0x00200000; /* r = moving bit from right to left */ 117 118 while(r!=0) { 119 t = s0+r; 120 if(t<=ix0) { 121 s0 = t+r; 122 ix0 -= t; 123 q += r; 124 } 125 ix0 += ix0 + ((ix1&sign)>>31); 126 ix1 += ix1; 127 r>>=1; 128 } 129 130 r = sign; 131 while(r!=0) { 132 t1 = s1+r; 133 t = s0; 134 if((t<ix0)||((t==ix0)&&(t1<=ix1))) { 135 s1 = t1+r; 136 if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1; 137 ix0 -= t; 138 if (ix1 < t1) ix0 -= 1; 139 ix1 -= t1; 140 q1 += r; 141 } 142 ix0 += ix0 + ((ix1&sign)>>31); 143 ix1 += ix1; 144 r>>=1; 145 } 146 147 /* use floating add to find out rounding direction */ 148 if((ix0|ix1)!=0) { 149 z = one-tiny; /* trigger inexact flag */ 150 if (z>=one) { 151 z = one+tiny; 152 if (q1==(uint32_t)0xffffffff) { q1=0; q += 1;} 153 else if (z>one) { 154 if (q1==(uint32_t)0xfffffffe) q+=1; 155 q1+=2; 156 } else 157 q1 += (q1&1); 158 } 159 } 160 ix0 = (q>>1)+0x3fe00000; 161 ix1 = q1>>1; 162 if ((q&1)==1) ix1 |= sign; 163 ix0 += (m <<20); 164 INSERT_WORDS(z,ix0,ix1); 165 return z; 166 } 1 167 2 168 double sqrt(double x) 3 169 { 4 double z; 5 __asm__ ("sqrt.d %0,%1" : "=f" (z) : "f" (x)); 6 return z; 170 #if GIET_USE_HARD_FLOAT 171 double z; 172 __asm__ ("sqrt.d %0,%1" : "=f" (z) : "f" (x)); 173 return z; 174 #else 175 return __ieee754_sqrt(x); 176 #endif 7 177 } 8 178 179 /* 180 * vim: ts=4 : sts=4 : sw=4 : et 181 */
Note: See TracChangeset
for help on using the changeset viewer.