1 /* Simple data type for positive real numbers for the GNU compiler.
2 Copyright (C) 2002, 2003, 2004, 2007 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 3, 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 COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
20 /* This library supports positive real numbers and 0;
21 inf and nan are NOT supported.
22 It is written to be simple and fast.
28 (for < 64-bit machines sig = sig_lo + sig_hi * 2 ^ SREAL_PART_BITS)
31 One HOST_WIDE_INT is used for the significant on 64-bit (and more than
33 otherwise two HOST_WIDE_INTs are used for the significant.
34 Only a half of significant bits is used (in normalized sreals) so that we do
35 not have problems with overflow, for example when c->sig = a->sig * b->sig.
36 So the precision for 64-bit and 32-bit machines is 32-bit.
38 Invariant: The numbers are normalized before and after each call of sreal_*.
41 All numbers (except zero) meet following conditions:
42 SREAL_MIN_SIG <= sig && sig <= SREAL_MAX_SIG
43 -SREAL_MAX_EXP <= exp && exp <= SREAL_MAX_EXP
45 If the number would be too large, it is set to upper bounds of these
48 If the number is zero or would be too small it meets following conditions:
49 sig == 0 && exp == -SREAL_MAX_EXP
54 #include "coretypes.h"
58 static inline void copy (sreal
*, sreal
*);
59 static inline void shift_right (sreal
*, int);
60 static void normalize (sreal
*);
62 /* Print the content of struct sreal. */
65 dump_sreal (FILE *file
, sreal
*x
)
67 #if SREAL_PART_BITS < 32
68 fprintf (file
, "((" HOST_WIDE_INT_PRINT_UNSIGNED
" * 2^16 + "
69 HOST_WIDE_INT_PRINT_UNSIGNED
") * 2^%d)",
70 x
->sig_hi
, x
->sig_lo
, x
->exp
);
72 fprintf (file
, "(" HOST_WIDE_INT_PRINT_UNSIGNED
" * 2^%d)", x
->sig
, x
->exp
);
76 /* Copy the sreal number. */
79 copy (sreal
*r
, sreal
*a
)
81 #if SREAL_PART_BITS < 32
82 r
->sig_lo
= a
->sig_lo
;
83 r
->sig_hi
= a
->sig_hi
;
90 /* Shift X right by S bits. Needed: 0 < S <= SREAL_BITS.
91 When the most significant bit shifted out is 1, add 1 to X (rounding). */
94 shift_right (sreal
*x
, int s
)
97 gcc_assert (s
<= SREAL_BITS
);
98 /* Exponent should never be so large because shift_right is used only by
99 sreal_add and sreal_sub ant thus the number cannot be shifted out from
101 gcc_assert (x
->exp
+ s
<= SREAL_MAX_EXP
);
105 #if SREAL_PART_BITS < 32
106 if (s
> SREAL_PART_BITS
)
108 s
-= SREAL_PART_BITS
;
109 x
->sig_hi
+= (uhwi
) 1 << (s
- 1);
110 x
->sig_lo
= x
->sig_hi
>> s
;
115 x
->sig_lo
+= (uhwi
) 1 << (s
- 1);
116 if (x
->sig_lo
& ((uhwi
) 1 << SREAL_PART_BITS
))
119 x
->sig_lo
-= (uhwi
) 1 << SREAL_PART_BITS
;
122 x
->sig_lo
|= (x
->sig_hi
& (((uhwi
) 1 << s
) - 1)) << (SREAL_PART_BITS
- s
);
126 x
->sig
+= (uhwi
) 1 << (s
- 1);
136 #if SREAL_PART_BITS < 32
140 if (x
->sig_lo
== 0 && x
->sig_hi
== 0)
142 x
->exp
= -SREAL_MAX_EXP
;
144 else if (x
->sig_hi
< SREAL_MIN_SIG
)
148 /* Move lower part of significant to higher part. */
149 x
->sig_hi
= x
->sig_lo
;
151 x
->exp
-= SREAL_PART_BITS
;
154 while (x
->sig_hi
< SREAL_MIN_SIG
)
160 /* Check underflow. */
161 if (x
->exp
< -SREAL_MAX_EXP
)
163 x
->exp
= -SREAL_MAX_EXP
;
169 mask
= (1 << SREAL_PART_BITS
) - (1 << (SREAL_PART_BITS
- shift
));
170 x
->sig_hi
|= (x
->sig_lo
& mask
) >> (SREAL_PART_BITS
- shift
);
171 x
->sig_lo
= (x
->sig_lo
<< shift
) & (((uhwi
) 1 << SREAL_PART_BITS
) - 1);
174 else if (x
->sig_hi
> SREAL_MAX_SIG
)
176 unsigned HOST_WIDE_INT tmp
= x
->sig_hi
;
178 /* Find out how many bits will be shifted. */
185 while (tmp
> SREAL_MAX_SIG
);
187 /* Round the number. */
188 x
->sig_lo
+= (uhwi
) 1 << (shift
- 1);
191 x
->sig_lo
+= ((x
->sig_hi
& (((uhwi
) 1 << shift
) - 1))
192 << (SREAL_PART_BITS
- shift
));
195 if (x
->sig_lo
& ((uhwi
) 1 << SREAL_PART_BITS
))
197 x
->sig_lo
-= (uhwi
) 1 << SREAL_PART_BITS
;
199 if (x
->sig_hi
> SREAL_MAX_SIG
)
201 /* x->sig_hi was SREAL_MAX_SIG before increment
202 so now last bit is zero. */
209 /* Check overflow. */
210 if (x
->exp
> SREAL_MAX_EXP
)
212 x
->exp
= SREAL_MAX_EXP
;
213 x
->sig_hi
= SREAL_MAX_SIG
;
214 x
->sig_lo
= SREAL_MAX_SIG
;
220 x
->exp
= -SREAL_MAX_EXP
;
222 else if (x
->sig
< SREAL_MIN_SIG
)
229 while (x
->sig
< SREAL_MIN_SIG
);
231 /* Check underflow. */
232 if (x
->exp
< -SREAL_MAX_EXP
)
234 x
->exp
= -SREAL_MAX_EXP
;
238 else if (x
->sig
> SREAL_MAX_SIG
)
243 last_bit
= x
->sig
& 1;
247 while (x
->sig
> SREAL_MAX_SIG
);
249 /* Round the number. */
251 if (x
->sig
> SREAL_MAX_SIG
)
257 /* Check overflow. */
258 if (x
->exp
> SREAL_MAX_EXP
)
260 x
->exp
= SREAL_MAX_EXP
;
261 x
->sig
= SREAL_MAX_SIG
;
267 /* Set *R to SIG * 2 ^ EXP. Return R. */
270 sreal_init (sreal
*r
, unsigned HOST_WIDE_INT sig
, signed int exp
)
272 #if SREAL_PART_BITS < 32
284 /* Return integer value of *R. */
287 sreal_to_int (sreal
*r
)
289 #if SREAL_PART_BITS < 32
290 if (r
->exp
<= -SREAL_BITS
)
293 return MAX_HOST_WIDE_INT
;
294 return ((r
->sig_hi
<< SREAL_PART_BITS
) + r
->sig_lo
) >> -r
->exp
;
296 if (r
->exp
<= -SREAL_BITS
)
298 if (r
->exp
>= SREAL_PART_BITS
)
299 return MAX_HOST_WIDE_INT
;
301 return r
->sig
<< r
->exp
;
303 return r
->sig
>> -r
->exp
;
308 /* Compare *A and *B. Return -1 if *A < *B, 1 if *A > *B and 0 if *A == *B. */
311 sreal_compare (sreal
*a
, sreal
*b
)
317 #if SREAL_PART_BITS < 32
318 if (a
->sig_hi
> b
->sig_hi
)
320 if (a
->sig_hi
< b
->sig_hi
)
322 if (a
->sig_lo
> b
->sig_lo
)
324 if (a
->sig_lo
< b
->sig_lo
)
335 /* *R = *A + *B. Return R. */
338 sreal_add (sreal
*r
, sreal
*a
, sreal
*b
)
344 if (sreal_compare (a
, b
) < 0)
352 dexp
= a
->exp
- b
->exp
;
354 if (dexp
> SREAL_BITS
)
356 #if SREAL_PART_BITS < 32
357 r
->sig_hi
= a
->sig_hi
;
358 r
->sig_lo
= a
->sig_lo
;
370 shift_right (&tmp
, dexp
);
374 #if SREAL_PART_BITS < 32
375 r
->sig_hi
= a
->sig_hi
+ bb
->sig_hi
;
376 r
->sig_lo
= a
->sig_lo
+ bb
->sig_lo
;
377 if (r
->sig_lo
& ((uhwi
) 1 << SREAL_PART_BITS
))
380 r
->sig_lo
-= (uhwi
) 1 << SREAL_PART_BITS
;
383 r
->sig
= a
->sig
+ bb
->sig
;
389 /* *R = *A - *B. Return R. */
392 sreal_sub (sreal
*r
, sreal
*a
, sreal
*b
)
398 gcc_assert (sreal_compare (a
, b
) >= 0);
400 dexp
= a
->exp
- b
->exp
;
402 if (dexp
> SREAL_BITS
)
404 #if SREAL_PART_BITS < 32
405 r
->sig_hi
= a
->sig_hi
;
406 r
->sig_lo
= a
->sig_lo
;
417 shift_right (&tmp
, dexp
);
421 #if SREAL_PART_BITS < 32
422 if (a
->sig_lo
< bb
->sig_lo
)
424 r
->sig_hi
= a
->sig_hi
- bb
->sig_hi
- 1;
425 r
->sig_lo
= a
->sig_lo
+ ((uhwi
) 1 << SREAL_PART_BITS
) - bb
->sig_lo
;
429 r
->sig_hi
= a
->sig_hi
- bb
->sig_hi
;
430 r
->sig_lo
= a
->sig_lo
- bb
->sig_lo
;
433 r
->sig
= a
->sig
- bb
->sig
;
439 /* *R = *A * *B. Return R. */
442 sreal_mul (sreal
*r
, sreal
*a
, sreal
*b
)
444 #if SREAL_PART_BITS < 32
445 if (a
->sig_hi
< SREAL_MIN_SIG
|| b
->sig_hi
< SREAL_MIN_SIG
)
449 r
->exp
= -SREAL_MAX_EXP
;
453 unsigned HOST_WIDE_INT tmp1
, tmp2
, tmp3
;
454 if (sreal_compare (a
, b
) < 0)
462 r
->exp
= a
->exp
+ b
->exp
+ SREAL_PART_BITS
;
464 tmp1
= a
->sig_lo
* b
->sig_lo
;
465 tmp2
= a
->sig_lo
* b
->sig_hi
;
466 tmp3
= a
->sig_hi
* b
->sig_lo
+ (tmp1
>> SREAL_PART_BITS
);
468 r
->sig_hi
= a
->sig_hi
* b
->sig_hi
;
469 r
->sig_hi
+= (tmp2
>> SREAL_PART_BITS
) + (tmp3
>> SREAL_PART_BITS
);
470 tmp2
&= ((uhwi
) 1 << SREAL_PART_BITS
) - 1;
471 tmp3
&= ((uhwi
) 1 << SREAL_PART_BITS
) - 1;
474 r
->sig_lo
= tmp1
& (((uhwi
) 1 << SREAL_PART_BITS
) - 1);
475 r
->sig_hi
+= tmp1
>> SREAL_PART_BITS
;
480 if (a
->sig
< SREAL_MIN_SIG
|| b
->sig
< SREAL_MIN_SIG
)
483 r
->exp
= -SREAL_MAX_EXP
;
487 r
->sig
= a
->sig
* b
->sig
;
488 r
->exp
= a
->exp
+ b
->exp
;
495 /* *R = *A / *B. Return R. */
498 sreal_div (sreal
*r
, sreal
*a
, sreal
*b
)
500 #if SREAL_PART_BITS < 32
501 unsigned HOST_WIDE_INT tmp
, tmp1
, tmp2
;
503 gcc_assert (b
->sig_hi
>= SREAL_MIN_SIG
);
504 if (a
->sig_hi
< SREAL_MIN_SIG
)
508 r
->exp
= -SREAL_MAX_EXP
;
512 /* Since division by the whole number is pretty ugly to write
513 we are dividing by first 3/4 of bits of number. */
515 tmp1
= (a
->sig_hi
<< SREAL_PART_BITS
) + a
->sig_lo
;
516 tmp2
= ((b
->sig_hi
<< (SREAL_PART_BITS
/ 2))
517 + (b
->sig_lo
>> (SREAL_PART_BITS
/ 2)));
518 if (b
->sig_lo
& ((uhwi
) 1 << ((SREAL_PART_BITS
/ 2) - 1)))
523 tmp1
= (tmp1
% tmp2
) << (SREAL_PART_BITS
/ 2);
524 r
->sig_hi
= tmp
<< SREAL_PART_BITS
;
527 tmp1
= (tmp1
% tmp2
) << (SREAL_PART_BITS
/ 2);
528 r
->sig_hi
+= tmp
<< (SREAL_PART_BITS
/ 2);
533 r
->exp
= a
->exp
- b
->exp
- SREAL_BITS
- SREAL_PART_BITS
/ 2;
537 gcc_assert (b
->sig
!= 0);
538 r
->sig
= (a
->sig
<< SREAL_PART_BITS
) / b
->sig
;
539 r
->exp
= a
->exp
- b
->exp
- SREAL_PART_BITS
;