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