2002-06-06 James Clark <jjc@jclark.com>
[official-gcc.git] / gcc / sreal.c
blob0468a9631b08fd80488cfe611c93509f18adc51a
1 /* Simple data type for positive real numbers for the GNU compiler.
2 Copyright (C) 2002, 2003 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
9 version.
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING. If not, write to the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
21 /* This library supports positive real numbers and 0;
22 inf and nan are NOT supported.
23 It is written to be simple and fast.
25 Value of sreal is
26 x = sig * 2 ^ exp
27 where
28 sig = significant
29 (for < 64-bit machines sig = sig_lo + sig_hi * 2 ^ SREAL_PART_BITS)
30 exp = exponent
32 One HOST_WIDE_INT is used for the significant on 64-bit (and more than
33 64-bit) machines,
34 otherwise two HOST_WIDE_INTs are used for the significant.
35 Only a half of significant bits is used (in normalized sreals) so that we do
36 not have problems with overflow, for example when c->sig = a->sig * b->sig.
37 So the precission for 64-bit and 32-bit machines is 32-bit.
39 Invariant: The numbers are normalized before and after each call of sreal_*.
41 Normalized sreals:
42 All numbers (except zero) meet following conditions:
43 SREAL_MIN_SIG <= sig && sig <= SREAL_MAX_SIG
44 -SREAL_MAX_EXP <= exp && exp <= SREAL_MAX_EXP
46 If the number would be too large, it is set to upper bounds of these
47 conditions.
49 If the number is zero or would be too small it meets following conditions:
50 sig == 0 && exp == -SREAL_MAX_EXP
53 #include "config.h"
54 #include "system.h"
55 #include "coretypes.h"
56 #include "tm.h"
57 #include "sreal.h"
59 void dump_sreal PARAMS ((FILE *, sreal *));
60 static inline void copy PARAMS ((sreal *, sreal *));
61 static inline void shift_right PARAMS ((sreal *, int));
62 static void normalize PARAMS ((sreal *));
64 /* Print the content of struct sreal. */
66 void
67 dump_sreal (file, x)
68 FILE *file;
69 sreal *x;
71 #if SREAL_PART_BITS < 32
72 fprintf (file, "((" HOST_WIDE_INT_PRINT_UNSIGNED " * 2^16 + "
73 HOST_WIDE_INT_PRINT_UNSIGNED ") * 2^%d)",
74 x->sig_hi, x->sig_lo, x->exp);
75 #else
76 fprintf (file, "(" HOST_WIDE_INT_PRINT_UNSIGNED " * 2^%d)", x->sig, x->exp);
77 #endif
80 /* Copy the sreal number. */
82 static inline void
83 copy (r, a)
84 sreal *r;
85 sreal *a;
87 #if SREAL_PART_BITS < 32
88 r->sig_lo = a->sig_lo;
89 r->sig_hi = a->sig_hi;
90 #else
91 r->sig = a->sig;
92 #endif
93 r->exp = a->exp;
96 /* Shift X right by S bits. Needed: 0 < S <= SREAL_BITS.
97 When the most significant bit shifted out is 1, add 1 to X (rounding). */
99 static inline void
100 shift_right (x, s)
101 sreal *x;
102 int s;
104 #ifdef ENABLE_CHECKING
105 if (s <= 0 || s > SREAL_BITS)
106 abort ();
107 if (x->exp + s > SREAL_MAX_EXP)
109 /* Exponent should never be so large because shift_right is used only by
110 sreal_add and sreal_sub ant thus the number cannot be shifted out from
111 exponent range. */
112 abort ();
114 #endif
116 x->exp += s;
118 #if SREAL_PART_BITS < 32
119 if (s > SREAL_PART_BITS)
121 s -= SREAL_PART_BITS;
122 x->sig_hi += (uhwi) 1 << (s - 1);
123 x->sig_lo = x->sig_hi >> s;
124 x->sig_hi = 0;
126 else
128 x->sig_lo += (uhwi) 1 << (s - 1);
129 if (x->sig_lo & ((uhwi) 1 << SREAL_PART_BITS))
131 x->sig_hi++;
132 x->sig_lo -= (uhwi) 1 << SREAL_PART_BITS;
134 x->sig_lo >>= s;
135 x->sig_lo |= (x->sig_hi & (((uhwi) 1 << s) - 1)) << (SREAL_PART_BITS - s);
136 x->sig_hi >>= s;
138 #else
139 x->sig += (uhwi) 1 << (s - 1);
140 x->sig >>= s;
141 #endif
144 /* Normalize *X. */
146 static void
147 normalize (x)
148 sreal *x;
150 #if SREAL_PART_BITS < 32
151 int shift;
152 HOST_WIDE_INT mask;
154 if (x->sig_lo == 0 && x->sig_hi == 0)
156 x->exp = -SREAL_MAX_EXP;
158 else if (x->sig_hi < SREAL_MIN_SIG)
160 if (x->sig_hi == 0)
162 /* Move lower part of significant to higher part. */
163 x->sig_hi = x->sig_lo;
164 x->sig_lo = 0;
165 x->exp -= SREAL_PART_BITS;
167 shift = 0;
168 while (x->sig_hi < SREAL_MIN_SIG)
170 x->sig_hi <<= 1;
171 x->exp--;
172 shift++;
174 /* Check underflow. */
175 if (x->exp < -SREAL_MAX_EXP)
177 x->exp = -SREAL_MAX_EXP;
178 x->sig_hi = 0;
179 x->sig_lo = 0;
181 else if (shift)
183 mask = (1 << SREAL_PART_BITS) - (1 << (SREAL_PART_BITS - shift));
184 x->sig_hi |= (x->sig_lo & mask) >> (SREAL_PART_BITS - shift);
185 x->sig_lo = (x->sig_lo << shift) & (((uhwi) 1 << SREAL_PART_BITS) - 1);
188 else if (x->sig_hi > SREAL_MAX_SIG)
190 unsigned HOST_WIDE_INT tmp = x->sig_hi;
192 /* Find out how many bits will be shifted. */
193 shift = 0;
196 tmp >>= 1;
197 shift++;
199 while (tmp > SREAL_MAX_SIG);
201 /* Round the number. */
202 x->sig_lo += (uhwi) 1 << (shift - 1);
204 x->sig_lo >>= shift;
205 x->sig_lo += ((x->sig_hi & (((uhwi) 1 << shift) - 1))
206 << (SREAL_PART_BITS - shift));
207 x->sig_hi >>= shift;
208 x->exp += shift;
209 if (x->sig_lo & ((uhwi) 1 << SREAL_PART_BITS))
211 x->sig_lo -= (uhwi) 1 << SREAL_PART_BITS;
212 x->sig_hi++;
213 if (x->sig_hi > SREAL_MAX_SIG)
215 /* x->sig_hi was SREAL_MAX_SIG before increment
216 so now last bit is zero. */
217 x->sig_hi >>= 1;
218 x->sig_lo >>= 1;
219 x->exp++;
223 /* Check overflow. */
224 if (x->exp > SREAL_MAX_EXP)
226 x->exp = SREAL_MAX_EXP;
227 x->sig_hi = SREAL_MAX_SIG;
228 x->sig_lo = SREAL_MAX_SIG;
231 #else
232 if (x->sig == 0)
234 x->exp = -SREAL_MAX_EXP;
236 else if (x->sig < SREAL_MIN_SIG)
240 x->sig <<= 1;
241 x->exp--;
243 while (x->sig < SREAL_MIN_SIG);
245 /* Check underflow. */
246 if (x->exp < -SREAL_MAX_EXP)
248 x->exp = -SREAL_MAX_EXP;
249 x->sig = 0;
252 else if (x->sig > SREAL_MAX_SIG)
254 int last_bit;
257 last_bit = x->sig & 1;
258 x->sig >>= 1;
259 x->exp++;
261 while (x->sig > SREAL_MAX_SIG);
263 /* Round the number. */
264 x->sig += last_bit;
265 if (x->sig > SREAL_MAX_SIG)
267 x->sig >>= 1;
268 x->exp++;
271 /* Check overflow. */
272 if (x->exp > SREAL_MAX_EXP)
274 x->exp = SREAL_MAX_EXP;
275 x->sig = SREAL_MAX_SIG;
278 #endif
281 /* Set *R to SIG * 2 ^ EXP. Return R. */
283 sreal *
284 sreal_init (r, sig, exp)
285 sreal *r;
286 unsigned HOST_WIDE_INT sig;
287 signed int exp;
289 #if SREAL_PART_BITS < 32
290 r->sig_lo = 0;
291 r->sig_hi = sig;
292 r->exp = exp - 16;
293 #else
294 r->sig = sig;
295 r->exp = exp;
296 #endif
297 normalize (r);
298 return r;
301 /* Return integer value of *R. */
303 HOST_WIDE_INT
304 sreal_to_int (r)
305 sreal *r;
307 #if SREAL_PART_BITS < 32
308 if (r->exp <= -SREAL_BITS)
309 return 0;
310 if (r->exp >= 0)
311 return MAX_HOST_WIDE_INT;
312 return ((r->sig_hi << SREAL_PART_BITS) + r->sig_lo) >> -r->exp;
313 #else
314 if (r->exp <= -SREAL_BITS)
315 return 0;
316 if (r->exp >= SREAL_PART_BITS)
317 return MAX_HOST_WIDE_INT;
318 if (r->exp > 0)
319 return r->sig << r->exp;
320 if (r->exp < 0)
321 return r->sig >> -r->exp;
322 return r->sig;
323 #endif
326 /* Compare *A and *B. Return -1 if *A < *B, 1 if *A > *B and 0 if *A == *B. */
329 sreal_compare (a, b)
330 sreal *a;
331 sreal *b;
333 if (a->exp > b->exp)
334 return 1;
335 if (a->exp < b->exp)
336 return -1;
337 #if SREAL_PART_BITS < 32
338 if (a->sig_hi > b->sig_hi)
339 return 1;
340 if (a->sig_hi < b->sig_hi)
341 return -1;
342 if (a->sig_lo > b->sig_lo)
343 return 1;
344 if (a->sig_lo < b->sig_lo)
345 return -1;
346 #else
347 if (a->sig > b->sig)
348 return 1;
349 if (a->sig < b->sig)
350 return -1;
351 #endif
352 return 0;
355 /* *R = *A + *B. Return R. */
357 sreal *
358 sreal_add (r, a, b)
359 sreal *r;
360 sreal *a;
361 sreal *b;
363 int dexp;
364 sreal tmp;
365 sreal *bb;
367 if (sreal_compare (a, b) < 0)
369 sreal *swap;
370 swap = a;
371 a = b;
372 b = swap;
375 dexp = a->exp - b->exp;
376 r->exp = a->exp;
377 if (dexp > SREAL_BITS)
379 #if SREAL_PART_BITS < 32
380 r->sig_hi = a->sig_hi;
381 r->sig_lo = a->sig_lo;
382 #else
383 r->sig = a->sig;
384 #endif
385 return r;
388 if (dexp == 0)
389 bb = b;
390 else
392 copy (&tmp, b);
393 shift_right (&tmp, dexp);
394 bb = &tmp;
397 #if SREAL_PART_BITS < 32
398 r->sig_hi = a->sig_hi + bb->sig_hi;
399 r->sig_lo = a->sig_lo + bb->sig_lo;
400 if (r->sig_lo & ((uhwi) 1 << SREAL_PART_BITS))
402 r->sig_hi++;
403 r->sig_lo -= (uhwi) 1 << SREAL_PART_BITS;
405 #else
406 r->sig = a->sig + bb->sig;
407 #endif
408 normalize (r);
409 return r;
412 /* *R = *A - *B. Return R. */
414 sreal *
415 sreal_sub (r, a, b)
416 sreal *r;
417 sreal *a;
418 sreal *b;
420 int dexp;
421 sreal tmp;
422 sreal *bb;
424 if (sreal_compare (a, b) < 0)
426 abort ();
429 dexp = a->exp - b->exp;
430 r->exp = a->exp;
431 if (dexp > SREAL_BITS)
433 #if SREAL_PART_BITS < 32
434 r->sig_hi = a->sig_hi;
435 r->sig_lo = a->sig_lo;
436 #else
437 r->sig = a->sig;
438 #endif
439 return r;
441 if (dexp == 0)
442 bb = b;
443 else
445 copy (&tmp, b);
446 shift_right (&tmp, dexp);
447 bb = &tmp;
450 #if SREAL_PART_BITS < 32
451 if (a->sig_lo < bb->sig_lo)
453 r->sig_hi = a->sig_hi - bb->sig_hi - 1;
454 r->sig_lo = a->sig_lo + ((uhwi) 1 << SREAL_PART_BITS) - bb->sig_lo;
456 else
458 r->sig_hi = a->sig_hi - bb->sig_hi;
459 r->sig_lo = a->sig_lo - bb->sig_lo;
461 #else
462 r->sig = a->sig - bb->sig;
463 #endif
464 normalize (r);
465 return r;
468 /* *R = *A * *B. Return R. */
470 sreal *
471 sreal_mul (r, a, b)
472 sreal *r;
473 sreal *a;
474 sreal *b;
476 #if SREAL_PART_BITS < 32
477 if (a->sig_hi < SREAL_MIN_SIG || b->sig_hi < SREAL_MIN_SIG)
479 r->sig_lo = 0;
480 r->sig_hi = 0;
481 r->exp = -SREAL_MAX_EXP;
483 else
485 unsigned HOST_WIDE_INT tmp1, tmp2, tmp3;
486 if (sreal_compare (a, b) < 0)
488 sreal *swap;
489 swap = a;
490 a = b;
491 b = swap;
494 r->exp = a->exp + b->exp + SREAL_PART_BITS;
496 tmp1 = a->sig_lo * b->sig_lo;
497 tmp2 = a->sig_lo * b->sig_hi;
498 tmp3 = a->sig_hi * b->sig_lo + (tmp1 >> SREAL_PART_BITS);
500 r->sig_hi = a->sig_hi * b->sig_hi;
501 r->sig_hi += (tmp2 >> SREAL_PART_BITS) + (tmp3 >> SREAL_PART_BITS);
502 tmp2 &= ((uhwi) 1 << SREAL_PART_BITS) - 1;
503 tmp3 &= ((uhwi) 1 << SREAL_PART_BITS) - 1;
504 tmp1 = tmp2 + tmp3;
506 r->sig_lo = tmp1 & (((uhwi) 1 << SREAL_PART_BITS) - 1);
507 r->sig_hi += tmp1 >> SREAL_PART_BITS;
509 normalize (r);
511 #else
512 if (a->sig < SREAL_MIN_SIG || b->sig < SREAL_MIN_SIG)
514 r->sig = 0;
515 r->exp = -SREAL_MAX_EXP;
517 else
519 r->sig = a->sig * b->sig;
520 r->exp = a->exp + b->exp;
521 normalize (r);
523 #endif
524 return r;
527 /* *R = *A / *B. Return R. */
529 sreal *
530 sreal_div (r, a, b)
531 sreal *r;
532 sreal *a;
533 sreal *b;
535 #if SREAL_PART_BITS < 32
536 unsigned HOST_WIDE_INT tmp, tmp1, tmp2;
538 if (b->sig_hi < SREAL_MIN_SIG)
540 abort ();
542 else if (a->sig_hi < SREAL_MIN_SIG)
544 r->sig_hi = 0;
545 r->sig_lo = 0;
546 r->exp = -SREAL_MAX_EXP;
548 else
550 /* Since division by the whole number is pretty ugly to write
551 we are dividing by first 3/4 of bits of number. */
553 tmp1 = (a->sig_hi << SREAL_PART_BITS) + a->sig_lo;
554 tmp2 = ((b->sig_hi << (SREAL_PART_BITS / 2))
555 + (b->sig_lo >> (SREAL_PART_BITS / 2)));
556 if (b->sig_lo & ((uhwi) 1 << ((SREAL_PART_BITS / 2) - 1)))
557 tmp2++;
559 r->sig_lo = 0;
560 tmp = tmp1 / tmp2;
561 tmp1 = (tmp1 % tmp2) << (SREAL_PART_BITS / 2);
562 r->sig_hi = tmp << SREAL_PART_BITS;
564 tmp = tmp1 / tmp2;
565 tmp1 = (tmp1 % tmp2) << (SREAL_PART_BITS / 2);
566 r->sig_hi += tmp << (SREAL_PART_BITS / 2);
568 tmp = tmp1 / tmp2;
569 r->sig_hi += tmp;
571 r->exp = a->exp - b->exp - SREAL_BITS - SREAL_PART_BITS / 2;
572 normalize (r);
574 #else
575 if (b->sig == 0)
577 abort ();
579 else
581 r->sig = (a->sig << SREAL_PART_BITS) / b->sig;
582 r->exp = a->exp - b->exp - SREAL_PART_BITS;
583 normalize (r);
585 #endif
586 return r;