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
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
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
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.
29 (for < 64-bit machines sig = sig_lo + sig_hi * 2 ^ SREAL_PART_BITS)
32 One HOST_WIDE_INT is used for the significant on 64-bit (and more than
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 precision for 64-bit and 32-bit machines is 32-bit.
39 Invariant: The numbers are normalized before and after each call of sreal_*.
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
49 If the number is zero or would be too small it meets following conditions:
50 sig == 0 && exp == -SREAL_MAX_EXP
55 #include "coretypes.h"
59 static inline void copy (sreal
*, sreal
*);
60 static inline void shift_right (sreal
*, int);
61 static void normalize (sreal
*);
63 /* Print the content of struct sreal. */
66 dump_sreal (FILE *file
, sreal
*x
)
68 #if SREAL_PART_BITS < 32
69 fprintf (file
, "((" HOST_WIDE_INT_PRINT_UNSIGNED
" * 2^16 + "
70 HOST_WIDE_INT_PRINT_UNSIGNED
") * 2^%d)",
71 x
->sig_hi
, x
->sig_lo
, x
->exp
);
73 fprintf (file
, "(" HOST_WIDE_INT_PRINT_UNSIGNED
" * 2^%d)", x
->sig
, x
->exp
);
77 /* Copy the sreal number. */
80 copy (sreal
*r
, sreal
*a
)
82 #if SREAL_PART_BITS < 32
83 r
->sig_lo
= a
->sig_lo
;
84 r
->sig_hi
= a
->sig_hi
;
91 /* Shift X right by S bits. Needed: 0 < S <= SREAL_BITS.
92 When the most significant bit shifted out is 1, add 1 to X (rounding). */
95 shift_right (sreal
*x
, int s
)
97 #ifdef ENABLE_CHECKING
98 if (s
<= 0 || s
> SREAL_BITS
)
100 if (x
->exp
+ s
> SREAL_MAX_EXP
)
102 /* Exponent should never be so large because shift_right is used only by
103 sreal_add and sreal_sub ant thus the number cannot be shifted out from
111 #if SREAL_PART_BITS < 32
112 if (s
> SREAL_PART_BITS
)
114 s
-= SREAL_PART_BITS
;
115 x
->sig_hi
+= (uhwi
) 1 << (s
- 1);
116 x
->sig_lo
= x
->sig_hi
>> s
;
121 x
->sig_lo
+= (uhwi
) 1 << (s
- 1);
122 if (x
->sig_lo
& ((uhwi
) 1 << SREAL_PART_BITS
))
125 x
->sig_lo
-= (uhwi
) 1 << SREAL_PART_BITS
;
128 x
->sig_lo
|= (x
->sig_hi
& (((uhwi
) 1 << s
) - 1)) << (SREAL_PART_BITS
- s
);
132 x
->sig
+= (uhwi
) 1 << (s
- 1);
142 #if SREAL_PART_BITS < 32
146 if (x
->sig_lo
== 0 && x
->sig_hi
== 0)
148 x
->exp
= -SREAL_MAX_EXP
;
150 else if (x
->sig_hi
< SREAL_MIN_SIG
)
154 /* Move lower part of significant to higher part. */
155 x
->sig_hi
= x
->sig_lo
;
157 x
->exp
-= SREAL_PART_BITS
;
160 while (x
->sig_hi
< SREAL_MIN_SIG
)
166 /* Check underflow. */
167 if (x
->exp
< -SREAL_MAX_EXP
)
169 x
->exp
= -SREAL_MAX_EXP
;
175 mask
= (1 << SREAL_PART_BITS
) - (1 << (SREAL_PART_BITS
- shift
));
176 x
->sig_hi
|= (x
->sig_lo
& mask
) >> (SREAL_PART_BITS
- shift
);
177 x
->sig_lo
= (x
->sig_lo
<< shift
) & (((uhwi
) 1 << SREAL_PART_BITS
) - 1);
180 else if (x
->sig_hi
> SREAL_MAX_SIG
)
182 unsigned HOST_WIDE_INT tmp
= x
->sig_hi
;
184 /* Find out how many bits will be shifted. */
191 while (tmp
> SREAL_MAX_SIG
);
193 /* Round the number. */
194 x
->sig_lo
+= (uhwi
) 1 << (shift
- 1);
197 x
->sig_lo
+= ((x
->sig_hi
& (((uhwi
) 1 << shift
) - 1))
198 << (SREAL_PART_BITS
- shift
));
201 if (x
->sig_lo
& ((uhwi
) 1 << SREAL_PART_BITS
))
203 x
->sig_lo
-= (uhwi
) 1 << SREAL_PART_BITS
;
205 if (x
->sig_hi
> SREAL_MAX_SIG
)
207 /* x->sig_hi was SREAL_MAX_SIG before increment
208 so now last bit is zero. */
215 /* Check overflow. */
216 if (x
->exp
> SREAL_MAX_EXP
)
218 x
->exp
= SREAL_MAX_EXP
;
219 x
->sig_hi
= SREAL_MAX_SIG
;
220 x
->sig_lo
= SREAL_MAX_SIG
;
226 x
->exp
= -SREAL_MAX_EXP
;
228 else if (x
->sig
< SREAL_MIN_SIG
)
235 while (x
->sig
< SREAL_MIN_SIG
);
237 /* Check underflow. */
238 if (x
->exp
< -SREAL_MAX_EXP
)
240 x
->exp
= -SREAL_MAX_EXP
;
244 else if (x
->sig
> SREAL_MAX_SIG
)
249 last_bit
= x
->sig
& 1;
253 while (x
->sig
> SREAL_MAX_SIG
);
255 /* Round the number. */
257 if (x
->sig
> SREAL_MAX_SIG
)
263 /* Check overflow. */
264 if (x
->exp
> SREAL_MAX_EXP
)
266 x
->exp
= SREAL_MAX_EXP
;
267 x
->sig
= SREAL_MAX_SIG
;
273 /* Set *R to SIG * 2 ^ EXP. Return R. */
276 sreal_init (sreal
*r
, unsigned HOST_WIDE_INT sig
, signed int exp
)
278 #if SREAL_PART_BITS < 32
290 /* Return integer value of *R. */
293 sreal_to_int (sreal
*r
)
295 #if SREAL_PART_BITS < 32
296 if (r
->exp
<= -SREAL_BITS
)
299 return MAX_HOST_WIDE_INT
;
300 return ((r
->sig_hi
<< SREAL_PART_BITS
) + r
->sig_lo
) >> -r
->exp
;
302 if (r
->exp
<= -SREAL_BITS
)
304 if (r
->exp
>= SREAL_PART_BITS
)
305 return MAX_HOST_WIDE_INT
;
307 return r
->sig
<< r
->exp
;
309 return r
->sig
>> -r
->exp
;
314 /* Compare *A and *B. Return -1 if *A < *B, 1 if *A > *B and 0 if *A == *B. */
317 sreal_compare (sreal
*a
, sreal
*b
)
323 #if SREAL_PART_BITS < 32
324 if (a
->sig_hi
> b
->sig_hi
)
326 if (a
->sig_hi
< b
->sig_hi
)
328 if (a
->sig_lo
> b
->sig_lo
)
330 if (a
->sig_lo
< b
->sig_lo
)
341 /* *R = *A + *B. Return R. */
344 sreal_add (sreal
*r
, sreal
*a
, sreal
*b
)
350 if (sreal_compare (a
, b
) < 0)
358 dexp
= a
->exp
- b
->exp
;
360 if (dexp
> SREAL_BITS
)
362 #if SREAL_PART_BITS < 32
363 r
->sig_hi
= a
->sig_hi
;
364 r
->sig_lo
= a
->sig_lo
;
376 shift_right (&tmp
, dexp
);
380 #if SREAL_PART_BITS < 32
381 r
->sig_hi
= a
->sig_hi
+ bb
->sig_hi
;
382 r
->sig_lo
= a
->sig_lo
+ bb
->sig_lo
;
383 if (r
->sig_lo
& ((uhwi
) 1 << SREAL_PART_BITS
))
386 r
->sig_lo
-= (uhwi
) 1 << SREAL_PART_BITS
;
389 r
->sig
= a
->sig
+ bb
->sig
;
395 /* *R = *A - *B. Return R. */
398 sreal_sub (sreal
*r
, sreal
*a
, sreal
*b
)
404 if (sreal_compare (a
, b
) < 0)
409 dexp
= a
->exp
- b
->exp
;
411 if (dexp
> SREAL_BITS
)
413 #if SREAL_PART_BITS < 32
414 r
->sig_hi
= a
->sig_hi
;
415 r
->sig_lo
= a
->sig_lo
;
426 shift_right (&tmp
, dexp
);
430 #if SREAL_PART_BITS < 32
431 if (a
->sig_lo
< bb
->sig_lo
)
433 r
->sig_hi
= a
->sig_hi
- bb
->sig_hi
- 1;
434 r
->sig_lo
= a
->sig_lo
+ ((uhwi
) 1 << SREAL_PART_BITS
) - bb
->sig_lo
;
438 r
->sig_hi
= a
->sig_hi
- bb
->sig_hi
;
439 r
->sig_lo
= a
->sig_lo
- bb
->sig_lo
;
442 r
->sig
= a
->sig
- bb
->sig
;
448 /* *R = *A * *B. Return R. */
451 sreal_mul (sreal
*r
, sreal
*a
, sreal
*b
)
453 #if SREAL_PART_BITS < 32
454 if (a
->sig_hi
< SREAL_MIN_SIG
|| b
->sig_hi
< SREAL_MIN_SIG
)
458 r
->exp
= -SREAL_MAX_EXP
;
462 unsigned HOST_WIDE_INT tmp1
, tmp2
, tmp3
;
463 if (sreal_compare (a
, b
) < 0)
471 r
->exp
= a
->exp
+ b
->exp
+ SREAL_PART_BITS
;
473 tmp1
= a
->sig_lo
* b
->sig_lo
;
474 tmp2
= a
->sig_lo
* b
->sig_hi
;
475 tmp3
= a
->sig_hi
* b
->sig_lo
+ (tmp1
>> SREAL_PART_BITS
);
477 r
->sig_hi
= a
->sig_hi
* b
->sig_hi
;
478 r
->sig_hi
+= (tmp2
>> SREAL_PART_BITS
) + (tmp3
>> SREAL_PART_BITS
);
479 tmp2
&= ((uhwi
) 1 << SREAL_PART_BITS
) - 1;
480 tmp3
&= ((uhwi
) 1 << SREAL_PART_BITS
) - 1;
483 r
->sig_lo
= tmp1
& (((uhwi
) 1 << SREAL_PART_BITS
) - 1);
484 r
->sig_hi
+= tmp1
>> SREAL_PART_BITS
;
489 if (a
->sig
< SREAL_MIN_SIG
|| b
->sig
< SREAL_MIN_SIG
)
492 r
->exp
= -SREAL_MAX_EXP
;
496 r
->sig
= a
->sig
* b
->sig
;
497 r
->exp
= a
->exp
+ b
->exp
;
504 /* *R = *A / *B. Return R. */
507 sreal_div (sreal
*r
, sreal
*a
, sreal
*b
)
509 #if SREAL_PART_BITS < 32
510 unsigned HOST_WIDE_INT tmp
, tmp1
, tmp2
;
512 if (b
->sig_hi
< SREAL_MIN_SIG
)
516 else if (a
->sig_hi
< SREAL_MIN_SIG
)
520 r
->exp
= -SREAL_MAX_EXP
;
524 /* Since division by the whole number is pretty ugly to write
525 we are dividing by first 3/4 of bits of number. */
527 tmp1
= (a
->sig_hi
<< SREAL_PART_BITS
) + a
->sig_lo
;
528 tmp2
= ((b
->sig_hi
<< (SREAL_PART_BITS
/ 2))
529 + (b
->sig_lo
>> (SREAL_PART_BITS
/ 2)));
530 if (b
->sig_lo
& ((uhwi
) 1 << ((SREAL_PART_BITS
/ 2) - 1)))
535 tmp1
= (tmp1
% tmp2
) << (SREAL_PART_BITS
/ 2);
536 r
->sig_hi
= tmp
<< SREAL_PART_BITS
;
539 tmp1
= (tmp1
% tmp2
) << (SREAL_PART_BITS
/ 2);
540 r
->sig_hi
+= tmp
<< (SREAL_PART_BITS
/ 2);
545 r
->exp
= a
->exp
- b
->exp
- SREAL_BITS
- SREAL_PART_BITS
/ 2;
555 r
->sig
= (a
->sig
<< SREAL_PART_BITS
) / b
->sig
;
556 r
->exp
= a
->exp
- b
->exp
- SREAL_PART_BITS
;