beifg: Let be_ifg_foreach_neighbour() declare the node variable.
[libfirm] / ir / tv / fltcalc.c
1 /*
2  * Copyright (C) 1995-2011 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief    tarval floating point calculations
23  * @date     2003
24  * @author   Mathias Heil
25  */
26 #include "config.h"
27
28 #include "fltcalc.h"
29 #include "strcalc.h"
30 #include "error.h"
31
32 #include <math.h>
33 #include <inttypes.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <assert.h>
38 #include <stdbool.h>
39
40 #include "xmalloc.h"
41
42 /*
43  * portability stuff (why do we even care about the msvc people with their C89?)
44  */
45
46
47 static long double string_to_long_double(const char *str)
48 {
49 #if __STDC_VERSION__ >= 199901L || _POSIX_C_SOURCE >= 200112L
50         return strtold(str, NULL);
51 #else
52         return strtod(str, NULL);
53 #endif
54 }
55
56 static bool my_isnan(long double val)
57 {
58 #if __STDC_VERSION__ >= 199901L
59         return isnan(val);
60 #else
61         /* hopefully the compiler does not optimize aggressively (=incorrect) */
62         return val != val;
63 #endif
64 }
65
66 static bool my_isinf(long double val)
67 {
68 #if __STDC_VERSION__ >= 199901L
69         return isinf(val);
70 #else
71         /* hopefully the compiler does not optimize aggressively (=incorrect) */
72         return my_isnan(val-val) && !my_isnan(val);
73 #endif
74 }
75
76 /** The number of extra precision rounding bits */
77 #define ROUNDING_BITS 2
78
79 typedef union {
80         struct {
81 #ifdef WORDS_BIGENDIAN
82                 uint32_t high;
83 #else
84                 uint32_t low;
85 #endif
86                 uint32_t mid;
87 #ifdef WORDS_BIGENDIAN
88                 uint32_t low;
89 #else
90                 uint32_t high;
91 #endif
92         } val_ld12;
93         struct {
94 #ifdef WORDS_BIGENDIAN
95                 uint32_t high;
96 #else
97                 uint32_t low;
98 #endif
99 #ifdef WORDS_BIGENDIAN
100                 uint32_t low;
101 #else
102                 uint32_t high;
103 #endif
104         } val_ld8;
105         volatile long double d;
106 } value_t;
107
108 #define CLEAR_BUFFER(buffer) memset(buffer, 0, calc_buffer_size)
109
110 /* our floating point value */
111 struct fp_value {
112         float_descriptor_t desc;
113         unsigned char clss;
114         char sign;
115         char value[1];        /* exp[value_size] + mant[value_size] */
116 };
117
118 #define _exp(a)  &((a)->value[0])
119 #define _mant(a) &((a)->value[value_size])
120
121 #define _save_result(x) memcpy((x), sc_get_buffer(), value_size)
122 #define _shift_right(x, y, res) sc_shr((x), (y), value_size*4, 0, (res))
123 #define _shift_left(x, y, res) sc_shl((x), (y), value_size*4, 0, (res))
124
125 /** A temporal buffer. */
126 static fp_value *calc_buffer = NULL;
127
128 /** Current rounding mode.*/
129 static fc_rounding_mode_t rounding_mode;
130
131 static int calc_buffer_size;
132 static int value_size;
133 static int max_precision;
134
135 /** Exact flag. */
136 static int fc_exact = 1;
137
138 /** pack machine-like */
139 static void *pack(const fp_value *int_float, void *packed)
140 {
141         char     *shift_val;
142         char     *temp;
143         fp_value *val_buffer;
144         int      pos;
145
146         temp      = (char*) alloca(value_size);
147         shift_val = (char*) alloca(value_size);
148
149         switch ((value_class_t)int_float->clss) {
150         case FC_NAN:
151                 val_buffer = (fp_value*) alloca(calc_buffer_size);
152                 fc_get_qnan(&int_float->desc, val_buffer);
153                 int_float = val_buffer;
154                 break;
155
156         case FC_INF:
157                 val_buffer = (fp_value*) alloca(calc_buffer_size);
158                 fc_get_plusinf(&int_float->desc, val_buffer);
159                 val_buffer->sign = int_float->sign;
160                 int_float = val_buffer;
161                 break;
162
163         default:
164                 break;
165         }
166         assert(int_float->desc.explicit_one <= 1);
167
168         /* pack sign: move it to the left after exponent AND mantissa */
169         sc_val_from_ulong(int_float->sign, temp);
170
171         pos = int_float->desc.exponent_size + int_float->desc.mantissa_size + int_float->desc.explicit_one;
172         sc_val_from_ulong(pos, NULL);
173         _shift_left(temp, sc_get_buffer(), packed);
174
175         /* pack exponent: move it to the left after mantissa */
176         pos = int_float->desc.mantissa_size + int_float->desc.explicit_one;
177         sc_val_from_ulong(pos, shift_val);
178         _shift_left(_exp(int_float), shift_val, temp);
179
180         /* combine sign|exponent */
181         sc_or(temp, packed, packed);
182
183         /* extract mantissa */
184         /* remove rounding bits */
185         sc_val_from_ulong(ROUNDING_BITS, shift_val);
186         _shift_right(_mant(int_float), shift_val, temp);
187
188         /* remove leading 1 (or 0 if denormalized) */
189         sc_max_from_bits(pos, 0, shift_val); /* all mantissa bits are 1's */
190         sc_and(temp, shift_val, temp);
191
192         /* combine sign|exponent|mantissa */
193         sc_or(temp, packed, packed);
194
195         return packed;
196 }
197
198 /**
199  * Normalize a fp_value.
200  *
201  * @return non-zero if result is exact
202  */
203 static int normalize(const fp_value *in_val, fp_value *out_val, int sticky)
204 {
205         int exact = 1;
206         int hsb;
207         char lsb, guard, round, round_dir = 0;
208         char *temp = (char*) alloca(value_size);
209
210         /* save rounding bits at the end */
211         hsb = ROUNDING_BITS + in_val->desc.mantissa_size - sc_get_highest_set_bit(_mant(in_val)) - 1;
212
213         if (in_val != out_val)   {
214                 out_val->sign = in_val->sign;
215                 out_val->desc = in_val->desc;
216         }
217
218         out_val->clss = FC_NORMAL;
219
220         /* mantissa all zeros, so zero exponent (because of explicit one) */
221         if (hsb == ROUNDING_BITS + in_val->desc.mantissa_size)   {
222                 sc_val_from_ulong(0, _exp(out_val));
223                 hsb = -1;
224         }
225
226         /* shift the first 1 into the left of the radix point (i.e. hsb == -1) */
227         if (hsb < -1)   {
228                 /* shift right */
229                 sc_val_from_ulong(-hsb-1, temp);
230
231                 _shift_right(_mant(in_val), temp, _mant(out_val));
232
233                 /* remember if some bits were shifted away */
234                 if (sc_had_carry()) {
235                         exact = 0;
236                         sticky = 1;
237                 }
238                 sc_add(_exp(in_val), temp, _exp(out_val));
239         } else if (hsb > -1) {
240                 /* shift left */
241                 sc_val_from_ulong(hsb+1, temp);
242
243                 _shift_left(_mant(in_val), temp, _mant(out_val));
244
245                 sc_sub(_exp(in_val), temp, _exp(out_val));
246         }
247
248         /* check for exponent underflow */
249         if (sc_is_negative(_exp(out_val)) || sc_is_zero(_exp(out_val))) {
250                 /* exponent underflow */
251                 /* shift the mantissa right to have a zero exponent */
252                 sc_val_from_ulong(1, temp);
253                 sc_sub(temp, _exp(out_val), NULL);
254
255                 _shift_right(_mant(out_val), sc_get_buffer(), _mant(out_val));
256                 if (sc_had_carry()) {
257                         exact  = 0;
258                         sticky = 1;
259                 }
260                 /* denormalized means exponent of zero */
261                 sc_val_from_ulong(0, _exp(out_val));
262
263                 out_val->clss = FC_SUBNORMAL;
264         }
265
266         /* perform rounding by adding a value that clears the guard bit and the round bit
267          * and either causes a carry to round up or not */
268         /* get the last 3 bits of the value */
269         lsb = sc_sub_bits(_mant(out_val), out_val->desc.mantissa_size + ROUNDING_BITS, 0) & 0x7;
270         guard = (lsb&0x2)>>1;
271         round = lsb&0x1;
272
273         switch (rounding_mode) {
274         case FC_TONEAREST:
275                 /* round to nearest representable value, if in doubt choose the version
276                  * with lsb == 0 */
277                 round_dir = guard && (sticky || round || lsb>>2);
278                 break;
279         case FC_TOPOSITIVE:
280                 /* if positive: round to one if the exact value is bigger, else to zero */
281                 round_dir = (!out_val->sign && (guard || round || sticky));
282                 break;
283         case FC_TONEGATIVE:
284                 /* if negative: round to one if the exact value is bigger, else to zero */
285                 round_dir = (out_val->sign && (guard || round || sticky));
286                 break;
287         case FC_TOZERO:
288                 /* always round to 0 (chopping mode) */
289                 round_dir = 0;
290                 break;
291         }
292
293         if (round_dir == 1) {
294                 guard = (round^guard)<<1;
295                 lsb = !(round || guard)<<2 | guard | round;
296         } else {
297                 lsb = -((guard<<1) | round);
298         }
299
300         /* add the rounded value */
301         if (lsb != 0) {
302                 sc_val_from_long(lsb, temp);
303                 sc_add(_mant(out_val), temp, _mant(out_val));
304                 exact = 0;
305         }
306
307         /* could have rounded down to zero */
308         if (sc_is_zero(_mant(out_val)) && (out_val->clss == FC_SUBNORMAL))
309                 out_val->clss = FC_ZERO;
310
311         /* check for rounding overflow */
312         hsb = ROUNDING_BITS + out_val->desc.mantissa_size - sc_get_highest_set_bit(_mant(out_val)) - 1;
313         if ((out_val->clss != FC_SUBNORMAL) && (hsb < -1)) {
314                 sc_val_from_ulong(1, temp);
315                 _shift_right(_mant(out_val), temp, _mant(out_val));
316                 if (exact && sc_had_carry())
317                         exact = 0;
318                 sc_add(_exp(out_val), temp, _exp(out_val));
319         } else if ((out_val->clss == FC_SUBNORMAL) && (hsb == -1)) {
320                 /* overflow caused the mantissa to be normal again,
321                  * so adapt the exponent accordingly */
322                 sc_val_from_ulong(1, temp);
323                 sc_add(_exp(out_val), temp, _exp(out_val));
324
325                 out_val->clss = FC_NORMAL;
326         }
327         /* no further rounding is needed, because rounding overflow means
328          * the carry of the original rounding was propagated all the way
329          * up to the bit left of the radix point. This implies the bits
330          * to the right are all zeros (rounding is +1) */
331
332         /* check for exponent overflow */
333         sc_val_from_ulong((1 << out_val->desc.exponent_size) - 1, temp);
334         if (sc_comp(_exp(out_val), temp) != -1) {
335                 /* exponent overflow, reaction depends on rounding method:
336                  *
337                  * mode        | sign of value |  result
338                  *--------------------------------------------------------------
339                  * TO_NEAREST  |      +        |   +inf
340                  *             |      -        |   -inf
341                  *--------------------------------------------------------------
342                  * TO_POSITIVE |      +        |   +inf
343                  *             |      -        |   smallest representable value
344                  *--------------------------------------------------------------
345                  * TO_NEAGTIVE |      +        |   largest representable value
346                  *             |      -        |   -inf
347                  *--------------------------------------------------------------
348                  * TO_ZERO     |      +        |   largest representable value
349                  *             |      -        |   smallest representable value
350                  *--------------------------------------------------------------*/
351                 if (out_val->sign == 0) {
352                         /* value is positive */
353                         switch (rounding_mode) {
354                         case FC_TONEAREST:
355                         case FC_TOPOSITIVE:
356                                 out_val->clss = FC_INF;
357                                 break;
358
359                         case FC_TONEGATIVE:
360                         case FC_TOZERO:
361                                 fc_get_max(&out_val->desc, out_val);
362                         }
363                 } else {
364                         /* value is negative */
365                         switch (rounding_mode) {
366                         case FC_TONEAREST:
367                         case FC_TONEGATIVE:
368                                 out_val->clss = FC_INF;
369                                 break;
370
371                         case FC_TOPOSITIVE:
372                         case FC_TOZERO:
373                                 fc_get_min(&out_val->desc, out_val);
374                         }
375                 }
376         }
377         return exact;
378 }
379
380 /**
381  * Operations involving NaN's must return NaN.
382  * They are NOT exact.
383  */
384 #define handle_NAN(a, b, result) \
385 do {                                                      \
386   if (a->clss == FC_NAN) {                                \
387     if (a != result) memcpy(result, a, calc_buffer_size); \
388     fc_exact = 0;                                         \
389     return;                                               \
390   }                                                       \
391   if (b->clss == FC_NAN) {                                \
392     if (b != result) memcpy(result, b, calc_buffer_size); \
393     fc_exact = 0;                                         \
394     return;                                               \
395   }                                                       \
396 }while (0)
397
398
399 /**
400  * calculate a + b, where a is the value with the bigger exponent
401  */
402 static void _fadd(const fp_value *a, const fp_value *b, fp_value *result)
403 {
404         char *temp;
405         char *exp_diff;
406
407         char sign, res_sign;
408         char sticky;
409
410         fc_exact = 1;
411
412         handle_NAN(a, b, result);
413
414         /* make sure result has a descriptor */
415         if (result != a && result != b)
416                 result->desc = a->desc;
417
418         /* determine if this is an addition or subtraction */
419         sign = a->sign ^ b->sign;
420
421         /* produce NaN on inf - inf */
422         if (sign && (a->clss == FC_INF) && (b->clss == FC_INF)) {
423                 fc_exact = 0;
424                 fc_get_qnan(&a->desc, result);
425                 return;
426         }
427
428         temp     = (char*) alloca(value_size);
429         exp_diff = (char*) alloca(value_size);
430
431         /* get exponent difference */
432         sc_sub(_exp(a), _exp(b), exp_diff);
433
434         /* initially set sign to be the sign of a, special treatment of subtraction
435          * when exponents are equal is required though.
436          * Also special care about the sign is needed when the mantissas are equal
437          * (+/- 0 ?) */
438         if (sign && sc_val_to_long(exp_diff) == 0) {
439                 switch (sc_comp(_mant(a), _mant(b))) {
440                 case 1:  /* a > b */
441                         res_sign = a->sign;  /* abs(a) is bigger and a is negative */
442                         break;
443                 case 0:  /* a == b */
444                         res_sign = (rounding_mode == FC_TONEGATIVE);
445                         break;
446                 case -1: /* a < b */
447                         res_sign = b->sign; /* abs(b) is bigger and b is negative */
448                         break;
449                 default:
450                         /* can't be reached */
451                         res_sign = 0;
452                         break;
453                 }
454         }
455         else
456                 res_sign = a->sign;
457         result->sign = res_sign;
458
459         /* sign has been taken care of, check for special cases */
460         if (a->clss == FC_ZERO || b->clss == FC_INF) {
461                 if (b != result)
462                         memcpy(result, b, calc_buffer_size);
463                 fc_exact = b->clss == FC_NORMAL;
464                 result->sign = res_sign;
465                 return;
466         }
467         if (b->clss == FC_ZERO || a->clss == FC_INF) {
468                 if (a != result)
469                         memcpy(result, a, calc_buffer_size);
470                 fc_exact = a->clss == FC_NORMAL;
471                 result->sign = res_sign;
472                 return;
473         }
474
475         /* shift the smaller value to the right to align the radix point */
476         /* subnormals have their radix point shifted to the right,
477          * take care of this first */
478         if ((b->clss == FC_SUBNORMAL) && (a->clss != FC_SUBNORMAL)) {
479                 sc_val_from_ulong(1, temp);
480                 sc_sub(exp_diff, temp, exp_diff);
481         }
482
483         _shift_right(_mant(b), exp_diff, temp);
484         sticky = sc_had_carry();
485         fc_exact &= !sticky;
486
487         if (sticky && sign) {
488                 /* if subtracting a little more than the represented value or adding a little
489                  * more than the represented value to a negative value this, in addition to the
490                  * still set sticky bit, takes account of the 'little more' */
491                 char *temp1 = (char*) alloca(calc_buffer_size);
492                 sc_val_from_ulong(1, temp1);
493                 sc_add(temp, temp1, temp);
494         }
495
496         if (sign) {
497                 if (sc_comp(_mant(a), temp) == -1)
498                         sc_sub(temp, _mant(a), _mant(result));
499                 else
500                         sc_sub(_mant(a), temp, _mant(result));
501         } else {
502                 sc_add(_mant(a), temp, _mant(result));
503         }
504
505         /* _normalize expects a 'normal' radix point, adding two subnormals
506          * results in a subnormal radix point -> shifting before normalizing */
507         if ((a->clss == FC_SUBNORMAL) && (b->clss == FC_SUBNORMAL)) {
508                 sc_val_from_ulong(1, NULL);
509                 _shift_left(_mant(result), sc_get_buffer(), _mant(result));
510         }
511
512         /* resulting exponent is the bigger one */
513         memmove(_exp(result), _exp(a), value_size);
514
515         fc_exact &= normalize(result, result, sticky);
516 }
517
518 /**
519  * calculate a * b
520  */
521 static void _fmul(const fp_value *a, const fp_value *b, fp_value *result)
522 {
523         int sticky;
524         char *temp;
525         char res_sign;
526
527         fc_exact = 1;
528
529         handle_NAN(a, b, result);
530
531         temp = (char*) alloca(value_size);
532
533         if (result != a && result != b)
534                 result->desc = a->desc;
535
536         result->sign = res_sign = a->sign ^ b->sign;
537
538         /* produce NaN on 0 * inf */
539         if (a->clss == FC_ZERO) {
540                 if (b->clss == FC_INF) {
541                         fc_get_qnan(&a->desc, result);
542                         fc_exact = 0;
543                 } else {
544                         if (a != result)
545                                 memcpy(result, a, calc_buffer_size);
546                         result->sign = res_sign;
547                 }
548                 return;
549         }
550         if (b->clss == FC_ZERO) {
551                 if (a->clss == FC_INF) {
552                         fc_get_qnan(&a->desc, result);
553                         fc_exact = 0;
554                 } else {
555                         if (b != result)
556                                 memcpy(result, b, calc_buffer_size);
557                         result->sign = res_sign;
558                 }
559                 return;
560         }
561
562         if (a->clss == FC_INF) {
563                 fc_exact = 0;
564                 if (a != result)
565                         memcpy(result, a, calc_buffer_size);
566                 result->sign = res_sign;
567                 return;
568         }
569         if (b->clss == FC_INF) {
570                 fc_exact = 0;
571                 if (b != result)
572                         memcpy(result, b, calc_buffer_size);
573                 result->sign = res_sign;
574                 return;
575         }
576
577         /* exp = exp(a) + exp(b) - excess */
578         sc_add(_exp(a), _exp(b), _exp(result));
579
580         sc_val_from_ulong((1 << (a->desc.exponent_size - 1)) - 1, temp);
581         sc_sub(_exp(result), temp, _exp(result));
582
583         /* mixed normal, subnormal values introduce an error of 1, correct it */
584         if ((a->clss == FC_SUBNORMAL) ^ (b->clss == FC_SUBNORMAL)) {
585                 sc_val_from_ulong(1, temp);
586                 sc_add(_exp(result), temp, _exp(result));
587         }
588
589         sc_mul(_mant(a), _mant(b), _mant(result));
590
591         /* realign result: after a multiplication the digits right of the radix
592          * point are the sum of the factors' digits after the radix point. As all
593          * values are normalized they both have the same amount of these digits,
594          * which has to be restored by proper shifting
595          * because of the rounding bits */
596         sc_val_from_ulong(ROUNDING_BITS + result->desc.mantissa_size, temp);
597
598         _shift_right(_mant(result), temp, _mant(result));
599         sticky = sc_had_carry();
600         fc_exact &= !sticky;
601
602         fc_exact &= normalize(result, result, sticky);
603 }
604
605 /**
606  * calculate a / b
607  */
608 static void _fdiv(const fp_value *a, const fp_value *b, fp_value *result)
609 {
610         int sticky;
611         char *temp, *dividend;
612         char res_sign;
613
614         fc_exact = 1;
615
616         handle_NAN(a, b, result);
617
618         temp = (char*) alloca(value_size);
619         dividend = (char*) alloca(value_size);
620
621         if (result != a && result != b)
622                 result->desc = a->desc;
623
624         result->sign = res_sign = a->sign ^ b->sign;
625
626         /* produce FC_NAN on 0/0 and inf/inf */
627         if (a->clss == FC_ZERO) {
628                 if (b->clss == FC_ZERO) {
629                         /* 0/0 -> NaN */
630                         fc_get_qnan(&a->desc, result);
631                         fc_exact = 0;
632                 } else {
633                         /* 0/x -> a */
634                         if (a != result)
635                                 memcpy(result, a, calc_buffer_size);
636                         result->sign = res_sign;
637                 }
638                 return;
639         }
640
641         if (b->clss == FC_INF) {
642                 fc_exact = 0;
643                 if (a->clss == FC_INF) {
644                         /* inf/inf -> NaN */
645                         fc_get_qnan(&a->desc, result);
646                 } else {
647                         /* x/inf -> 0 */
648                         sc_val_from_ulong(0, NULL);
649                         _save_result(_exp(result));
650                         _save_result(_mant(result));
651                         result->clss = FC_ZERO;
652                 }
653                 return;
654         }
655
656         if (a->clss == FC_INF) {
657                 fc_exact = 0;
658                 /* inf/x -> inf */
659                 if (a != result)
660                         memcpy(result, a, calc_buffer_size);
661                 result->sign = res_sign;
662                 return;
663         }
664         if (b->clss == FC_ZERO) {
665                 fc_exact = 0;
666                 /* division by zero */
667                 if (result->sign)
668                         fc_get_minusinf(&a->desc, result);
669                 else
670                         fc_get_plusinf(&a->desc, result);
671                 return;
672         }
673
674         /* exp = exp(a) - exp(b) + excess - 1*/
675         sc_sub(_exp(a), _exp(b), _exp(result));
676         sc_val_from_ulong((1 << (a->desc.exponent_size - 1)) - 2, temp);
677         sc_add(_exp(result), temp, _exp(result));
678
679         /* mixed normal, subnormal values introduce an error of 1, correct it */
680         if ((a->clss == FC_SUBNORMAL) ^ (b->clss == FC_SUBNORMAL)) {
681                 sc_val_from_ulong(1, temp);
682                 sc_add(_exp(result), temp, _exp(result));
683         }
684
685         /* mant(res) = mant(a) / 1/2mant(b) */
686         /* to gain more bits of precision in the result the dividend could be
687          * shifted left, as this operation does not loose bits. This would not
688          * fit into the integer precision, but due to the rounding bits (which
689          * are always zero because the values are all normalized) the divisor
690          * can be shifted right instead to achieve the same result */
691         sc_val_from_ulong(ROUNDING_BITS + result->desc.mantissa_size, temp);
692
693         _shift_left(_mant(a), temp, dividend);
694
695         {
696                 char *divisor = (char*) alloca(calc_buffer_size);
697                 sc_val_from_ulong(1, divisor);
698                 _shift_right(_mant(b), divisor, divisor);
699                 sc_div(dividend, divisor, _mant(result));
700                 sticky = sc_had_carry();
701                 fc_exact &= !sticky;
702         }
703
704         fc_exact &= normalize(result, result, sticky);
705 }
706
707 /**
708  * Truncate the fractional part away.
709  *
710  * This does not clip to any integer range.
711  */
712 static void _trunc(const fp_value *a, fp_value *result)
713 {
714         /*
715          * When exponent == 0 all bits left of the radix point
716          * are the integral part of the value. For 15bit exp_size
717          * this would require a left shift of max. 16383 bits which
718          * is too much.
719          * But it is enough to ensure that no bit right of the radix
720          * point remains set. This restricts the interesting
721          * exponents to the interval [0, mant_size-1].
722          * Outside this interval the truncated value is either 0 or
723          * it does not have fractional parts.
724          */
725
726         int exp_bias, exp_val;
727         char *temp;
728
729         /* fixme: can be exact */
730         fc_exact = 0;
731
732         temp = (char*) alloca(value_size);
733
734         if (a != result) {
735                 result->desc = a->desc;
736                 result->clss = a->clss;
737         }
738
739         exp_bias = (1 << (a->desc.exponent_size - 1)) - 1;
740         exp_val  = sc_val_to_long(_exp(a)) - exp_bias;
741
742         if (exp_val < 0) {
743                 sc_val_from_ulong(0, NULL);
744                 _save_result(_exp(result));
745                 _save_result(_mant(result));
746                 result->clss = FC_ZERO;
747
748                 return;
749         }
750
751         if (exp_val > (long)a->desc.mantissa_size) {
752                 if (a != result)
753                         memcpy(result, a, calc_buffer_size);
754
755                 return;
756         }
757
758         /* set up a proper mask to delete all bits right of the
759          * radix point if the mantissa had been shifted until exp == 0 */
760         sc_max_from_bits(1 + exp_val, 0, temp);
761         sc_val_from_long(a->desc.mantissa_size - exp_val + 2, NULL);
762         _shift_left(temp, sc_get_buffer(), temp);
763
764         /* and the mask and return the result */
765         sc_and(_mant(a), temp, _mant(result));
766
767         if (a != result) {
768                 memcpy(_exp(result), _exp(a), value_size);
769                 result->sign = a->sign;
770         }
771 }
772
773 /********
774  * functions defined in fltcalc.h
775  ********/
776 const void *fc_get_buffer(void)
777 {
778         return calc_buffer;
779 }
780
781 int fc_get_buffer_length(void)
782 {
783         return calc_buffer_size;
784 }
785
786 void *fc_val_from_str(const char *str, size_t len,
787                       const float_descriptor_t *desc, void *result)
788 {
789         char *buffer;
790
791         /* XXX excuse of an implementation to make things work */
792         long double        val;
793         fp_value          *tmp = (fp_value*) alloca(calc_buffer_size);
794         float_descriptor_t tmp_desc;
795
796         buffer = (char*) alloca(len+1);
797         memcpy(buffer, str, len);
798         buffer[len] = '\0';
799         val = string_to_long_double(buffer);
800
801         tmp_desc.exponent_size = 15;
802         tmp_desc.mantissa_size = 63;
803         tmp_desc.explicit_one  = 1;
804         fc_val_from_ieee754(val, &tmp_desc, tmp);
805
806         return fc_cast(tmp, desc, (fp_value*) result);
807 }
808
809 fp_value *fc_val_from_ieee754(long double l, const float_descriptor_t *desc,
810                               fp_value *result)
811 {
812         char    *temp;
813         int      bias_res, bias_val, mant_val;
814         value_t  srcval;
815         char     sign;
816         uint32_t exponent, mantissa0, mantissa1;
817         size_t   long_double_size = sizeof(long double);
818
819         srcval.d = l;
820         bias_res = ((1 << (desc->exponent_size - 1)) - 1);
821
822         if (long_double_size == 8) {
823                 mant_val  = 52;
824                 bias_val  = 0x3ff;
825                 sign      = (srcval.val_ld8.high & 0x80000000) != 0;
826                 exponent  = (srcval.val_ld8.high & 0x7FF00000) >> 20;
827                 mantissa0 = srcval.val_ld8.high & 0x000FFFFF;
828                 mantissa1 = srcval.val_ld8.low;
829         } else {
830                 /* we assume an x86-like 80bit representation of the value... */
831                 assert(sizeof(long double)==12 || sizeof(long double)==16);
832                 mant_val  = 63;
833                 bias_val  = 0x3fff;
834                 sign      = (srcval.val_ld12.high & 0x00008000) != 0;
835                 exponent  = (srcval.val_ld12.high & 0x00007FFF) ;
836                 mantissa0 = srcval.val_ld12.mid;
837                 mantissa1 = srcval.val_ld12.low;
838         }
839
840         if (result == NULL)
841                 result = calc_buffer;
842         temp = (char*) alloca(value_size);
843
844         /* CLEAR the buffer, else some bits might be uninitialized */
845         memset(result, 0, fc_get_buffer_length());
846
847         result->desc = *desc;
848         result->clss = FC_NORMAL;
849         result->sign = sign;
850
851         /* sign and flag suffice to identify NaN or inf, no exponent/mantissa
852          * encoding is needed. the function can return immediately in these cases */
853         if (my_isnan(l)) {
854                 result->clss = FC_NAN;
855                 return result;
856         } else if (my_isinf(l)) {
857                 result->clss = FC_INF;
858                 return result;
859         }
860
861         /* build exponent, because input and output exponent and mantissa sizes may differ
862          * this looks more complicated than it is: unbiased input exponent + output bias,
863          * minus the mantissa difference which is added again later when the output float
864          * becomes normalized */
865         sc_val_from_long((exponent - bias_val + bias_res) - (mant_val - desc->mantissa_size), _exp(result));
866
867         /* build mantissa representation */
868         if (exponent != 0) {
869                 /* insert the hidden bit */
870                 sc_val_from_ulong(1, temp);
871                 sc_val_from_ulong(mant_val + ROUNDING_BITS, NULL);
872                 _shift_left(temp, sc_get_buffer(), NULL);
873         }
874         else {
875                 sc_val_from_ulong(0, NULL);
876         }
877
878         _save_result(_mant(result));
879
880         /* bits from the upper word */
881         sc_val_from_ulong(mantissa0, temp);
882         sc_val_from_ulong(34, NULL);
883         _shift_left(temp, sc_get_buffer(), temp);
884         sc_or(_mant(result), temp, _mant(result));
885
886         /* bits from the lower word */
887         sc_val_from_ulong(mantissa1, temp);
888         sc_val_from_ulong(ROUNDING_BITS, NULL);
889         _shift_left(temp, sc_get_buffer(), temp);
890         sc_or(_mant(result), temp, _mant(result));
891
892         /* _normalize expects the radix point to be normal, so shift mantissa of subnormal
893          * origin one to the left */
894         if (exponent == 0) {
895                 sc_val_from_ulong(1, NULL);
896                 _shift_left(_mant(result), sc_get_buffer(), _mant(result));
897         }
898
899         normalize(result, result, 0);
900
901         return result;
902 }
903
904 long double fc_val_to_ieee754(const fp_value *val)
905 {
906         fp_value *value;
907         fp_value *temp = NULL;
908
909         unsigned byte_offset;
910
911         uint32_t sign;
912         uint32_t exponent;
913         uint32_t mantissa0;
914         uint32_t mantissa1;
915
916         value_t           buildval;
917         float_descriptor_t desc;
918         unsigned          mantissa_size;
919
920         size_t            long_double_size = sizeof(long double);
921
922         if (long_double_size == 8) {
923                 desc.exponent_size = 11;
924                 desc.mantissa_size = 52;
925                 desc.explicit_one  = 0;
926         } else {
927                 desc.exponent_size = 15;
928                 desc.mantissa_size = 63;
929                 desc.explicit_one  = 1;
930         }
931         mantissa_size = desc.mantissa_size + desc.explicit_one;
932
933         temp = (fp_value*) alloca(calc_buffer_size);
934         value = fc_cast(val, &desc, temp);
935
936         sign = value->sign;
937
938         /* @@@ long double exponent is 15bit, so the use of sc_val_to_long should not
939          * lead to wrong results */
940         exponent = sc_val_to_long(_exp(value)) ;
941
942         sc_val_from_ulong(ROUNDING_BITS, NULL);
943         _shift_right(_mant(value), sc_get_buffer(), _mant(value));
944
945         mantissa0 = 0;
946         mantissa1 = 0;
947
948         for (byte_offset = 0; byte_offset < 4; byte_offset++)
949                 mantissa1 |= sc_sub_bits(_mant(value), mantissa_size, byte_offset) << (byte_offset << 3);
950
951         for (; (byte_offset<<3) < desc.mantissa_size; byte_offset++)
952                 mantissa0 |= sc_sub_bits(_mant(value), mantissa_size, byte_offset) << ((byte_offset - 4) << 3);
953
954         if (long_double_size == 8) {
955                 mantissa0 &= 0x000FFFFF;  /* get rid of garbage */
956                 buildval.val_ld8.high = sign << 31;
957                 buildval.val_ld8.high |= exponent << 20;
958                 buildval.val_ld8.high |= mantissa0;
959                 buildval.val_ld8.low = mantissa1;
960         } else {
961                 buildval.val_ld12.high = sign << 15;
962                 buildval.val_ld12.high |= exponent;
963                 buildval.val_ld12.mid = mantissa0;
964                 buildval.val_ld12.low = mantissa1;
965         }
966
967         return buildval.d;
968 }
969
970 fp_value *fc_cast(const fp_value *value, const float_descriptor_t *desc,
971                   fp_value *result)
972 {
973         char *temp;
974         int exp_offset, val_bias, res_bias;
975
976         if (result == NULL) result = calc_buffer;
977         temp = (char*) alloca(value_size);
978
979         if (value->desc.exponent_size == desc->exponent_size &&
980                 value->desc.mantissa_size == desc->mantissa_size &&
981                 value->desc.explicit_one  == desc->explicit_one) {
982                 if (value != result)
983                         memcpy(result, value, calc_buffer_size);
984                 return result;
985         }
986
987         if (value->clss == FC_NAN) {
988                 if (sc_get_highest_set_bit(_mant(value)) == value->desc.mantissa_size + 1)
989                         return fc_get_qnan(desc, result);
990                 else
991                         return fc_get_snan(desc, result);
992         }
993         else if (value->clss == FC_INF) {
994                 if (value->sign == 0)
995                         return fc_get_plusinf(desc, result);
996                 else
997                         return fc_get_minusinf(desc, result);
998         }
999
1000         /* set the descriptor of the new value */
1001         result->desc = *desc;
1002         result->clss = value->clss;
1003         result->sign = value->sign;
1004
1005         /* when the mantissa sizes differ normalizing has to shift to align it.
1006          * this would change the exponent, which is unwanted. So calculate this
1007          * offset and add it */
1008         val_bias = (1 << (value->desc.exponent_size - 1)) - 1;
1009         res_bias = (1 << (desc->exponent_size - 1)) - 1;
1010
1011         exp_offset = (res_bias - val_bias) - (value->desc.mantissa_size - desc->mantissa_size);
1012         sc_val_from_long(exp_offset, temp);
1013         sc_add(_exp(value), temp, _exp(result));
1014
1015         /* _normalize expects normalized radix point */
1016         if (value->clss == FC_SUBNORMAL) {
1017                 sc_val_from_ulong(1, NULL);
1018                 _shift_left(_mant(value), sc_get_buffer(), _mant(result));
1019         } else if (value != result) {
1020                 memcpy(_mant(result), _mant(value), value_size);
1021         } else {
1022                 memmove(_mant(result), _mant(value), value_size);
1023         }
1024
1025         normalize(result, result, 0);
1026         return result;
1027 }
1028
1029 fp_value *fc_get_max(const float_descriptor_t *desc, fp_value *result)
1030 {
1031         if (result == NULL) result = calc_buffer;
1032
1033         result->desc = *desc;
1034         result->clss = FC_NORMAL;
1035         result->sign = 0;
1036
1037         sc_val_from_ulong((1 << desc->exponent_size) - 2, _exp(result));
1038
1039         sc_max_from_bits(desc->mantissa_size + 1, 0, _mant(result));
1040         sc_val_from_ulong(ROUNDING_BITS, NULL);
1041         _shift_left(_mant(result), sc_get_buffer(), _mant(result));
1042
1043         return result;
1044 }
1045
1046 fp_value *fc_get_min(const float_descriptor_t *desc, fp_value *result)
1047 {
1048         if (result == NULL) result = calc_buffer;
1049
1050         fc_get_max(desc, result);
1051         result->sign = 1;
1052
1053         return result;
1054 }
1055
1056 fp_value *fc_get_snan(const float_descriptor_t *desc, fp_value *result)
1057 {
1058         if (result == NULL) result = calc_buffer;
1059
1060         result->desc = *desc;
1061         result->clss = FC_NAN;
1062         result->sign = 0;
1063
1064         sc_val_from_ulong((1 << desc->exponent_size) - 1, _exp(result));
1065
1066         /* signaling NaN has non-zero mantissa with msb not set */
1067         sc_val_from_ulong(1, _mant(result));
1068
1069         return result;
1070 }
1071
1072 fp_value *fc_get_qnan(const float_descriptor_t *desc, fp_value *result)
1073 {
1074         if (result == NULL) result = calc_buffer;
1075
1076         result->desc = *desc;
1077         result->clss = FC_NAN;
1078         result->sign = 0;
1079
1080         sc_val_from_ulong((1 << desc->exponent_size) - 1, _exp(result));
1081
1082         /* quiet NaN has the msb of the mantissa set, so shift one there */
1083         sc_val_from_ulong(1, _mant(result));
1084         /* mantissa_size >+< 1 because of two extra rounding bits */
1085         sc_val_from_ulong(desc->mantissa_size + 1, NULL);
1086         _shift_left(_mant(result), sc_get_buffer(), _mant(result));
1087
1088         return result;
1089 }
1090
1091 fp_value *fc_get_plusinf(const float_descriptor_t *desc, fp_value *result)
1092 {
1093         char *mant;
1094
1095         if (result == NULL) result = calc_buffer;
1096
1097         result->desc = *desc;
1098         result->clss = FC_INF;
1099         result->sign = 0;
1100
1101         sc_val_from_ulong((1 << desc->exponent_size) - 1, _exp(result));
1102
1103         mant = _mant(result);
1104         sc_val_from_ulong(0, mant);
1105         if (desc->explicit_one) {
1106                 sc_set_bit_at(mant, result->desc.mantissa_size + ROUNDING_BITS);
1107         }
1108
1109         return result;
1110 }
1111
1112 fp_value *fc_get_minusinf(const float_descriptor_t *desc, fp_value *result)
1113 {
1114         if (result == NULL) result = calc_buffer;
1115
1116         fc_get_plusinf(desc, result);
1117         result->sign = 1;
1118
1119         return result;
1120 }
1121
1122 int fc_comp(const fp_value *val_a, const fp_value *val_b)
1123 {
1124         int mul = 1;
1125
1126         /*
1127          * shortcut: if both values are identical, they are either
1128          * Unordered if NaN or equal
1129          */
1130         if (val_a == val_b)
1131                 return val_a->clss == FC_NAN ? 2 : 0;
1132
1133         /* unordered if one is a NaN */
1134         if (val_a->clss == FC_NAN || val_b->clss == FC_NAN)
1135                 return 2;
1136
1137         /* zero is equal independent of sign */
1138         if ((val_a->clss == FC_ZERO) && (val_b->clss == FC_ZERO))
1139                 return 0;
1140
1141         /* different signs make compare easy */
1142         if (val_a->sign != val_b->sign)
1143                 return (val_a->sign == 0) ? (1) : (-1);
1144
1145         mul = val_a->sign ? -1 : 1;
1146
1147         /* both infinity means equality */
1148         if ((val_a->clss == FC_INF) && (val_b->clss == FC_INF))
1149                 return 0;
1150
1151         /* infinity is bigger than the rest */
1152         if (val_a->clss == FC_INF)
1153                 return  1 * mul;
1154         if (val_b->clss == FC_INF)
1155                 return -1 * mul;
1156
1157         /* check first exponent, that mantissa if equal */
1158         switch (sc_comp(_exp(val_a), _exp(val_b))) {
1159         case -1:
1160                 return -1 * mul;
1161         case  1:
1162                 return  1 * mul;
1163         case  0:
1164                 return sc_comp(_mant(val_a), _mant(val_b)) * mul;
1165         default:
1166                 return 2;
1167         }
1168 }
1169
1170 int fc_is_zero(const fp_value *a)
1171 {
1172         return a->clss == FC_ZERO;
1173 }
1174
1175 int fc_is_negative(const fp_value *a)
1176 {
1177         return a->sign;
1178 }
1179
1180 int fc_is_inf(const fp_value *a)
1181 {
1182         return a->clss == FC_INF;
1183 }
1184
1185 int fc_is_nan(const fp_value *a)
1186 {
1187         return a->clss == FC_NAN;
1188 }
1189
1190 int fc_is_subnormal(const fp_value *a)
1191 {
1192         return a->clss == FC_SUBNORMAL;
1193 }
1194
1195 char *fc_print(const fp_value *val, char *buf, int buflen, unsigned base)
1196 {
1197         char *mul_1;
1198         long double flt_val;
1199
1200         mul_1 = (char*) alloca(calc_buffer_size);
1201
1202         switch (base) {
1203         case FC_DEC:
1204                 switch ((value_class_t)val->clss) {
1205                 case FC_INF:
1206                         snprintf(buf, buflen, "%cINF", val->sign ? '-' : '+');
1207                         break;
1208                 case FC_NAN:
1209                         snprintf(buf, buflen, "NaN");
1210                         break;
1211                 case FC_ZERO:
1212                         snprintf(buf, buflen, "0.0");
1213                         break;
1214                 default:
1215                         flt_val = fc_val_to_ieee754(val);
1216                         /* XXX 30 is arbitrary */
1217                         snprintf(buf, buflen, "%.30LE", flt_val);
1218                 }
1219                 break;
1220
1221         case FC_HEX:
1222                 switch ((value_class_t)val->clss) {
1223                 case FC_INF:
1224                         snprintf(buf, buflen, "%cINF", val->sign ? '-' : '+');
1225                         break;
1226                 case FC_NAN:
1227                         snprintf(buf, buflen, "NaN");
1228                         break;
1229                 case FC_ZERO:
1230                         snprintf(buf, buflen, "0.0");
1231                         break;
1232                 default:
1233                         flt_val = fc_val_to_ieee754(val);
1234                         snprintf(buf, buflen, "%LA", flt_val);
1235                 }
1236                 break;
1237
1238         case FC_PACKED:
1239         default:
1240                 snprintf(buf, buflen, "%s", sc_print(pack(val, mul_1), value_size*4, SC_HEX, 0));
1241                 buf[buflen - 1] = '\0';
1242                 break;
1243         }
1244         return buf;
1245 }
1246
1247 unsigned char fc_sub_bits(const fp_value *value, unsigned num_bits, unsigned byte_ofs)
1248 {
1249         /* this is used to cache the packed version of the value */
1250         static char *packed_value = NULL;
1251
1252         if (packed_value == NULL) packed_value = XMALLOCN(char, value_size);
1253
1254         if (value != NULL)
1255                 pack(value, packed_value);
1256
1257         return sc_sub_bits(packed_value, num_bits, byte_ofs);
1258 }
1259
1260 /* Returns non-zero if the mantissa is zero, i.e. 1.0Exxx */
1261 int fc_zero_mantissa(const fp_value *value)
1262 {
1263         return sc_get_lowest_set_bit(_mant(value)) == ROUNDING_BITS + value->desc.mantissa_size;
1264 }
1265
1266 /* Returns the exponent of a value. */
1267 int fc_get_exponent(const fp_value *value)
1268 {
1269         int exp_bias = (1 << (value->desc.exponent_size - 1)) - 1;
1270         return sc_val_to_long(_exp(value)) - exp_bias;
1271 }
1272
1273 /* Return non-zero if a given value can be converted lossless into another precision */
1274 int fc_can_lossless_conv_to(const fp_value *value, const float_descriptor_t *desc)
1275 {
1276         int v;
1277         int exp_bias;
1278
1279         /* handle some special cases first */
1280         switch (value->clss) {
1281         case FC_ZERO:
1282         case FC_INF:
1283         case FC_NAN:
1284                 return 1;
1285         default:
1286                 break;
1287         }
1288
1289         /* check if the exponent can be encoded: note, 0 and all ones are reserved for the exponent */
1290         exp_bias = (1 << (desc->exponent_size - 1)) - 1;
1291         v = fc_get_exponent(value) + exp_bias;
1292         if (0 < v && v < (1 << desc->exponent_size) - 1) {
1293                 /* exponent can be encoded, now check the mantissa */
1294                 v = value->desc.mantissa_size + ROUNDING_BITS - sc_get_lowest_set_bit(_mant(value));
1295                 return v <= (int)desc->mantissa_size;
1296         }
1297         return 0;
1298 }
1299
1300
1301 fc_rounding_mode_t fc_set_rounding_mode(fc_rounding_mode_t mode)
1302 {
1303         if (mode == FC_TONEAREST || mode == FC_TOPOSITIVE || mode == FC_TONEGATIVE || mode == FC_TOZERO)
1304                 rounding_mode = mode;
1305
1306         return rounding_mode;
1307 }
1308
1309 fc_rounding_mode_t fc_get_rounding_mode(void)
1310 {
1311         return rounding_mode;
1312 }
1313
1314 void init_fltcalc(int precision)
1315 {
1316         if (calc_buffer == NULL) {
1317                 /* does nothing if already init */
1318                 if (precision == 0) precision = FC_DEFAULT_PRECISION;
1319
1320                 init_strcalc(precision + 2 + ROUNDING_BITS);
1321
1322                 /* needs additionally rounding bits, one bit as explicit 1., and one for
1323                  * addition overflow */
1324                 max_precision = sc_get_precision() - (2 + ROUNDING_BITS);
1325                 if (max_precision < precision)
1326                         printf("WARNING: not enough precision available, using %d\n", max_precision);
1327
1328                 rounding_mode    = FC_TONEAREST;
1329                 value_size       = sc_get_buffer_length();
1330                 calc_buffer_size = sizeof(fp_value) + 2*value_size - 1;
1331
1332                 calc_buffer = (fp_value*) xmalloc(calc_buffer_size);
1333                 memset(calc_buffer, 0, calc_buffer_size);
1334         }
1335 }
1336
1337 void finish_fltcalc (void)
1338 {
1339         free(calc_buffer); calc_buffer = NULL;
1340 }
1341
1342 /* definition of interface functions */
1343 fp_value *fc_add(const fp_value *a, const fp_value *b, fp_value *result)
1344 {
1345         if (result == NULL) result = calc_buffer;
1346
1347         /* make the value with the bigger exponent the first one */
1348         if (sc_comp(_exp(a), _exp(b)) == -1)
1349                 _fadd(b, a, result);
1350         else
1351                 _fadd(a, b, result);
1352
1353         return result;
1354 }
1355
1356 fp_value *fc_sub(const fp_value *a, const fp_value *b, fp_value *result)
1357 {
1358         fp_value *temp;
1359
1360         if (result == NULL) result = calc_buffer;
1361
1362         temp = (fp_value*) alloca(calc_buffer_size);
1363         memcpy(temp, b, calc_buffer_size);
1364         temp->sign = !b->sign;
1365         if (sc_comp(_exp(a), _exp(temp)) == -1)
1366                 _fadd(temp, a, result);
1367         else
1368                 _fadd(a, temp, result);
1369
1370         return result;
1371 }
1372
1373 fp_value *fc_mul(const fp_value *a, const fp_value *b, fp_value *result)
1374 {
1375         if (result == NULL) result = calc_buffer;
1376
1377         _fmul(a, b, result);
1378
1379         return result;
1380 }
1381
1382 fp_value *fc_div(const fp_value *a, const fp_value *b, fp_value *result)
1383 {
1384         if (result == NULL) result = calc_buffer;
1385
1386         _fdiv(a, b, result);
1387
1388         return result;
1389 }
1390
1391 fp_value *fc_neg(const fp_value *a, fp_value *result)
1392 {
1393         if (result == NULL) result = calc_buffer;
1394
1395         if (a != result)
1396                 memcpy(result, a, calc_buffer_size);
1397         result->sign = !a->sign;
1398
1399         return result;
1400 }
1401
1402 fp_value *fc_int(const fp_value *a, fp_value *result)
1403 {
1404         if (result == NULL) result = calc_buffer;
1405
1406         _trunc(a, result);
1407
1408         return result;
1409 }
1410
1411 fp_value *fc_rnd(const fp_value *a, fp_value *result)
1412 {
1413         (void)a;
1414         (void)result;
1415
1416         panic("not yet implemented");
1417 }
1418
1419 /*
1420  * convert a floating point value into an sc value ...
1421  */
1422 int fc_flt2int(const fp_value *a, void *result, ir_mode *dst_mode)
1423 {
1424         if (a->clss == FC_NORMAL) {
1425                 int exp_bias = (1 << (a->desc.exponent_size - 1)) - 1;
1426                 int exp_val  = sc_val_to_long(_exp(a)) - exp_bias;
1427                 int shift, highest;
1428                 int mantissa_size;
1429                 int tgt_bits;
1430
1431                 if (a->sign && !mode_is_signed(dst_mode)) {
1432                         /* FIXME: for now we cannot convert this */
1433                         return 0;
1434                 }
1435
1436                 tgt_bits = get_mode_size_bits(dst_mode);
1437                 if (mode_is_signed(dst_mode))
1438                         --tgt_bits;
1439
1440                 assert(exp_val >= 0 && "floating point value not integral before fc_flt2int() call");
1441                 mantissa_size = a->desc.mantissa_size + ROUNDING_BITS;
1442                 shift         = exp_val - mantissa_size;
1443
1444                 if (tgt_bits < mantissa_size + 1)
1445                         tgt_bits = mantissa_size + 1;
1446                 if (shift > 0) {
1447                         sc_shlI(_mant(a),  shift, tgt_bits, 0, result);
1448                 } else {
1449                         sc_shrI(_mant(a), -shift, tgt_bits, 0, result);
1450                 }
1451
1452                 /* check for overflow */
1453                 highest = sc_get_highest_set_bit(result);
1454
1455                 if (mode_is_signed(dst_mode)) {
1456                         if (highest == sc_get_lowest_set_bit(result)) {
1457                                 /* need extra test for MIN_INT */
1458                                 if (highest >= (int) get_mode_size_bits(dst_mode)) {
1459                                         /* FIXME: handle overflow */
1460                                         return 0;
1461                                 }
1462                         } else {
1463                                 if (highest >= (int) get_mode_size_bits(dst_mode) - 1) {
1464                                         /* FIXME: handle overflow */
1465                                         return 0;
1466                                 }
1467                         }
1468                 } else {
1469                         if (highest >= (int) get_mode_size_bits(dst_mode)) {
1470                                 /* FIXME: handle overflow */
1471                                 return 0;
1472                         }
1473                 }
1474
1475                 if (a->sign)
1476                         sc_neg(result, result);
1477
1478                 return 1;
1479         } else if (a->clss == FC_ZERO) {
1480                 sc_zero(result);
1481                 return 1;
1482         }
1483         return 0;
1484 }
1485
1486 int fc_is_exact(void)
1487 {
1488         return fc_exact;
1489 }