github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/cmd/gc/mparith3.c (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 #include <u.h> 6 #include <libc.h> 7 #include "go.h" 8 9 /* 10 * returns the leading non-zero 11 * word of the number 12 */ 13 int 14 sigfig(Mpflt *a) 15 { 16 int i; 17 18 for(i=Mpprec-1; i>=0; i--) 19 if(a->val.a[i] != 0) 20 break; 21 //print("sigfig %d %d\n", i-z+1, z); 22 return i+1; 23 } 24 25 /* 26 * shifts the leading non-zero 27 * word of the number to Mpnorm 28 */ 29 void 30 mpnorm(Mpflt *a) 31 { 32 int s, os; 33 long x; 34 35 os = sigfig(a); 36 if(os == 0) { 37 // zero 38 a->exp = 0; 39 a->val.neg = 0; 40 return; 41 } 42 43 // this will normalize to the nearest word 44 x = a->val.a[os-1]; 45 s = (Mpnorm-os) * Mpscale; 46 47 // further normalize to the nearest bit 48 for(;;) { 49 x <<= 1; 50 if(x & Mpbase) 51 break; 52 s++; 53 if(x == 0) { 54 // this error comes from trying to 55 // convert an Inf or something 56 // where the initial x=0x80000000 57 s = (Mpnorm-os) * Mpscale; 58 break; 59 } 60 } 61 62 mpshiftfix(&a->val, s); 63 a->exp -= s; 64 } 65 66 /// implements float arihmetic 67 68 void 69 mpaddfltflt(Mpflt *a, Mpflt *b) 70 { 71 int sa, sb, s; 72 Mpflt c; 73 74 if(Mpdebug) 75 print("\n%F + %F", a, b); 76 77 sa = sigfig(a); 78 if(sa == 0) { 79 mpmovefltflt(a, b); 80 goto out; 81 } 82 83 sb = sigfig(b); 84 if(sb == 0) 85 goto out; 86 87 s = a->exp - b->exp; 88 if(s > 0) { 89 // a is larger, shift b right 90 mpmovefltflt(&c, b); 91 mpshiftfix(&c.val, -s); 92 mpaddfixfix(&a->val, &c.val, 0); 93 goto out; 94 } 95 if(s < 0) { 96 // b is larger, shift a right 97 mpshiftfix(&a->val, s); 98 a->exp -= s; 99 mpaddfixfix(&a->val, &b->val, 0); 100 goto out; 101 } 102 mpaddfixfix(&a->val, &b->val, 0); 103 104 out: 105 mpnorm(a); 106 if(Mpdebug) 107 print(" = %F\n\n", a); 108 } 109 110 void 111 mpmulfltflt(Mpflt *a, Mpflt *b) 112 { 113 int sa, sb; 114 115 if(Mpdebug) 116 print("%F\n * %F\n", a, b); 117 118 sa = sigfig(a); 119 if(sa == 0) { 120 // zero 121 a->exp = 0; 122 a->val.neg = 0; 123 return; 124 } 125 126 sb = sigfig(b); 127 if(sb == 0) { 128 // zero 129 mpmovefltflt(a, b); 130 return; 131 } 132 133 mpmulfract(&a->val, &b->val); 134 a->exp = (a->exp + b->exp) + Mpscale*Mpprec - Mpscale - 1; 135 136 mpnorm(a); 137 if(Mpdebug) 138 print(" = %F\n\n", a); 139 } 140 141 void 142 mpdivfltflt(Mpflt *a, Mpflt *b) 143 { 144 int sa, sb; 145 Mpflt c; 146 147 if(Mpdebug) 148 print("%F\n / %F\n", a, b); 149 150 sb = sigfig(b); 151 if(sb == 0) { 152 // zero and ovfl 153 a->exp = 0; 154 a->val.neg = 0; 155 a->val.ovf = 1; 156 yyerror("constant division by zero"); 157 return; 158 } 159 160 sa = sigfig(a); 161 if(sa == 0) { 162 // zero 163 a->exp = 0; 164 a->val.neg = 0; 165 return; 166 } 167 168 // adjust b to top 169 mpmovefltflt(&c, b); 170 mpshiftfix(&c.val, Mpscale); 171 172 // divide 173 mpdivfract(&a->val, &c.val); 174 a->exp = (a->exp-c.exp) - Mpscale*(Mpprec-1) + 1; 175 176 mpnorm(a); 177 if(Mpdebug) 178 print(" = %F\n\n", a); 179 } 180 181 double 182 mpgetflt(Mpflt *a) 183 { 184 int s, i, e; 185 uvlong v, vm; 186 double f; 187 188 if(a->val.ovf && nsavederrors+nerrors == 0) 189 yyerror("mpgetflt ovf"); 190 191 s = sigfig(a); 192 if(s == 0) 193 return 0; 194 195 if(s != Mpnorm) { 196 yyerror("mpgetflt norm"); 197 mpnorm(a); 198 } 199 200 while((a->val.a[Mpnorm-1] & Mpsign) == 0) { 201 mpshiftfix(&a->val, 1); 202 a->exp -= 1; 203 } 204 205 // the magic numbers (64, 63, 53, 10, -1074) are 206 // IEEE specific. this should be done machine 207 // independently or in the 6g half of the compiler 208 209 // pick up the mantissa and a rounding bit in a uvlong 210 s = 53+1; 211 v = 0; 212 for(i=Mpnorm-1; s>=Mpscale; i--) { 213 v = (v<<Mpscale) | a->val.a[i]; 214 s -= Mpscale; 215 } 216 vm = v; 217 if(s > 0) 218 vm = (vm<<s) | (a->val.a[i]>>(Mpscale-s)); 219 220 // continue with 64 more bits 221 s += 64; 222 for(; s>=Mpscale; i--) { 223 v = (v<<Mpscale) | a->val.a[i]; 224 s -= Mpscale; 225 } 226 if(s > 0) 227 v = (v<<s) | (a->val.a[i]>>(Mpscale-s)); 228 229 // gradual underflow 230 e = Mpnorm*Mpscale + a->exp - 53; 231 if(e < -1074) { 232 s = -e - 1074; 233 if(s > 54) 234 s = 54; 235 v |= vm & ((1ULL<<s) - 1); 236 vm >>= s; 237 e = -1074; 238 } 239 240 //print("vm=%.16llux v=%.16llux\n", vm, v); 241 // round toward even 242 if(v != 0 || (vm&2ULL) != 0) 243 vm = (vm>>1) + (vm&1ULL); 244 else 245 vm >>= 1; 246 247 f = (double)(vm); 248 f = ldexp(f, e); 249 250 if(a->val.neg) 251 f = -f; 252 return f; 253 } 254 255 void 256 mpmovecflt(Mpflt *a, double c) 257 { 258 int i; 259 double f; 260 long l; 261 262 if(Mpdebug) 263 print("\nconst %g", c); 264 mpmovecfix(&a->val, 0); 265 a->exp = 0; 266 if(c == 0) 267 goto out; 268 if(c < 0) { 269 a->val.neg = 1; 270 c = -c; 271 } 272 273 f = frexp(c, &i); 274 a->exp = i; 275 276 for(i=0; i<10; i++) { 277 f = f*Mpbase; 278 l = floor(f); 279 f = f - l; 280 a->exp -= Mpscale; 281 a->val.a[0] = l; 282 if(f == 0) 283 break; 284 mpshiftfix(&a->val, Mpscale); 285 } 286 287 out: 288 mpnorm(a); 289 if(Mpdebug) 290 print(" = %F\n", a); 291 } 292 293 void 294 mpnegflt(Mpflt *a) 295 { 296 a->val.neg ^= 1; 297 } 298 299 int 300 mptestflt(Mpflt *a) 301 { 302 int s; 303 304 if(Mpdebug) 305 print("\n%F?", a); 306 s = sigfig(a); 307 if(s != 0) { 308 s = +1; 309 if(a->val.neg) 310 s = -1; 311 } 312 if(Mpdebug) 313 print(" = %d\n", s); 314 return s; 315 }