FSF GCC merge 02/23/03
[official-gcc.git] / gcc / sreal.c
blob54648eafeec1251ead377e74f90ad6e18ad60a89
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, "((");
73 fprintf (file, HOST_WIDE_INT_PRINT_UNSIGNED, x->sig_hi);
74 fprintf (file, " * 2^16 + ");
75 fprintf (file, HOST_WIDE_INT_PRINT_UNSIGNED, x->sig_lo);
76 fprintf (file, ") * 2^%d)", x->exp);
77 #else
78 fprintf (file, "(");
79 fprintf (file, HOST_WIDE_INT_PRINT_UNSIGNED, x->sig);
80 fprintf (file, " * 2^%d)", x->exp);
81 #endif
84 /* Copy the sreal number. */
86 static inline void
87 copy (r, a)
88 sreal *r;
89 sreal *a;
91 #if SREAL_PART_BITS < 32
92 r->sig_lo = a->sig_lo;
93 r->sig_hi = a->sig_hi;
94 #else
95 r->sig = a->sig;
96 #endif
97 r->exp = a->exp;
100 /* Shift X right by S bits. Needed: 0 < S <= SREAL_BITS.
101 When the most significant bit shifted out is 1, add 1 to X (rounding). */
103 static inline void
104 shift_right (x, s)
105 sreal *x;
106 int s;
108 #ifdef ENABLE_CHECKING
109 if (s <= 0 || s > SREAL_BITS)
110 abort ();
111 if (x->exp + s > SREAL_MAX_EXP)
113 /* Exponent should never be so large because shift_right is used only by
114 sreal_add and sreal_sub ant thus the number cannot be shifted out from
115 exponent range. */
116 abort ();
118 #endif
120 x->exp += s;
122 #if SREAL_PART_BITS < 32
123 if (s > SREAL_PART_BITS)
125 s -= SREAL_PART_BITS;
126 x->sig_hi += (uhwi) 1 << (s - 1);
127 x->sig_lo = x->sig_hi >> s;
128 x->sig_hi = 0;
130 else
132 x->sig_lo += (uhwi) 1 << (s - 1);
133 if (x->sig_lo & ((uhwi) 1 << SREAL_PART_BITS))
135 x->sig_hi++;
136 x->sig_lo -= (uhwi) 1 << SREAL_PART_BITS;
138 x->sig_lo >>= s;
139 x->sig_lo |= (x->sig_hi & (((uhwi) 1 << s) - 1)) << (SREAL_PART_BITS - s);
140 x->sig_hi >>= s;
142 #else
143 x->sig += (uhwi) 1 << (s - 1);
144 x->sig >>= s;
145 #endif
148 /* Normalize *X. */
150 static void
151 normalize (x)
152 sreal *x;
154 #if SREAL_PART_BITS < 32
155 int shift;
156 HOST_WIDE_INT mask;
158 if (x->sig_lo == 0 && x->sig_hi == 0)
160 x->exp = -SREAL_MAX_EXP;
162 else if (x->sig_hi < SREAL_MIN_SIG)
164 if (x->sig_hi == 0)
166 /* Move lower part of significant to higher part. */
167 x->sig_hi = x->sig_lo;
168 x->sig_lo = 0;
169 x->exp -= SREAL_PART_BITS;
171 shift = 0;
172 while (x->sig_hi < SREAL_MIN_SIG)
174 x->sig_hi <<= 1;
175 x->exp--;
176 shift++;
178 /* Check underflow. */
179 if (x->exp < -SREAL_MAX_EXP)
181 x->exp = -SREAL_MAX_EXP;
182 x->sig_hi = 0;
183 x->sig_lo = 0;
185 else if (shift)
187 mask = (1 << SREAL_PART_BITS) - (1 << (SREAL_PART_BITS - shift));
188 x->sig_hi |= (x->sig_lo & mask) >> (SREAL_PART_BITS - shift);
189 x->sig_lo = (x->sig_lo << shift) & (((uhwi) 1 << SREAL_PART_BITS) - 1);
192 else if (x->sig_hi > SREAL_MAX_SIG)
194 unsigned HOST_WIDE_INT tmp = x->sig_hi;
196 /* Find out how many bits will be shifted. */
197 shift = 0;
200 tmp >>= 1;
201 shift++;
203 while (tmp > SREAL_MAX_SIG);
205 /* Round the number. */
206 x->sig_lo += (uhwi) 1 << (shift - 1);
208 x->sig_lo >>= shift;
209 x->sig_lo += ((x->sig_hi & (((uhwi) 1 << shift) - 1))
210 << (SREAL_PART_BITS - shift));
211 x->sig_hi >>= shift;
212 x->exp += shift;
213 if (x->sig_lo & ((uhwi) 1 << SREAL_PART_BITS))
215 x->sig_lo -= (uhwi) 1 << SREAL_PART_BITS;
216 x->sig_hi++;
217 if (x->sig_hi > SREAL_MAX_SIG)
219 /* x->sig_hi was SREAL_MAX_SIG before increment
220 so now last bit is zero. */
221 x->sig_hi >>= 1;
222 x->sig_lo >>= 1;
223 x->exp++;
227 /* Check overflow. */
228 if (x->exp > SREAL_MAX_EXP)
230 x->exp = SREAL_MAX_EXP;
231 x->sig_hi = SREAL_MAX_SIG;
232 x->sig_lo = SREAL_MAX_SIG;
235 #else
236 if (x->sig == 0)
238 x->exp = -SREAL_MAX_EXP;
240 else if (x->sig < SREAL_MIN_SIG)
244 x->sig <<= 1;
245 x->exp--;
247 while (x->sig < SREAL_MIN_SIG);
249 /* Check underflow. */
250 if (x->exp < -SREAL_MAX_EXP)
252 x->exp = -SREAL_MAX_EXP;
253 x->sig = 0;
256 else if (x->sig > SREAL_MAX_SIG)
258 int last_bit;
261 last_bit = x->sig & 1;
262 x->sig >>= 1;
263 x->exp++;
265 while (x->sig > SREAL_MAX_SIG);
267 /* Round the number. */
268 x->sig += last_bit;
269 if (x->sig > SREAL_MAX_SIG)
271 x->sig >>= 1;
272 x->exp++;
275 /* Check overflow. */
276 if (x->exp > SREAL_MAX_EXP)
278 x->exp = SREAL_MAX_EXP;
279 x->sig = SREAL_MAX_SIG;
282 #endif
285 /* Set *R to SIG * 2 ^ EXP. Return R. */
287 sreal *
288 sreal_init (r, sig, exp)
289 sreal *r;
290 unsigned HOST_WIDE_INT sig;
291 signed int exp;
293 #if SREAL_PART_BITS < 32
294 r->sig_lo = 0;
295 r->sig_hi = sig;
296 r->exp = exp - 16;
297 #else
298 r->sig = sig;
299 r->exp = exp;
300 #endif
301 normalize (r);
302 return r;
305 /* Return integer value of *R. */
307 HOST_WIDE_INT
308 sreal_to_int (r)
309 sreal *r;
311 #if SREAL_PART_BITS < 32
312 if (r->exp <= -SREAL_BITS)
313 return 0;
314 if (r->exp >= 0)
315 return MAX_HOST_WIDE_INT;
316 return ((r->sig_hi << SREAL_PART_BITS) + r->sig_lo) >> -r->exp;
317 #else
318 if (r->exp <= -SREAL_BITS)
319 return 0;
320 if (r->exp >= SREAL_PART_BITS)
321 return MAX_HOST_WIDE_INT;
322 if (r->exp > 0)
323 return r->sig << r->exp;
324 if (r->exp < 0)
325 return r->sig >> -r->exp;
326 return r->sig;
327 #endif
330 /* Compare *A and *B. Return -1 if *A < *B, 1 if *A > *B and 0 if *A == *B. */
333 sreal_compare (a, b)
334 sreal *a;
335 sreal *b;
337 if (a->exp > b->exp)
338 return 1;
339 if (a->exp < b->exp)
340 return -1;
341 #if SREAL_PART_BITS < 32
342 if (a->sig_hi > b->sig_hi)
343 return 1;
344 if (a->sig_hi < b->sig_hi)
345 return -1;
346 if (a->sig_lo > b->sig_lo)
347 return 1;
348 if (a->sig_lo < b->sig_lo)
349 return -1;
350 #else
351 if (a->sig > b->sig)
352 return 1;
353 if (a->sig < b->sig)
354 return -1;
355 #endif
356 return 0;
359 /* *R = *A + *B. Return R. */
361 sreal *
362 sreal_add (r, a, b)
363 sreal *r;
364 sreal *a;
365 sreal *b;
367 int dexp;
368 sreal tmp;
369 sreal *bb;
371 if (sreal_compare (a, b) < 0)
373 sreal *swap;
374 swap = a;
375 a = b;
376 b = swap;
379 dexp = a->exp - b->exp;
380 r->exp = a->exp;
381 if (dexp > SREAL_BITS)
383 #if SREAL_PART_BITS < 32
384 r->sig_hi = a->sig_hi;
385 r->sig_lo = a->sig_lo;
386 #else
387 r->sig = a->sig;
388 #endif
389 return r;
392 if (dexp == 0)
393 bb = b;
394 else
396 copy (&tmp, b);
397 shift_right (&tmp, dexp);
398 bb = &tmp;
401 #if SREAL_PART_BITS < 32
402 r->sig_hi = a->sig_hi + bb->sig_hi;
403 r->sig_lo = a->sig_lo + bb->sig_lo;
404 if (r->sig_lo & ((uhwi) 1 << SREAL_PART_BITS))
406 r->sig_hi++;
407 r->sig_lo -= (uhwi) 1 << SREAL_PART_BITS;
409 #else
410 r->sig = a->sig + bb->sig;
411 #endif
412 normalize (r);
413 return r;
416 /* *R = *A - *B. Return R. */
418 sreal *
419 sreal_sub (r, a, b)
420 sreal *r;
421 sreal *a;
422 sreal *b;
424 int dexp;
425 sreal tmp;
426 sreal *bb;
428 if (sreal_compare (a, b) < 0)
430 abort ();
433 dexp = a->exp - b->exp;
434 r->exp = a->exp;
435 if (dexp > SREAL_BITS)
437 #if SREAL_PART_BITS < 32
438 r->sig_hi = a->sig_hi;
439 r->sig_lo = a->sig_lo;
440 #else
441 r->sig = a->sig;
442 #endif
443 return r;
445 if (dexp == 0)
446 bb = b;
447 else
449 copy (&tmp, b);
450 shift_right (&tmp, dexp);
451 bb = &tmp;
454 #if SREAL_PART_BITS < 32
455 if (a->sig_lo < bb->sig_lo)
457 r->sig_hi = a->sig_hi - bb->sig_hi - 1;
458 r->sig_lo = a->sig_lo + ((uhwi) 1 << SREAL_PART_BITS) - bb->sig_lo;
460 else
462 r->sig_hi = a->sig_hi - bb->sig_hi;
463 r->sig_lo = a->sig_lo - bb->sig_lo;
465 #else
466 r->sig = a->sig - bb->sig;
467 #endif
468 normalize (r);
469 return r;
472 /* *R = *A * *B. Return R. */
474 sreal *
475 sreal_mul (r, a, b)
476 sreal *r;
477 sreal *a;
478 sreal *b;
480 #if SREAL_PART_BITS < 32
481 if (a->sig_hi < SREAL_MIN_SIG || b->sig_hi < SREAL_MIN_SIG)
483 r->sig_lo = 0;
484 r->sig_hi = 0;
485 r->exp = -SREAL_MAX_EXP;
487 else
489 unsigned HOST_WIDE_INT tmp1, tmp2, tmp3;
490 if (sreal_compare (a, b) < 0)
492 sreal *swap;
493 swap = a;
494 a = b;
495 b = swap;
498 r->exp = a->exp + b->exp + SREAL_PART_BITS;
500 tmp1 = a->sig_lo * b->sig_lo;
501 tmp2 = a->sig_lo * b->sig_hi;
502 tmp3 = a->sig_hi * b->sig_lo + (tmp1 >> SREAL_PART_BITS);
504 r->sig_hi = a->sig_hi * b->sig_hi;
505 r->sig_hi += (tmp2 >> SREAL_PART_BITS) + (tmp3 >> SREAL_PART_BITS);
506 tmp2 &= ((uhwi) 1 << SREAL_PART_BITS) - 1;
507 tmp3 &= ((uhwi) 1 << SREAL_PART_BITS) - 1;
508 tmp1 = tmp2 + tmp3;
510 r->sig_lo = tmp1 & (((uhwi) 1 << SREAL_PART_BITS) - 1);
511 r->sig_hi += tmp1 >> SREAL_PART_BITS;
513 normalize (r);
515 #else
516 if (a->sig < SREAL_MIN_SIG || b->sig < SREAL_MIN_SIG)
518 r->sig = 0;
519 r->exp = -SREAL_MAX_EXP;
521 else
523 r->sig = a->sig * b->sig;
524 r->exp = a->exp + b->exp;
525 normalize (r);
527 #endif
528 return r;
531 /* *R = *A / *B. Return R. */
533 sreal *
534 sreal_div (r, a, b)
535 sreal *r;
536 sreal *a;
537 sreal *b;
539 #if SREAL_PART_BITS < 32
540 unsigned HOST_WIDE_INT tmp, tmp1, tmp2;
542 if (b->sig_hi < SREAL_MIN_SIG)
544 abort ();
546 else if (a->sig_hi < SREAL_MIN_SIG)
548 r->sig_hi = 0;
549 r->sig_lo = 0;
550 r->exp = -SREAL_MAX_EXP;
552 else
554 /* Since division by the whole number is pretty ugly to write
555 we are dividing by first 3/4 of bits of number. */
557 tmp1 = (a->sig_hi << SREAL_PART_BITS) + a->sig_lo;
558 tmp2 = ((b->sig_hi << (SREAL_PART_BITS / 2))
559 + (b->sig_lo >> (SREAL_PART_BITS / 2)));
560 if (b->sig_lo & ((uhwi) 1 << ((SREAL_PART_BITS / 2) - 1)))
561 tmp2++;
563 r->sig_lo = 0;
564 tmp = tmp1 / tmp2;
565 tmp1 = (tmp1 % tmp2) << (SREAL_PART_BITS / 2);
566 r->sig_hi = tmp << SREAL_PART_BITS;
568 tmp = tmp1 / tmp2;
569 tmp1 = (tmp1 % tmp2) << (SREAL_PART_BITS / 2);
570 r->sig_hi += tmp << (SREAL_PART_BITS / 2);
572 tmp = tmp1 / tmp2;
573 r->sig_hi += tmp;
575 r->exp = a->exp - b->exp - SREAL_BITS - SREAL_PART_BITS / 2;
576 normalize (r);
578 #else
579 if (b->sig == 0)
581 abort ();
583 else
585 r->sig = (a->sig << SREAL_PART_BITS) / b->sig;
586 r->exp = a->exp - b->exp - SREAL_PART_BITS;
587 normalize (r);
589 #endif
590 return r;