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 precission 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 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. */
71 #if SREAL_PART_BITS < 32
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
);
79 fprintf (file
, HOST_WIDE_INT_PRINT_UNSIGNED
, x
->sig
);
80 fprintf (file
, " * 2^%d)", x
->exp
);
84 /* Copy the sreal number. */
91 #if SREAL_PART_BITS < 32
92 r
->sig_lo
= a
->sig_lo
;
93 r
->sig_hi
= a
->sig_hi
;
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). */
108 #ifdef ENABLE_CHECKING
109 if (s
<= 0 || s
> SREAL_BITS
)
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
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
;
132 x
->sig_lo
+= (uhwi
) 1 << (s
- 1);
133 if (x
->sig_lo
& ((uhwi
) 1 << SREAL_PART_BITS
))
136 x
->sig_lo
-= (uhwi
) 1 << SREAL_PART_BITS
;
139 x
->sig_lo
|= (x
->sig_hi
& (((uhwi
) 1 << s
) - 1)) << (SREAL_PART_BITS
- s
);
143 x
->sig
+= (uhwi
) 1 << (s
- 1);
154 #if SREAL_PART_BITS < 32
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
)
166 /* Move lower part of significant to higher part. */
167 x
->sig_hi
= x
->sig_lo
;
169 x
->exp
-= SREAL_PART_BITS
;
172 while (x
->sig_hi
< SREAL_MIN_SIG
)
178 /* Check underflow. */
179 if (x
->exp
< -SREAL_MAX_EXP
)
181 x
->exp
= -SREAL_MAX_EXP
;
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. */
203 while (tmp
> SREAL_MAX_SIG
);
205 /* Round the number. */
206 x
->sig_lo
+= (uhwi
) 1 << (shift
- 1);
209 x
->sig_lo
+= ((x
->sig_hi
& (((uhwi
) 1 << shift
) - 1))
210 << (SREAL_PART_BITS
- shift
));
213 if (x
->sig_lo
& ((uhwi
) 1 << SREAL_PART_BITS
))
215 x
->sig_lo
-= (uhwi
) 1 << SREAL_PART_BITS
;
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. */
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
;
238 x
->exp
= -SREAL_MAX_EXP
;
240 else if (x
->sig
< SREAL_MIN_SIG
)
247 while (x
->sig
< SREAL_MIN_SIG
);
249 /* Check underflow. */
250 if (x
->exp
< -SREAL_MAX_EXP
)
252 x
->exp
= -SREAL_MAX_EXP
;
256 else if (x
->sig
> SREAL_MAX_SIG
)
261 last_bit
= x
->sig
& 1;
265 while (x
->sig
> SREAL_MAX_SIG
);
267 /* Round the number. */
269 if (x
->sig
> SREAL_MAX_SIG
)
275 /* Check overflow. */
276 if (x
->exp
> SREAL_MAX_EXP
)
278 x
->exp
= SREAL_MAX_EXP
;
279 x
->sig
= SREAL_MAX_SIG
;
285 /* Set *R to SIG * 2 ^ EXP. Return R. */
288 sreal_init (r
, sig
, exp
)
290 unsigned HOST_WIDE_INT sig
;
293 #if SREAL_PART_BITS < 32
305 /* Return integer value of *R. */
311 #if SREAL_PART_BITS < 32
312 if (r
->exp
<= -SREAL_BITS
)
315 return MAX_HOST_WIDE_INT
;
316 return ((r
->sig_hi
<< SREAL_PART_BITS
) + r
->sig_lo
) >> -r
->exp
;
318 if (r
->exp
<= -SREAL_BITS
)
320 if (r
->exp
>= SREAL_PART_BITS
)
321 return MAX_HOST_WIDE_INT
;
323 return r
->sig
<< r
->exp
;
325 return r
->sig
>> -r
->exp
;
330 /* Compare *A and *B. Return -1 if *A < *B, 1 if *A > *B and 0 if *A == *B. */
341 #if SREAL_PART_BITS < 32
342 if (a
->sig_hi
> b
->sig_hi
)
344 if (a
->sig_hi
< b
->sig_hi
)
346 if (a
->sig_lo
> b
->sig_lo
)
348 if (a
->sig_lo
< b
->sig_lo
)
359 /* *R = *A + *B. Return R. */
371 if (sreal_compare (a
, b
) < 0)
379 dexp
= a
->exp
- b
->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
;
397 shift_right (&tmp
, dexp
);
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
))
407 r
->sig_lo
-= (uhwi
) 1 << SREAL_PART_BITS
;
410 r
->sig
= a
->sig
+ bb
->sig
;
416 /* *R = *A - *B. Return R. */
428 if (sreal_compare (a
, b
) < 0)
433 dexp
= a
->exp
- b
->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
;
450 shift_right (&tmp
, dexp
);
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
;
462 r
->sig_hi
= a
->sig_hi
- bb
->sig_hi
;
463 r
->sig_lo
= a
->sig_lo
- bb
->sig_lo
;
466 r
->sig
= a
->sig
- bb
->sig
;
472 /* *R = *A * *B. Return R. */
480 #if SREAL_PART_BITS < 32
481 if (a
->sig_hi
< SREAL_MIN_SIG
|| b
->sig_hi
< SREAL_MIN_SIG
)
485 r
->exp
= -SREAL_MAX_EXP
;
489 unsigned HOST_WIDE_INT tmp1
, tmp2
, tmp3
;
490 if (sreal_compare (a
, b
) < 0)
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;
510 r
->sig_lo
= tmp1
& (((uhwi
) 1 << SREAL_PART_BITS
) - 1);
511 r
->sig_hi
+= tmp1
>> SREAL_PART_BITS
;
516 if (a
->sig
< SREAL_MIN_SIG
|| b
->sig
< SREAL_MIN_SIG
)
519 r
->exp
= -SREAL_MAX_EXP
;
523 r
->sig
= a
->sig
* b
->sig
;
524 r
->exp
= a
->exp
+ b
->exp
;
531 /* *R = *A / *B. Return R. */
539 #if SREAL_PART_BITS < 32
540 unsigned HOST_WIDE_INT tmp
, tmp1
, tmp2
;
542 if (b
->sig_hi
< SREAL_MIN_SIG
)
546 else if (a
->sig_hi
< SREAL_MIN_SIG
)
550 r
->exp
= -SREAL_MAX_EXP
;
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)))
565 tmp1
= (tmp1
% tmp2
) << (SREAL_PART_BITS
/ 2);
566 r
->sig_hi
= tmp
<< SREAL_PART_BITS
;
569 tmp1
= (tmp1
% tmp2
) << (SREAL_PART_BITS
/ 2);
570 r
->sig_hi
+= tmp
<< (SREAL_PART_BITS
/ 2);
575 r
->exp
= a
->exp
- b
->exp
- SREAL_BITS
- SREAL_PART_BITS
/ 2;
585 r
->sig
= (a
->sig
<< SREAL_PART_BITS
) / b
->sig
;
586 r
->exp
= a
->exp
- b
->exp
- SREAL_PART_BITS
;