]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/sreal.c
sbitmap.c: Convert prototypes to ISO C90.
[thirdparty/gcc.git] / gcc / sreal.c
CommitLineData
ac5e69da
JZ
1/* Simple data type for positive real numbers for the GNU compiler.
2 Copyright (C) 2002, 2003 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 2, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING. If not, write to the Free
18Software Foundation, 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
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.
24
25 Value of sreal is
26 x = sig * 2 ^ exp
46c5ad27 27 where
ac5e69da
JZ
28 sig = significant
29 (for < 64-bit machines sig = sig_lo + sig_hi * 2 ^ SREAL_PART_BITS)
30 exp = exponent
31
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.
e0bb17a8 37 So the precision for 64-bit and 32-bit machines is 32-bit.
46c5ad27 38
ac5e69da
JZ
39 Invariant: The numbers are normalized before and after each call of sreal_*.
40
41 Normalized sreals:
42 All numbers (except zero) meet following conditions:
43 SREAL_MIN_SIG <= sig && sig <= SREAL_MAX_SIG
46c5ad27 44 -SREAL_MAX_EXP <= exp && exp <= SREAL_MAX_EXP
ac5e69da
JZ
45
46 If the number would be too large, it is set to upper bounds of these
47 conditions.
48
49 If the number is zero or would be too small it meets following conditions:
50 sig == 0 && exp == -SREAL_MAX_EXP
51*/
52
53#include "config.h"
54#include "system.h"
55#include "coretypes.h"
56#include "tm.h"
57#include "sreal.h"
58
46c5ad27
AJ
59static inline void copy (sreal *, sreal *);
60static inline void shift_right (sreal *, int);
61static void normalize (sreal *);
ac5e69da
JZ
62
63/* Print the content of struct sreal. */
64
65void
46c5ad27 66dump_sreal (FILE *file, sreal *x)
ac5e69da
JZ
67{
68#if SREAL_PART_BITS < 32
90ff44cf
KG
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);
ac5e69da 72#else
90ff44cf 73 fprintf (file, "(" HOST_WIDE_INT_PRINT_UNSIGNED " * 2^%d)", x->sig, x->exp);
ac5e69da
JZ
74#endif
75}
76
77/* Copy the sreal number. */
78
79static inline void
46c5ad27 80copy (sreal *r, sreal *a)
ac5e69da
JZ
81{
82#if SREAL_PART_BITS < 32
83 r->sig_lo = a->sig_lo;
84 r->sig_hi = a->sig_hi;
85#else
86 r->sig = a->sig;
87#endif
88 r->exp = a->exp;
89}
90
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). */
93
94static inline void
46c5ad27 95shift_right (sreal *x, int s)
ac5e69da
JZ
96{
97#ifdef ENABLE_CHECKING
98 if (s <= 0 || s > SREAL_BITS)
99 abort ();
100 if (x->exp + s > SREAL_MAX_EXP)
101 {
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
104 exponent range. */
105 abort ();
106 }
107#endif
108
109 x->exp += s;
110
111#if SREAL_PART_BITS < 32
112 if (s > SREAL_PART_BITS)
113 {
114 s -= SREAL_PART_BITS;
115 x->sig_hi += (uhwi) 1 << (s - 1);
116 x->sig_lo = x->sig_hi >> s;
117 x->sig_hi = 0;
118 }
119 else
120 {
121 x->sig_lo += (uhwi) 1 << (s - 1);
122 if (x->sig_lo & ((uhwi) 1 << SREAL_PART_BITS))
123 {
124 x->sig_hi++;
125 x->sig_lo -= (uhwi) 1 << SREAL_PART_BITS;
126 }
127 x->sig_lo >>= s;
128 x->sig_lo |= (x->sig_hi & (((uhwi) 1 << s) - 1)) << (SREAL_PART_BITS - s);
129 x->sig_hi >>= s;
130 }
131#else
132 x->sig += (uhwi) 1 << (s - 1);
133 x->sig >>= s;
134#endif
135}
136
137/* Normalize *X. */
138
139static void
46c5ad27 140normalize (sreal *x)
ac5e69da
JZ
141{
142#if SREAL_PART_BITS < 32
143 int shift;
144 HOST_WIDE_INT mask;
46c5ad27 145
ac5e69da
JZ
146 if (x->sig_lo == 0 && x->sig_hi == 0)
147 {
148 x->exp = -SREAL_MAX_EXP;
149 }
150 else if (x->sig_hi < SREAL_MIN_SIG)
151 {
152 if (x->sig_hi == 0)
153 {
154 /* Move lower part of significant to higher part. */
155 x->sig_hi = x->sig_lo;
156 x->sig_lo = 0;
157 x->exp -= SREAL_PART_BITS;
158 }
159 shift = 0;
160 while (x->sig_hi < SREAL_MIN_SIG)
161 {
162 x->sig_hi <<= 1;
163 x->exp--;
164 shift++;
165 }
166 /* Check underflow. */
167 if (x->exp < -SREAL_MAX_EXP)
168 {
169 x->exp = -SREAL_MAX_EXP;
170 x->sig_hi = 0;
171 x->sig_lo = 0;
172 }
173 else if (shift)
174 {
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);
178 }
179 }
180 else if (x->sig_hi > SREAL_MAX_SIG)
181 {
182 unsigned HOST_WIDE_INT tmp = x->sig_hi;
183
184 /* Find out how many bits will be shifted. */
185 shift = 0;
186 do
187 {
188 tmp >>= 1;
189 shift++;
190 }
191 while (tmp > SREAL_MAX_SIG);
192
193 /* Round the number. */
194 x->sig_lo += (uhwi) 1 << (shift - 1);
195
196 x->sig_lo >>= shift;
197 x->sig_lo += ((x->sig_hi & (((uhwi) 1 << shift) - 1))
198 << (SREAL_PART_BITS - shift));
199 x->sig_hi >>= shift;
200 x->exp += shift;
201 if (x->sig_lo & ((uhwi) 1 << SREAL_PART_BITS))
202 {
203 x->sig_lo -= (uhwi) 1 << SREAL_PART_BITS;
204 x->sig_hi++;
205 if (x->sig_hi > SREAL_MAX_SIG)
206 {
207 /* x->sig_hi was SREAL_MAX_SIG before increment
208 so now last bit is zero. */
209 x->sig_hi >>= 1;
210 x->sig_lo >>= 1;
211 x->exp++;
212 }
213 }
214
215 /* Check overflow. */
216 if (x->exp > SREAL_MAX_EXP)
217 {
218 x->exp = SREAL_MAX_EXP;
219 x->sig_hi = SREAL_MAX_SIG;
220 x->sig_lo = SREAL_MAX_SIG;
221 }
222 }
223#else
224 if (x->sig == 0)
225 {
226 x->exp = -SREAL_MAX_EXP;
227 }
228 else if (x->sig < SREAL_MIN_SIG)
229 {
230 do
231 {
232 x->sig <<= 1;
233 x->exp--;
234 }
235 while (x->sig < SREAL_MIN_SIG);
236
237 /* Check underflow. */
238 if (x->exp < -SREAL_MAX_EXP)
239 {
240 x->exp = -SREAL_MAX_EXP;
241 x->sig = 0;
242 }
243 }
244 else if (x->sig > SREAL_MAX_SIG)
245 {
246 int last_bit;
247 do
248 {
249 last_bit = x->sig & 1;
250 x->sig >>= 1;
251 x->exp++;
252 }
253 while (x->sig > SREAL_MAX_SIG);
254
255 /* Round the number. */
256 x->sig += last_bit;
257 if (x->sig > SREAL_MAX_SIG)
258 {
259 x->sig >>= 1;
260 x->exp++;
261 }
262
263 /* Check overflow. */
264 if (x->exp > SREAL_MAX_EXP)
265 {
266 x->exp = SREAL_MAX_EXP;
267 x->sig = SREAL_MAX_SIG;
268 }
269 }
270#endif
271}
272
273/* Set *R to SIG * 2 ^ EXP. Return R. */
274
275sreal *
46c5ad27 276sreal_init (sreal *r, unsigned HOST_WIDE_INT sig, signed int exp)
ac5e69da
JZ
277{
278#if SREAL_PART_BITS < 32
279 r->sig_lo = 0;
280 r->sig_hi = sig;
281 r->exp = exp - 16;
282#else
283 r->sig = sig;
284 r->exp = exp;
285#endif
286 normalize (r);
287 return r;
288}
289
290/* Return integer value of *R. */
291
292HOST_WIDE_INT
46c5ad27 293sreal_to_int (sreal *r)
ac5e69da
JZ
294{
295#if SREAL_PART_BITS < 32
296 if (r->exp <= -SREAL_BITS)
297 return 0;
298 if (r->exp >= 0)
299 return MAX_HOST_WIDE_INT;
300 return ((r->sig_hi << SREAL_PART_BITS) + r->sig_lo) >> -r->exp;
301#else
302 if (r->exp <= -SREAL_BITS)
303 return 0;
304 if (r->exp >= SREAL_PART_BITS)
305 return MAX_HOST_WIDE_INT;
306 if (r->exp > 0)
307 return r->sig << r->exp;
308 if (r->exp < 0)
309 return r->sig >> -r->exp;
310 return r->sig;
311#endif
312}
313
314/* Compare *A and *B. Return -1 if *A < *B, 1 if *A > *B and 0 if *A == *B. */
315
316int
46c5ad27 317sreal_compare (sreal *a, sreal *b)
ac5e69da
JZ
318{
319 if (a->exp > b->exp)
320 return 1;
321 if (a->exp < b->exp)
322 return -1;
323#if SREAL_PART_BITS < 32
324 if (a->sig_hi > b->sig_hi)
325 return 1;
326 if (a->sig_hi < b->sig_hi)
327 return -1;
328 if (a->sig_lo > b->sig_lo)
329 return 1;
330 if (a->sig_lo < b->sig_lo)
331 return -1;
332#else
333 if (a->sig > b->sig)
334 return 1;
335 if (a->sig < b->sig)
336 return -1;
337#endif
338 return 0;
339}
340
341/* *R = *A + *B. Return R. */
342
343sreal *
46c5ad27 344sreal_add (sreal *r, sreal *a, sreal *b)
ac5e69da
JZ
345{
346 int dexp;
347 sreal tmp;
348 sreal *bb;
349
350 if (sreal_compare (a, b) < 0)
351 {
352 sreal *swap;
353 swap = a;
354 a = b;
355 b = swap;
356 }
357
358 dexp = a->exp - b->exp;
359 r->exp = a->exp;
360 if (dexp > SREAL_BITS)
361 {
362#if SREAL_PART_BITS < 32
363 r->sig_hi = a->sig_hi;
364 r->sig_lo = a->sig_lo;
365#else
366 r->sig = a->sig;
367#endif
368 return r;
369 }
370
371 if (dexp == 0)
372 bb = b;
373 else
374 {
375 copy (&tmp, b);
376 shift_right (&tmp, dexp);
377 bb = &tmp;
378 }
379
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))
384 {
385 r->sig_hi++;
386 r->sig_lo -= (uhwi) 1 << SREAL_PART_BITS;
387 }
388#else
389 r->sig = a->sig + bb->sig;
390#endif
391 normalize (r);
392 return r;
393}
394
395/* *R = *A - *B. Return R. */
396
397sreal *
46c5ad27 398sreal_sub (sreal *r, sreal *a, sreal *b)
ac5e69da
JZ
399{
400 int dexp;
401 sreal tmp;
402 sreal *bb;
403
404 if (sreal_compare (a, b) < 0)
405 {
406 abort ();
407 }
408
409 dexp = a->exp - b->exp;
410 r->exp = a->exp;
411 if (dexp > SREAL_BITS)
412 {
413#if SREAL_PART_BITS < 32
414 r->sig_hi = a->sig_hi;
415 r->sig_lo = a->sig_lo;
416#else
417 r->sig = a->sig;
418#endif
419 return r;
420 }
421 if (dexp == 0)
422 bb = b;
423 else
424 {
425 copy (&tmp, b);
426 shift_right (&tmp, dexp);
427 bb = &tmp;
428 }
429
430#if SREAL_PART_BITS < 32
431 if (a->sig_lo < bb->sig_lo)
432 {
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;
435 }
436 else
437 {
438 r->sig_hi = a->sig_hi - bb->sig_hi;
439 r->sig_lo = a->sig_lo - bb->sig_lo;
440 }
441#else
442 r->sig = a->sig - bb->sig;
443#endif
444 normalize (r);
445 return r;
446}
447
448/* *R = *A * *B. Return R. */
449
450sreal *
46c5ad27 451sreal_mul (sreal *r, sreal *a, sreal *b)
ac5e69da
JZ
452{
453#if SREAL_PART_BITS < 32
454 if (a->sig_hi < SREAL_MIN_SIG || b->sig_hi < SREAL_MIN_SIG)
455 {
456 r->sig_lo = 0;
457 r->sig_hi = 0;
458 r->exp = -SREAL_MAX_EXP;
459 }
460 else
461 {
462 unsigned HOST_WIDE_INT tmp1, tmp2, tmp3;
463 if (sreal_compare (a, b) < 0)
464 {
465 sreal *swap;
466 swap = a;
467 a = b;
468 b = swap;
469 }
470
471 r->exp = a->exp + b->exp + SREAL_PART_BITS;
472
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);
476
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;
481 tmp1 = tmp2 + tmp3;
482
483 r->sig_lo = tmp1 & (((uhwi) 1 << SREAL_PART_BITS) - 1);
484 r->sig_hi += tmp1 >> SREAL_PART_BITS;
485
486 normalize (r);
487 }
488#else
489 if (a->sig < SREAL_MIN_SIG || b->sig < SREAL_MIN_SIG)
490 {
491 r->sig = 0;
492 r->exp = -SREAL_MAX_EXP;
493 }
494 else
495 {
496 r->sig = a->sig * b->sig;
497 r->exp = a->exp + b->exp;
498 normalize (r);
499 }
500#endif
501 return r;
502}
503
504/* *R = *A / *B. Return R. */
505
506sreal *
46c5ad27 507sreal_div (sreal *r, sreal *a, sreal *b)
ac5e69da
JZ
508{
509#if SREAL_PART_BITS < 32
510 unsigned HOST_WIDE_INT tmp, tmp1, tmp2;
511
512 if (b->sig_hi < SREAL_MIN_SIG)
513 {
514 abort ();
515 }
516 else if (a->sig_hi < SREAL_MIN_SIG)
517 {
518 r->sig_hi = 0;
519 r->sig_lo = 0;
520 r->exp = -SREAL_MAX_EXP;
521 }
522 else
523 {
524 /* Since division by the whole number is pretty ugly to write
525 we are dividing by first 3/4 of bits of number. */
526
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)))
531 tmp2++;
532
533 r->sig_lo = 0;
534 tmp = tmp1 / tmp2;
535 tmp1 = (tmp1 % tmp2) << (SREAL_PART_BITS / 2);
536 r->sig_hi = tmp << SREAL_PART_BITS;
537
538 tmp = tmp1 / tmp2;
539 tmp1 = (tmp1 % tmp2) << (SREAL_PART_BITS / 2);
540 r->sig_hi += tmp << (SREAL_PART_BITS / 2);
541
542 tmp = tmp1 / tmp2;
543 r->sig_hi += tmp;
544
545 r->exp = a->exp - b->exp - SREAL_BITS - SREAL_PART_BITS / 2;
546 normalize (r);
547 }
548#else
549 if (b->sig == 0)
550 {
551 abort ();
552 }
553 else
554 {
555 r->sig = (a->sig << SREAL_PART_BITS) / b->sig;
556 r->exp = a->exp - b->exp - SREAL_PART_BITS;
557 normalize (r);
558 }
559#endif
560 return r;
561}