00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #include "config.h"
00054 #include "system.h"
00055 #include "coretypes.h"
00056 #include "tm.h"
00057 #include "sreal.h"
00058
00059 static inline void copy (sreal *, sreal *);
00060 static inline void shift_right (sreal *, int);
00061 static void normalize (sreal *);
00062
00063
00064
00065 void
00066 dump_sreal (FILE *file, sreal *x)
00067 {
00068 #if SREAL_PART_BITS < 32
00069 fprintf (file, "((" HOST_WIDE_INT_PRINT_UNSIGNED " * 2^16 + "
00070 HOST_WIDE_INT_PRINT_UNSIGNED ") * 2^%d)",
00071 x->sig_hi, x->sig_lo, x->exp);
00072 #else
00073 fprintf (file, "(" HOST_WIDE_INT_PRINT_UNSIGNED " * 2^%d)", x->sig, x->exp);
00074 #endif
00075 }
00076
00077
00078
00079 static inline void
00080 copy (sreal *r, sreal *a)
00081 {
00082 #if SREAL_PART_BITS < 32
00083 r->sig_lo = a->sig_lo;
00084 r->sig_hi = a->sig_hi;
00085 #else
00086 r->sig = a->sig;
00087 #endif
00088 r->exp = a->exp;
00089 }
00090
00091
00092
00093
00094 static inline void
00095 shift_right (sreal *x, int s)
00096 {
00097 gcc_assert (s > 0);
00098 gcc_assert (s <= SREAL_BITS);
00099
00100
00101
00102 gcc_assert (x->exp + s <= SREAL_MAX_EXP);
00103
00104 x->exp += s;
00105
00106 #if SREAL_PART_BITS < 32
00107 if (s > SREAL_PART_BITS)
00108 {
00109 s -= SREAL_PART_BITS;
00110 x->sig_hi += (uhwi) 1 << (s - 1);
00111 x->sig_lo = x->sig_hi >> s;
00112 x->sig_hi = 0;
00113 }
00114 else
00115 {
00116 x->sig_lo += (uhwi) 1 << (s - 1);
00117 if (x->sig_lo & ((uhwi) 1 << SREAL_PART_BITS))
00118 {
00119 x->sig_hi++;
00120 x->sig_lo -= (uhwi) 1 << SREAL_PART_BITS;
00121 }
00122 x->sig_lo >>= s;
00123 x->sig_lo |= (x->sig_hi & (((uhwi) 1 << s) - 1)) << (SREAL_PART_BITS - s);
00124 x->sig_hi >>= s;
00125 }
00126 #else
00127 x->sig += (uhwi) 1 << (s - 1);
00128 x->sig >>= s;
00129 #endif
00130 }
00131
00132
00133
00134 static void
00135 normalize (sreal *x)
00136 {
00137 #if SREAL_PART_BITS < 32
00138 int shift;
00139 HOST_WIDE_INT mask;
00140
00141 if (x->sig_lo == 0 && x->sig_hi == 0)
00142 {
00143 x->exp = -SREAL_MAX_EXP;
00144 }
00145 else if (x->sig_hi < SREAL_MIN_SIG)
00146 {
00147 if (x->sig_hi == 0)
00148 {
00149
00150 x->sig_hi = x->sig_lo;
00151 x->sig_lo = 0;
00152 x->exp -= SREAL_PART_BITS;
00153 }
00154 shift = 0;
00155 while (x->sig_hi < SREAL_MIN_SIG)
00156 {
00157 x->sig_hi <<= 1;
00158 x->exp--;
00159 shift++;
00160 }
00161
00162 if (x->exp < -SREAL_MAX_EXP)
00163 {
00164 x->exp = -SREAL_MAX_EXP;
00165 x->sig_hi = 0;
00166 x->sig_lo = 0;
00167 }
00168 else if (shift)
00169 {
00170 mask = (1 << SREAL_PART_BITS) - (1 << (SREAL_PART_BITS - shift));
00171 x->sig_hi |= (x->sig_lo & mask) >> (SREAL_PART_BITS - shift);
00172 x->sig_lo = (x->sig_lo << shift) & (((uhwi) 1 << SREAL_PART_BITS) - 1);
00173 }
00174 }
00175 else if (x->sig_hi > SREAL_MAX_SIG)
00176 {
00177 unsigned HOST_WIDE_INT tmp = x->sig_hi;
00178
00179
00180 shift = 0;
00181 do
00182 {
00183 tmp >>= 1;
00184 shift++;
00185 }
00186 while (tmp > SREAL_MAX_SIG);
00187
00188
00189 x->sig_lo += (uhwi) 1 << (shift - 1);
00190
00191 x->sig_lo >>= shift;
00192 x->sig_lo += ((x->sig_hi & (((uhwi) 1 << shift) - 1))
00193 << (SREAL_PART_BITS - shift));
00194 x->sig_hi >>= shift;
00195 x->exp += shift;
00196 if (x->sig_lo & ((uhwi) 1 << SREAL_PART_BITS))
00197 {
00198 x->sig_lo -= (uhwi) 1 << SREAL_PART_BITS;
00199 x->sig_hi++;
00200 if (x->sig_hi > SREAL_MAX_SIG)
00201 {
00202
00203
00204 x->sig_hi >>= 1;
00205 x->sig_lo >>= 1;
00206 x->exp++;
00207 }
00208 }
00209
00210
00211 if (x->exp > SREAL_MAX_EXP)
00212 {
00213 x->exp = SREAL_MAX_EXP;
00214 x->sig_hi = SREAL_MAX_SIG;
00215 x->sig_lo = SREAL_MAX_SIG;
00216 }
00217 }
00218 #else
00219 if (x->sig == 0)
00220 {
00221 x->exp = -SREAL_MAX_EXP;
00222 }
00223 else if (x->sig < SREAL_MIN_SIG)
00224 {
00225 do
00226 {
00227 x->sig <<= 1;
00228 x->exp--;
00229 }
00230 while (x->sig < SREAL_MIN_SIG);
00231
00232
00233 if (x->exp < -SREAL_MAX_EXP)
00234 {
00235 x->exp = -SREAL_MAX_EXP;
00236 x->sig = 0;
00237 }
00238 }
00239 else if (x->sig > SREAL_MAX_SIG)
00240 {
00241 int last_bit;
00242 do
00243 {
00244 last_bit = x->sig & 1;
00245 x->sig >>= 1;
00246 x->exp++;
00247 }
00248 while (x->sig > SREAL_MAX_SIG);
00249
00250
00251 x->sig += last_bit;
00252 if (x->sig > SREAL_MAX_SIG)
00253 {
00254 x->sig >>= 1;
00255 x->exp++;
00256 }
00257
00258
00259 if (x->exp > SREAL_MAX_EXP)
00260 {
00261 x->exp = SREAL_MAX_EXP;
00262 x->sig = SREAL_MAX_SIG;
00263 }
00264 }
00265 #endif
00266 }
00267
00268
00269
00270 sreal *
00271 sreal_init (sreal *r, unsigned HOST_WIDE_INT sig, signed int exp)
00272 {
00273 #if SREAL_PART_BITS < 32
00274 r->sig_lo = 0;
00275 r->sig_hi = sig;
00276 r->exp = exp - 16;
00277 #else
00278 r->sig = sig;
00279 r->exp = exp;
00280 #endif
00281 normalize (r);
00282 return r;
00283 }
00284
00285
00286
00287 HOST_WIDE_INT
00288 sreal_to_int (sreal *r)
00289 {
00290 #if SREAL_PART_BITS < 32
00291 if (r->exp <= -SREAL_BITS)
00292 return 0;
00293 if (r->exp >= 0)
00294 return MAX_HOST_WIDE_INT;
00295 return ((r->sig_hi << SREAL_PART_BITS) + r->sig_lo) >> -r->exp;
00296 #else
00297 if (r->exp <= -SREAL_BITS)
00298 return 0;
00299 if (r->exp >= SREAL_PART_BITS)
00300 return MAX_HOST_WIDE_INT;
00301 if (r->exp > 0)
00302 return r->sig << r->exp;
00303 if (r->exp < 0)
00304 return r->sig >> -r->exp;
00305 return r->sig;
00306 #endif
00307 }
00308
00309
00310
00311 int
00312 sreal_compare (sreal *a, sreal *b)
00313 {
00314 if (a->exp > b->exp)
00315 return 1;
00316 if (a->exp < b->exp)
00317 return -1;
00318 #if SREAL_PART_BITS < 32
00319 if (a->sig_hi > b->sig_hi)
00320 return 1;
00321 if (a->sig_hi < b->sig_hi)
00322 return -1;
00323 if (a->sig_lo > b->sig_lo)
00324 return 1;
00325 if (a->sig_lo < b->sig_lo)
00326 return -1;
00327 #else
00328 if (a->sig > b->sig)
00329 return 1;
00330 if (a->sig < b->sig)
00331 return -1;
00332 #endif
00333 return 0;
00334 }
00335
00336
00337
00338 sreal *
00339 sreal_add (sreal *r, sreal *a, sreal *b)
00340 {
00341 int dexp;
00342 sreal tmp;
00343 sreal *bb;
00344
00345 if (sreal_compare (a, b) < 0)
00346 {
00347 sreal *swap;
00348 swap = a;
00349 a = b;
00350 b = swap;
00351 }
00352
00353 dexp = a->exp - b->exp;
00354 r->exp = a->exp;
00355 if (dexp > SREAL_BITS)
00356 {
00357 #if SREAL_PART_BITS < 32
00358 r->sig_hi = a->sig_hi;
00359 r->sig_lo = a->sig_lo;
00360 #else
00361 r->sig = a->sig;
00362 #endif
00363 return r;
00364 }
00365
00366 if (dexp == 0)
00367 bb = b;
00368 else
00369 {
00370 copy (&tmp, b);
00371 shift_right (&tmp, dexp);
00372 bb = &tmp;
00373 }
00374
00375 #if SREAL_PART_BITS < 32
00376 r->sig_hi = a->sig_hi + bb->sig_hi;
00377 r->sig_lo = a->sig_lo + bb->sig_lo;
00378 if (r->sig_lo & ((uhwi) 1 << SREAL_PART_BITS))
00379 {
00380 r->sig_hi++;
00381 r->sig_lo -= (uhwi) 1 << SREAL_PART_BITS;
00382 }
00383 #else
00384 r->sig = a->sig + bb->sig;
00385 #endif
00386 normalize (r);
00387 return r;
00388 }
00389
00390
00391
00392 sreal *
00393 sreal_sub (sreal *r, sreal *a, sreal *b)
00394 {
00395 int dexp;
00396 sreal tmp;
00397 sreal *bb;
00398
00399 gcc_assert (sreal_compare (a, b) >= 0);
00400
00401 dexp = a->exp - b->exp;
00402 r->exp = a->exp;
00403 if (dexp > SREAL_BITS)
00404 {
00405 #if SREAL_PART_BITS < 32
00406 r->sig_hi = a->sig_hi;
00407 r->sig_lo = a->sig_lo;
00408 #else
00409 r->sig = a->sig;
00410 #endif
00411 return r;
00412 }
00413 if (dexp == 0)
00414 bb = b;
00415 else
00416 {
00417 copy (&tmp, b);
00418 shift_right (&tmp, dexp);
00419 bb = &tmp;
00420 }
00421
00422 #if SREAL_PART_BITS < 32
00423 if (a->sig_lo < bb->sig_lo)
00424 {
00425 r->sig_hi = a->sig_hi - bb->sig_hi - 1;
00426 r->sig_lo = a->sig_lo + ((uhwi) 1 << SREAL_PART_BITS) - bb->sig_lo;
00427 }
00428 else
00429 {
00430 r->sig_hi = a->sig_hi - bb->sig_hi;
00431 r->sig_lo = a->sig_lo - bb->sig_lo;
00432 }
00433 #else
00434 r->sig = a->sig - bb->sig;
00435 #endif
00436 normalize (r);
00437 return r;
00438 }
00439
00440
00441
00442 sreal *
00443 sreal_mul (sreal *r, sreal *a, sreal *b)
00444 {
00445 #if SREAL_PART_BITS < 32
00446 if (a->sig_hi < SREAL_MIN_SIG || b->sig_hi < SREAL_MIN_SIG)
00447 {
00448 r->sig_lo = 0;
00449 r->sig_hi = 0;
00450 r->exp = -SREAL_MAX_EXP;
00451 }
00452 else
00453 {
00454 unsigned HOST_WIDE_INT tmp1, tmp2, tmp3;
00455 if (sreal_compare (a, b) < 0)
00456 {
00457 sreal *swap;
00458 swap = a;
00459 a = b;
00460 b = swap;
00461 }
00462
00463 r->exp = a->exp + b->exp + SREAL_PART_BITS;
00464
00465 tmp1 = a->sig_lo * b->sig_lo;
00466 tmp2 = a->sig_lo * b->sig_hi;
00467 tmp3 = a->sig_hi * b->sig_lo + (tmp1 >> SREAL_PART_BITS);
00468
00469 r->sig_hi = a->sig_hi * b->sig_hi;
00470 r->sig_hi += (tmp2 >> SREAL_PART_BITS) + (tmp3 >> SREAL_PART_BITS);
00471 tmp2 &= ((uhwi) 1 << SREAL_PART_BITS) - 1;
00472 tmp3 &= ((uhwi) 1 << SREAL_PART_BITS) - 1;
00473 tmp1 = tmp2 + tmp3;
00474
00475 r->sig_lo = tmp1 & (((uhwi) 1 << SREAL_PART_BITS) - 1);
00476 r->sig_hi += tmp1 >> SREAL_PART_BITS;
00477
00478 normalize (r);
00479 }
00480 #else
00481 if (a->sig < SREAL_MIN_SIG || b->sig < SREAL_MIN_SIG)
00482 {
00483 r->sig = 0;
00484 r->exp = -SREAL_MAX_EXP;
00485 }
00486 else
00487 {
00488 r->sig = a->sig * b->sig;
00489 r->exp = a->exp + b->exp;
00490 normalize (r);
00491 }
00492 #endif
00493 return r;
00494 }
00495
00496
00497
00498 sreal *
00499 sreal_div (sreal *r, sreal *a, sreal *b)
00500 {
00501 #if SREAL_PART_BITS < 32
00502 unsigned HOST_WIDE_INT tmp, tmp1, tmp2;
00503
00504 gcc_assert (b->sig_hi >= SREAL_MIN_SIG);
00505 if (a->sig_hi < SREAL_MIN_SIG)
00506 {
00507 r->sig_hi = 0;
00508 r->sig_lo = 0;
00509 r->exp = -SREAL_MAX_EXP;
00510 }
00511 else
00512 {
00513
00514
00515
00516 tmp1 = (a->sig_hi << SREAL_PART_BITS) + a->sig_lo;
00517 tmp2 = ((b->sig_hi << (SREAL_PART_BITS / 2))
00518 + (b->sig_lo >> (SREAL_PART_BITS / 2)));
00519 if (b->sig_lo & ((uhwi) 1 << ((SREAL_PART_BITS / 2) - 1)))
00520 tmp2++;
00521
00522 r->sig_lo = 0;
00523 tmp = tmp1 / tmp2;
00524 tmp1 = (tmp1 % tmp2) << (SREAL_PART_BITS / 2);
00525 r->sig_hi = tmp << SREAL_PART_BITS;
00526
00527 tmp = tmp1 / tmp2;
00528 tmp1 = (tmp1 % tmp2) << (SREAL_PART_BITS / 2);
00529 r->sig_hi += tmp << (SREAL_PART_BITS / 2);
00530
00531 tmp = tmp1 / tmp2;
00532 r->sig_hi += tmp;
00533
00534 r->exp = a->exp - b->exp - SREAL_BITS - SREAL_PART_BITS / 2;
00535 normalize (r);
00536 }
00537 #else
00538 gcc_assert (b->sig != 0);
00539 r->sig = (a->sig << SREAL_PART_BITS) / b->sig;
00540 r->exp = a->exp - b->exp - SREAL_PART_BITS;
00541 normalize (r);
00542 #endif
00543 return r;
00544 }