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