include/ChangeLog:
[official-gcc.git] / gcc / sreal.c
blobf69cbb1f862a296105400f2becc00875e4736b77
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 static inline void copy PARAMS ((sreal *, sreal *));
60 static inline void shift_right PARAMS ((sreal *, int));
61 static void normalize PARAMS ((sreal *));
63 /* Print the content of struct sreal. */
65 void
66 dump_sreal (file, x)
67 FILE *file;
68 sreal *x;
70 #if SREAL_PART_BITS < 32
71 fprintf (file, "((" HOST_WIDE_INT_PRINT_UNSIGNED " * 2^16 + "
72 HOST_WIDE_INT_PRINT_UNSIGNED ") * 2^%d)",
73 x->sig_hi, x->sig_lo, x->exp);
74 #else
75 fprintf (file, "(" HOST_WIDE_INT_PRINT_UNSIGNED " * 2^%d)", x->sig, x->exp);
76 #endif
79 /* Copy the sreal number. */
81 static inline void
82 copy (r, a)
83 sreal *r;
84 sreal *a;
86 #if SREAL_PART_BITS < 32
87 r->sig_lo = a->sig_lo;
88 r->sig_hi = a->sig_hi;
89 #else
90 r->sig = a->sig;
91 #endif
92 r->exp = a->exp;
95 /* Shift X right by S bits. Needed: 0 < S <= SREAL_BITS.
96 When the most significant bit shifted out is 1, add 1 to X (rounding). */
98 static inline void
99 shift_right (x, s)
100 sreal *x;
101 int s;
103 #ifdef ENABLE_CHECKING
104 if (s <= 0 || s > SREAL_BITS)
105 abort ();
106 if (x->exp + s > SREAL_MAX_EXP)
108 /* Exponent should never be so large because shift_right is used only by
109 sreal_add and sreal_sub ant thus the number cannot be shifted out from
110 exponent range. */
111 abort ();
113 #endif
115 x->exp += s;
117 #if SREAL_PART_BITS < 32
118 if (s > SREAL_PART_BITS)
120 s -= SREAL_PART_BITS;
121 x->sig_hi += (uhwi) 1 << (s - 1);
122 x->sig_lo = x->sig_hi >> s;
123 x->sig_hi = 0;
125 else
127 x->sig_lo += (uhwi) 1 << (s - 1);
128 if (x->sig_lo & ((uhwi) 1 << SREAL_PART_BITS))
130 x->sig_hi++;
131 x->sig_lo -= (uhwi) 1 << SREAL_PART_BITS;
133 x->sig_lo >>= s;
134 x->sig_lo |= (x->sig_hi & (((uhwi) 1 << s) - 1)) << (SREAL_PART_BITS - s);
135 x->sig_hi >>= s;
137 #else
138 x->sig += (uhwi) 1 << (s - 1);
139 x->sig >>= s;
140 #endif
143 /* Normalize *X. */
145 static void
146 normalize (x)
147 sreal *x;
149 #if SREAL_PART_BITS < 32
150 int shift;
151 HOST_WIDE_INT mask;
153 if (x->sig_lo == 0 && x->sig_hi == 0)
155 x->exp = -SREAL_MAX_EXP;
157 else if (x->sig_hi < SREAL_MIN_SIG)
159 if (x->sig_hi == 0)
161 /* Move lower part of significant to higher part. */
162 x->sig_hi = x->sig_lo;
163 x->sig_lo = 0;
164 x->exp -= SREAL_PART_BITS;
166 shift = 0;
167 while (x->sig_hi < SREAL_MIN_SIG)
169 x->sig_hi <<= 1;
170 x->exp--;
171 shift++;
173 /* Check underflow. */
174 if (x->exp < -SREAL_MAX_EXP)
176 x->exp = -SREAL_MAX_EXP;
177 x->sig_hi = 0;
178 x->sig_lo = 0;
180 else if (shift)
182 mask = (1 << SREAL_PART_BITS) - (1 << (SREAL_PART_BITS - shift));
183 x->sig_hi |= (x->sig_lo & mask) >> (SREAL_PART_BITS - shift);
184 x->sig_lo = (x->sig_lo << shift) & (((uhwi) 1 << SREAL_PART_BITS) - 1);
187 else if (x->sig_hi > SREAL_MAX_SIG)
189 unsigned HOST_WIDE_INT tmp = x->sig_hi;
191 /* Find out how many bits will be shifted. */
192 shift = 0;
195 tmp >>= 1;
196 shift++;
198 while (tmp > SREAL_MAX_SIG);
200 /* Round the number. */
201 x->sig_lo += (uhwi) 1 << (shift - 1);
203 x->sig_lo >>= shift;
204 x->sig_lo += ((x->sig_hi & (((uhwi) 1 << shift) - 1))
205 << (SREAL_PART_BITS - shift));
206 x->sig_hi >>= shift;
207 x->exp += shift;
208 if (x->sig_lo & ((uhwi) 1 << SREAL_PART_BITS))
210 x->sig_lo -= (uhwi) 1 << SREAL_PART_BITS;
211 x->sig_hi++;
212 if (x->sig_hi > SREAL_MAX_SIG)
214 /* x->sig_hi was SREAL_MAX_SIG before increment
215 so now last bit is zero. */
216 x->sig_hi >>= 1;
217 x->sig_lo >>= 1;
218 x->exp++;
222 /* Check overflow. */
223 if (x->exp > SREAL_MAX_EXP)
225 x->exp = SREAL_MAX_EXP;
226 x->sig_hi = SREAL_MAX_SIG;
227 x->sig_lo = SREAL_MAX_SIG;
230 #else
231 if (x->sig == 0)
233 x->exp = -SREAL_MAX_EXP;
235 else if (x->sig < SREAL_MIN_SIG)
239 x->sig <<= 1;
240 x->exp--;
242 while (x->sig < SREAL_MIN_SIG);
244 /* Check underflow. */
245 if (x->exp < -SREAL_MAX_EXP)
247 x->exp = -SREAL_MAX_EXP;
248 x->sig = 0;
251 else if (x->sig > SREAL_MAX_SIG)
253 int last_bit;
256 last_bit = x->sig & 1;
257 x->sig >>= 1;
258 x->exp++;
260 while (x->sig > SREAL_MAX_SIG);
262 /* Round the number. */
263 x->sig += last_bit;
264 if (x->sig > SREAL_MAX_SIG)
266 x->sig >>= 1;
267 x->exp++;
270 /* Check overflow. */
271 if (x->exp > SREAL_MAX_EXP)
273 x->exp = SREAL_MAX_EXP;
274 x->sig = SREAL_MAX_SIG;
277 #endif
280 /* Set *R to SIG * 2 ^ EXP. Return R. */
282 sreal *
283 sreal_init (r, sig, exp)
284 sreal *r;
285 unsigned HOST_WIDE_INT sig;
286 signed int exp;
288 #if SREAL_PART_BITS < 32
289 r->sig_lo = 0;
290 r->sig_hi = sig;
291 r->exp = exp - 16;
292 #else
293 r->sig = sig;
294 r->exp = exp;
295 #endif
296 normalize (r);
297 return r;
300 /* Return integer value of *R. */
302 HOST_WIDE_INT
303 sreal_to_int (r)
304 sreal *r;
306 #if SREAL_PART_BITS < 32
307 if (r->exp <= -SREAL_BITS)
308 return 0;
309 if (r->exp >= 0)
310 return MAX_HOST_WIDE_INT;
311 return ((r->sig_hi << SREAL_PART_BITS) + r->sig_lo) >> -r->exp;
312 #else
313 if (r->exp <= -SREAL_BITS)
314 return 0;
315 if (r->exp >= SREAL_PART_BITS)
316 return MAX_HOST_WIDE_INT;
317 if (r->exp > 0)
318 return r->sig << r->exp;
319 if (r->exp < 0)
320 return r->sig >> -r->exp;
321 return r->sig;
322 #endif
325 /* Compare *A and *B. Return -1 if *A < *B, 1 if *A > *B and 0 if *A == *B. */
328 sreal_compare (a, b)
329 sreal *a;
330 sreal *b;
332 if (a->exp > b->exp)
333 return 1;
334 if (a->exp < b->exp)
335 return -1;
336 #if SREAL_PART_BITS < 32
337 if (a->sig_hi > b->sig_hi)
338 return 1;
339 if (a->sig_hi < b->sig_hi)
340 return -1;
341 if (a->sig_lo > b->sig_lo)
342 return 1;
343 if (a->sig_lo < b->sig_lo)
344 return -1;
345 #else
346 if (a->sig > b->sig)
347 return 1;
348 if (a->sig < b->sig)
349 return -1;
350 #endif
351 return 0;
354 /* *R = *A + *B. Return R. */
356 sreal *
357 sreal_add (r, a, b)
358 sreal *r;
359 sreal *a;
360 sreal *b;
362 int dexp;
363 sreal tmp;
364 sreal *bb;
366 if (sreal_compare (a, b) < 0)
368 sreal *swap;
369 swap = a;
370 a = b;
371 b = swap;
374 dexp = a->exp - b->exp;
375 r->exp = a->exp;
376 if (dexp > SREAL_BITS)
378 #if SREAL_PART_BITS < 32
379 r->sig_hi = a->sig_hi;
380 r->sig_lo = a->sig_lo;
381 #else
382 r->sig = a->sig;
383 #endif
384 return r;
387 if (dexp == 0)
388 bb = b;
389 else
391 copy (&tmp, b);
392 shift_right (&tmp, dexp);
393 bb = &tmp;
396 #if SREAL_PART_BITS < 32
397 r->sig_hi = a->sig_hi + bb->sig_hi;
398 r->sig_lo = a->sig_lo + bb->sig_lo;
399 if (r->sig_lo & ((uhwi) 1 << SREAL_PART_BITS))
401 r->sig_hi++;
402 r->sig_lo -= (uhwi) 1 << SREAL_PART_BITS;
404 #else
405 r->sig = a->sig + bb->sig;
406 #endif
407 normalize (r);
408 return r;
411 /* *R = *A - *B. Return R. */
413 sreal *
414 sreal_sub (r, a, b)
415 sreal *r;
416 sreal *a;
417 sreal *b;
419 int dexp;
420 sreal tmp;
421 sreal *bb;
423 if (sreal_compare (a, b) < 0)
425 abort ();
428 dexp = a->exp - b->exp;
429 r->exp = a->exp;
430 if (dexp > SREAL_BITS)
432 #if SREAL_PART_BITS < 32
433 r->sig_hi = a->sig_hi;
434 r->sig_lo = a->sig_lo;
435 #else
436 r->sig = a->sig;
437 #endif
438 return r;
440 if (dexp == 0)
441 bb = b;
442 else
444 copy (&tmp, b);
445 shift_right (&tmp, dexp);
446 bb = &tmp;
449 #if SREAL_PART_BITS < 32
450 if (a->sig_lo < bb->sig_lo)
452 r->sig_hi = a->sig_hi - bb->sig_hi - 1;
453 r->sig_lo = a->sig_lo + ((uhwi) 1 << SREAL_PART_BITS) - bb->sig_lo;
455 else
457 r->sig_hi = a->sig_hi - bb->sig_hi;
458 r->sig_lo = a->sig_lo - bb->sig_lo;
460 #else
461 r->sig = a->sig - bb->sig;
462 #endif
463 normalize (r);
464 return r;
467 /* *R = *A * *B. Return R. */
469 sreal *
470 sreal_mul (r, a, b)
471 sreal *r;
472 sreal *a;
473 sreal *b;
475 #if SREAL_PART_BITS < 32
476 if (a->sig_hi < SREAL_MIN_SIG || b->sig_hi < SREAL_MIN_SIG)
478 r->sig_lo = 0;
479 r->sig_hi = 0;
480 r->exp = -SREAL_MAX_EXP;
482 else
484 unsigned HOST_WIDE_INT tmp1, tmp2, tmp3;
485 if (sreal_compare (a, b) < 0)
487 sreal *swap;
488 swap = a;
489 a = b;
490 b = swap;
493 r->exp = a->exp + b->exp + SREAL_PART_BITS;
495 tmp1 = a->sig_lo * b->sig_lo;
496 tmp2 = a->sig_lo * b->sig_hi;
497 tmp3 = a->sig_hi * b->sig_lo + (tmp1 >> SREAL_PART_BITS);
499 r->sig_hi = a->sig_hi * b->sig_hi;
500 r->sig_hi += (tmp2 >> SREAL_PART_BITS) + (tmp3 >> SREAL_PART_BITS);
501 tmp2 &= ((uhwi) 1 << SREAL_PART_BITS) - 1;
502 tmp3 &= ((uhwi) 1 << SREAL_PART_BITS) - 1;
503 tmp1 = tmp2 + tmp3;
505 r->sig_lo = tmp1 & (((uhwi) 1 << SREAL_PART_BITS) - 1);
506 r->sig_hi += tmp1 >> SREAL_PART_BITS;
508 normalize (r);
510 #else
511 if (a->sig < SREAL_MIN_SIG || b->sig < SREAL_MIN_SIG)
513 r->sig = 0;
514 r->exp = -SREAL_MAX_EXP;
516 else
518 r->sig = a->sig * b->sig;
519 r->exp = a->exp + b->exp;
520 normalize (r);
522 #endif
523 return r;
526 /* *R = *A / *B. Return R. */
528 sreal *
529 sreal_div (r, a, b)
530 sreal *r;
531 sreal *a;
532 sreal *b;
534 #if SREAL_PART_BITS < 32
535 unsigned HOST_WIDE_INT tmp, tmp1, tmp2;
537 if (b->sig_hi < SREAL_MIN_SIG)
539 abort ();
541 else if (a->sig_hi < SREAL_MIN_SIG)
543 r->sig_hi = 0;
544 r->sig_lo = 0;
545 r->exp = -SREAL_MAX_EXP;
547 else
549 /* Since division by the whole number is pretty ugly to write
550 we are dividing by first 3/4 of bits of number. */
552 tmp1 = (a->sig_hi << SREAL_PART_BITS) + a->sig_lo;
553 tmp2 = ((b->sig_hi << (SREAL_PART_BITS / 2))
554 + (b->sig_lo >> (SREAL_PART_BITS / 2)));
555 if (b->sig_lo & ((uhwi) 1 << ((SREAL_PART_BITS / 2) - 1)))
556 tmp2++;
558 r->sig_lo = 0;
559 tmp = tmp1 / tmp2;
560 tmp1 = (tmp1 % tmp2) << (SREAL_PART_BITS / 2);
561 r->sig_hi = tmp << SREAL_PART_BITS;
563 tmp = tmp1 / tmp2;
564 tmp1 = (tmp1 % tmp2) << (SREAL_PART_BITS / 2);
565 r->sig_hi += tmp << (SREAL_PART_BITS / 2);
567 tmp = tmp1 / tmp2;
568 r->sig_hi += tmp;
570 r->exp = a->exp - b->exp - SREAL_BITS - SREAL_PART_BITS / 2;
571 normalize (r);
573 #else
574 if (b->sig == 0)
576 abort ();
578 else
580 r->sig = (a->sig << SREAL_PART_BITS) / b->sig;
581 r->exp = a->exp - b->exp - SREAL_PART_BITS;
582 normalize (r);
584 #endif
585 return r;