fixed conversion of NAN's
[libfirm] / ir / tv / fltcalc.c
1 /*
2  * Copyright (C) 1995-2007 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         result->desc.exponent_size = exp_size;
1067         result->desc.mantissa_size = mant_size;
1068
1069         /* extract sign */
1070         result->sign = sign;
1071
1072         /* sign and flag suffice to identify nan or inf, no exponent/mantissa
1073          * encoding is needed. the function can return immediately in these cases */
1074         if (isnan(l)) {
1075                 result->desc.clss = NAN;
1076                 TRACEPRINTF(("val_from_float resulted in NAN\n"));
1077                 return result;
1078         }
1079         else if (isinf(l)) {
1080                 result->desc.clss = INF;
1081                 TRACEPRINTF(("val_from_float resulted in %sINF\n", (result->sign == 1) ? "-" : ""));
1082                 return result;
1083         }
1084
1085         /* build exponent, because input and output exponent and mantissa sizes may differ
1086          * this looks more complicated than it is: unbiased input exponent + output bias,
1087          * minus the mantissa difference which is added again later when the output float
1088          * becomes normalized */
1089 #ifdef HAVE_EXPLICIT_ONE
1090         sc_val_from_long((exponent-bias_val+bias_res)-(mant_val-mant_size-1), _exp(result));
1091 #else
1092         sc_val_from_long((exponent-bias_val+bias_res)-(mant_val-mant_size), _exp(result));
1093 #endif
1094
1095         /* build mantissa representation */
1096 #ifndef HAVE_EXPLICIT_ONE
1097         if (exponent != 0) {
1098                 /* insert the hidden bit */
1099                 sc_val_from_ulong(1, temp);
1100                 sc_val_from_ulong(mant_val + 2, NULL);
1101                 _shift_left(temp, sc_get_buffer(), NULL);
1102         }
1103         else
1104 #endif
1105         {
1106                 sc_val_from_ulong(0, NULL);
1107         }
1108
1109         _save_result(_mant(result));
1110
1111         /* bits from the upper word */
1112         sc_val_from_ulong(mantissa0, temp);
1113         sc_val_from_ulong(34, NULL);
1114         _shift_left(temp, sc_get_buffer(), temp);
1115         sc_or(_mant(result), temp, _mant(result));
1116
1117         /* bits from the lower word */
1118         sc_val_from_ulong(mantissa1, temp);
1119         sc_val_from_ulong(2, NULL);
1120         _shift_left(temp, sc_get_buffer(), temp);
1121         sc_or(_mant(result), temp, _mant(result));
1122
1123         /* _normalize expects the radix point to be normal, so shift mantissa of subnormal
1124          * origin one to the left */
1125         if (exponent == 0) {
1126                 sc_val_from_ulong(1, NULL);
1127                 _shift_left(_mant(result), sc_get_buffer(), _mant(result));
1128         }
1129
1130         normalize(result, result, 0);
1131
1132         TRACEPRINTF(("val_from_float results in %s\n", fc_print(result, temp, calc_buffer_size, FC_PACKED)));
1133
1134         return result;
1135 }
1136
1137 LLDBL fc_val_to_ieee754(const fp_value *val) {
1138         fp_value *value;
1139         fp_value *temp = NULL;
1140
1141         int byte_offset;
1142
1143         UINT32 sign;
1144         UINT32 exponent;
1145         UINT32 mantissa0;
1146         UINT32 mantissa1;
1147
1148         value_t buildval;
1149
1150 #ifdef HAVE_LONG_DOUBLE
1151         char result_exponent = 15;
1152         char result_mantissa = 64;
1153 #else
1154         char result_exponent = 11;
1155         char result_mantissa = 52;
1156 #endif
1157
1158         temp = alloca(calc_buffer_size);
1159 #ifdef HAVE_EXPLICIT_ONE
1160         value = fc_cast(val, result_exponent, result_mantissa-1, temp);
1161 #else
1162         value = fc_cast(val, result_exponent, result_mantissa, temp);
1163 #endif
1164
1165         sign = value->sign;
1166
1167         /* @@@ long double exponent is 15bit, so the use of sc_val_to_long should not
1168          * lead to wrong results */
1169         exponent = sc_val_to_long(_exp(value)) ;
1170
1171         sc_val_from_ulong(2, NULL);
1172         _shift_right(_mant(value), sc_get_buffer(), _mant(value));
1173
1174         mantissa0 = 0;
1175         mantissa1 = 0;
1176
1177         for (byte_offset = 0; byte_offset < 4; byte_offset++)
1178                 mantissa1 |= sc_sub_bits(_mant(value), result_mantissa, byte_offset) << (byte_offset<<3);
1179
1180         for (; (byte_offset<<3) < result_mantissa; byte_offset++)
1181                 mantissa0 |= sc_sub_bits(_mant(value), result_mantissa, byte_offset) << ((byte_offset-4)<<3);
1182
1183 #ifdef HAVE_LONG_DOUBLE
1184         buildval.val.high = sign << 15;
1185         buildval.val.high |= exponent;
1186         buildval.val.mid = mantissa0;
1187         buildval.val.low = mantissa1;
1188 #else /* no long double */
1189         mantissa0 &= 0x000FFFFF;  /* get rid of garbage */
1190         buildval.val.high = sign << 31;
1191         buildval.val.high |= exponent << 20;
1192         buildval.val.high |= mantissa0;
1193         buildval.val.low = mantissa1;
1194 #endif
1195
1196         TRACEPRINTF(("val_to_float: %d-%x-%x%x\n", sign, exponent, mantissa0, mantissa1));
1197         return buildval.d;
1198 }
1199
1200 fp_value *fc_cast(const fp_value *value, char exp_size, char mant_size, fp_value *result) {
1201         char *temp;
1202         int exp_offset, val_bias, res_bias;
1203
1204         if (result == NULL) result = calc_buffer;
1205         temp = alloca(value_size);
1206
1207         if (value->desc.exponent_size == exp_size && value->desc.mantissa_size == mant_size) {
1208                 if (value != result)
1209                         memcpy(result, value, calc_buffer_size);
1210                 return result;
1211         }
1212
1213         if (value->desc.clss == NAN) {
1214                 if (sc_get_highest_set_bit(_mant(value)) == value->desc.mantissa_size + 1)
1215                         return fc_get_qnan(exp_size, mant_size, result);
1216                 else
1217                         return fc_get_snan(exp_size, mant_size, result);
1218         }
1219
1220         /* set the descriptor of the new value */
1221         result->desc.exponent_size = exp_size;
1222         result->desc.mantissa_size = mant_size;
1223         result->desc.clss = value->desc.clss;
1224
1225         result->sign = value->sign;
1226
1227         /* when the mantissa sizes differ normalizing has to shift to align it.
1228          * this would change the exponent, which is unwanted. So calculate this
1229          * offset and add it */
1230         val_bias = (1 << (value->desc.exponent_size - 1)) - 1;
1231         res_bias = (1 << (exp_size - 1)) - 1;
1232
1233         exp_offset = (res_bias - val_bias) - (value->desc.mantissa_size - mant_size);
1234         sc_val_from_long(exp_offset, temp);
1235         sc_add(_exp(value), temp, _exp(result));
1236
1237         /* _normalize expects normalized radix point */
1238         if (value->desc.clss == SUBNORMAL) {
1239                 sc_val_from_ulong(1, NULL);
1240                 _shift_left(_mant(value), sc_get_buffer(), _mant(result));
1241         } else if (value != result) {
1242                 memcpy(_mant(result), _mant(value), value_size);
1243         } else {
1244                 memmove(_mant(result), _mant(value), value_size);
1245         }
1246
1247         normalize(result, result, 0);
1248         TRACEPRINTF(("Cast results in %s\n", fc_print(result, temp, value_size, FC_PACKED)));
1249         return result;
1250 }
1251
1252 fp_value *fc_get_max(unsigned int exponent_size, unsigned int mantissa_size, fp_value *result) {
1253         if (result == NULL) result = calc_buffer;
1254
1255         result->desc.exponent_size = exponent_size;
1256         result->desc.mantissa_size = mantissa_size;
1257         result->desc.clss = NORMAL;
1258
1259         result->sign = 0;
1260
1261         sc_val_from_ulong((1<<exponent_size) - 2, _exp(result));
1262
1263         sc_max_from_bits(mantissa_size + 1, 0, _mant(result));
1264         sc_val_from_ulong(2, NULL);
1265         _shift_left(_mant(result), sc_get_buffer(), _mant(result));
1266
1267         return result;
1268 }
1269
1270 fp_value *fc_get_min(unsigned int exponent_size, unsigned int mantissa_size, fp_value *result) {
1271         if (result == NULL) result = calc_buffer;
1272
1273         fc_get_max(exponent_size, mantissa_size, result);
1274         result->sign = 1;
1275
1276         return result;
1277 }
1278
1279 fp_value *fc_get_snan(unsigned int exponent_size, unsigned int mantissa_size, fp_value *result) {
1280         if (result == NULL) result = calc_buffer;
1281
1282         result->desc.exponent_size = exponent_size;
1283         result->desc.mantissa_size = mantissa_size;
1284         result->desc.clss = NAN;
1285
1286         result->sign = 0;
1287
1288         sc_val_from_ulong((1<<exponent_size)-1, _exp(result));
1289
1290         /* signaling NaN has non-zero mantissa with msb not set */
1291         sc_val_from_ulong(1, _mant(result));
1292
1293         return result;
1294 }
1295
1296 fp_value *fc_get_qnan(unsigned int exponent_size, unsigned int mantissa_size, fp_value *result) {
1297         if (result == NULL) result = calc_buffer;
1298
1299         result->desc.exponent_size = exponent_size;
1300         result->desc.mantissa_size = mantissa_size;
1301         result->desc.clss = NAN;
1302
1303         result->sign = 0;
1304
1305         sc_val_from_ulong((1<<exponent_size)-1, _exp(result));
1306
1307         /* quiet NaN has the msb of the mantissa set, so shift one there */
1308         sc_val_from_ulong(1, _mant(result));
1309         /* mantissa_size >+< 1 because of two extra rounding bits */
1310         sc_val_from_ulong(mantissa_size + 1, NULL);
1311         _shift_left(_mant(result), sc_get_buffer(), _mant(result));
1312
1313         return result;
1314 }
1315
1316 fp_value *fc_get_plusinf(unsigned int exponent_size, unsigned int mantissa_size, fp_value *result) {
1317         if (result == NULL) result = calc_buffer;
1318
1319         result->desc.exponent_size = exponent_size;
1320         result->desc.mantissa_size = mantissa_size;
1321         result->desc.clss = NORMAL;
1322
1323         result->sign = 0;
1324
1325         sc_val_from_ulong((1<<exponent_size)-1, _exp(result));
1326
1327         sc_val_from_ulong(0, _mant(result));
1328
1329         return result;
1330 }
1331
1332 fp_value *fc_get_minusinf(unsigned int exponent_size, unsigned int mantissa_size, fp_value *result) {
1333         if (result == NULL) result = calc_buffer;
1334
1335         fc_get_plusinf(exponent_size, mantissa_size, result);
1336         result->sign = 1;
1337
1338         return result;
1339 }
1340
1341 int fc_comp(const fp_value *val_a, const fp_value *val_b) {
1342         int mul = 1;
1343
1344         /*
1345          * shortcut: if both values are identical, they are either
1346          * Unordered if NaN or equal
1347          */
1348         if (val_a == val_b)
1349                 return val_a->desc.clss == NAN ? 2 : 0;
1350
1351         /* unordered if one is a NaN */
1352         if (val_a->desc.clss == NAN || val_b->desc.clss == NAN)
1353                 return 2;
1354
1355         /* zero is equal independent of sign */
1356         if ((val_a->desc.clss == ZERO) && (val_b->desc.clss == ZERO))
1357                 return 0;
1358
1359         /* different signs make compare easy */
1360         if (val_a->sign != val_b->sign)
1361                 return (val_a->sign == 0) ? (1) : (-1);
1362
1363         mul = val_a->sign ? -1 : 1;
1364
1365         /* both infinity means equality */
1366         if ((val_a->desc.clss == INF) && (val_b->desc.clss == INF))
1367                 return 0;
1368
1369         /* infinity is bigger than the rest */
1370         if (val_a->desc.clss == INF)
1371                 return  1 * mul;
1372         if (val_b->desc.clss == INF)
1373                 return -1 * mul;
1374
1375         /* check first exponent, that mantissa if equal */
1376         switch (sc_comp(_exp(val_a), _exp(val_b))) {
1377         case -1:
1378                 return -1 * mul;
1379         case  1:
1380                 return  1 * mul;
1381         case  0:
1382                 return sc_comp(_mant(val_a), _mant(val_b)) * mul;
1383         default:
1384                 return 2;
1385         }
1386 }
1387
1388 int fc_is_zero(const fp_value *a) {
1389         return a->desc.clss == ZERO;
1390 }
1391
1392 int fc_is_negative(const fp_value *a) {
1393         return a->sign;
1394 }
1395
1396 int fc_is_inf(const fp_value *a) {
1397         return a->desc.clss == INF;
1398 }
1399
1400 int fc_is_nan(const fp_value *a) {
1401         return a->desc.clss == NAN;
1402 }
1403
1404 int fc_is_subnormal(const fp_value *a) {
1405         return a->desc.clss == SUBNORMAL;
1406 }
1407
1408 char *fc_print(const fp_value *val, char *buf, int buflen, unsigned base) {
1409         char *mul_1;
1410
1411         mul_1 = alloca(calc_buffer_size);
1412
1413         switch (base) {
1414         case FC_DEC:
1415                 switch (val->desc.clss) {
1416                 case INF:
1417                         if (buflen >= 8 + val->sign) sprintf(buf, "%sINFINITY", val->sign ? "-":"");
1418                         else snprintf(buf, buflen, "%sINF", val->sign ? "-":NULL);
1419                         break;
1420                 case NAN:
1421                         snprintf(buf, buflen, "NAN");
1422                         break;
1423                 case ZERO:
1424                         snprintf(buf, buflen, "0.0");
1425                         break;
1426                 default:
1427                         /* XXX to be implemented */
1428 #ifdef HAVE_LONG_DOUBLE
1429                         /* XXX 30 is arbitrary */
1430                         snprintf(buf, buflen, "%.30LE", fc_val_to_ieee754(val));
1431 #else
1432                         snprintf(buf, buflen, "%.18E", fc_val_to_ieee754(val));
1433 #endif
1434                 }
1435                 break;
1436
1437         case FC_HEX:
1438                 switch (val->desc.clss) {
1439                 case INF:
1440                         if (buflen >= 8+val->sign) sprintf(buf, "%sINFINITY", val->sign?"-":"");
1441                         else snprintf(buf, buflen, "%sINF", val->sign?"-":NULL);
1442                         break;
1443                 case NAN:
1444                         snprintf(buf, buflen, "NAN");
1445                         break;
1446                 case ZERO:
1447                         snprintf(buf, buflen, "0.0");
1448                         break;
1449                 default:
1450 #ifdef HAVE_LONG_DOUBLE
1451                         snprintf(buf, buflen, "%LA", fc_val_to_ieee754(val));
1452 #else
1453                         snprintf(buf, buflen, "%A", fc_val_to_ieee754(val));
1454 #endif
1455                 }
1456                 break;
1457
1458         case FC_PACKED:
1459         default:
1460                 snprintf(buf, buflen, "%s", sc_print(pack(val, mul_1), value_size*4, SC_HEX, 0));
1461                 buf[buflen - 1] = '\0';
1462                 break;
1463         }
1464         return buf;
1465 }
1466
1467 unsigned char fc_sub_bits(const fp_value *value, unsigned num_bits, unsigned byte_ofs) {
1468         /* this is used to cache the packed version of the value */
1469         static char *packed_value = NULL;
1470
1471         if (packed_value == NULL) packed_value = xmalloc(value_size);
1472
1473         if (value != NULL)
1474                 pack(value, packed_value);
1475
1476         return sc_sub_bits(packed_value, num_bits, byte_ofs);
1477 }
1478
1479 int fc_zero_mantissa(const fp_value *value) {
1480         return sc_get_lowest_set_bit(_mant(value)) == 2 + value->desc.mantissa_size;
1481 }
1482
1483 int fc_get_exponent(const fp_value *value) {
1484         int exp_bias = (1 << (value->desc.exponent_size - 1)) - 1;
1485         return sc_val_to_long(_exp(value)) - exp_bias;
1486 }
1487
1488
1489 fc_rounding_mode_t fc_set_rounding_mode(fc_rounding_mode_t mode) {
1490         if (mode == FC_TONEAREST || mode == FC_TOPOSITIVE || mode == FC_TONEGATIVE || mode == FC_TOZERO)
1491                 rounding_mode = mode;
1492
1493         return rounding_mode;
1494 }
1495
1496 fc_rounding_mode_t fc_get_rounding_mode(void) {
1497         return rounding_mode;
1498 }
1499
1500 void init_fltcalc(int precision) {
1501         if (calc_buffer == NULL) {
1502                 /* does nothing if already init */
1503                 if (precision == 0) precision = FC_DEFAULT_PRECISION;
1504
1505                 init_strcalc(precision + 4);
1506
1507                 /* needs additionally two bits to round, a bit as explicit 1., and one for
1508                  * addition overflow */
1509                 max_precision = sc_get_precision() - 4;
1510                 if (max_precision < precision)
1511                         printf("WARNING: not enough precision available, using %d\n", max_precision);
1512
1513                 rounding_mode    = FC_TONEAREST;
1514                 value_size       = sc_get_buffer_length();
1515                 calc_buffer_size = sizeof(fp_value) + 2*value_size - 1;
1516
1517                 calc_buffer = xmalloc(calc_buffer_size);
1518                 memset(calc_buffer, 0, calc_buffer_size);
1519                 DEBUGPRINTF(("init fltcalc:\n\tVALUE_SIZE = %d\ntCALC_BUFFER_SIZE = %d\n\tcalc_buffer = %p\n\n", value_size, calc_buffer_size, calc_buffer));
1520 #ifdef HAVE_LONG_DOUBLE
1521                 DEBUGPRINTF(("\tUsing long double (1-15-64) interface\n"));
1522 #else
1523                 DEBUGPRINTF(("\tUsing double (1-11-52) interface\n"));
1524 #endif
1525 #ifdef WORDS_BIGENDIAN
1526                 DEBUGPRINTF(("\tWord order is big endian\n\n"));
1527 #else
1528                 DEBUGPRINTF(("\tWord order is little endian\n\n"));
1529 #endif
1530         }
1531 }
1532
1533 void finish_fltcalc (void) {
1534         free(calc_buffer); calc_buffer = NULL;
1535 }
1536
1537 #ifdef FLTCALC_TRACE_CALC
1538 static char buffer[100];
1539 #endif
1540
1541 /* definition of interface functions */
1542 fp_value *fc_add(const fp_value *a, const fp_value *b, fp_value *result) {
1543         if (result == NULL) result = calc_buffer;
1544
1545         TRACEPRINTF(("%s ", fc_print(a, buffer, sizeof(buffer), FC_PACKED)));
1546         TRACEPRINTF(("+ %s ", fc_print(b, buffer, sizeof(buffer), FC_PACKED)));
1547
1548         /* make the value with the bigger exponent the first one */
1549         if (sc_comp(_exp(a), _exp(b)) == -1)
1550                 _fadd(b, a, result);
1551         else
1552                 _fadd(a, b, result);
1553
1554         TRACEPRINTF(("= %s\n", fc_print(result, buffer, sizeof(buffer), FC_PACKED)));
1555         return result;
1556 }
1557
1558 fp_value *fc_sub(const fp_value *a, const fp_value *b, fp_value *result) {
1559         fp_value *temp;
1560
1561         if (result == NULL) result = calc_buffer;
1562
1563         TRACEPRINTF(("%s ", fc_print(a, buffer, sizeof(buffer), FC_PACKED)));
1564         TRACEPRINTF(("- %s ", fc_print(b, buffer, sizeof(buffer), FC_PACKED)));
1565
1566         temp = alloca(calc_buffer_size);
1567         memcpy(temp, b, calc_buffer_size);
1568         temp->sign = !b->sign;
1569         if (sc_comp(_exp(a), _exp(temp)) == -1)
1570                 _fadd(temp, a, result);
1571         else
1572                 _fadd(a, temp, result);
1573
1574         TRACEPRINTF(("= %s\n", fc_print(result, buffer, sizeof(buffer), FC_PACKED)));
1575         return result;
1576 }
1577
1578 fp_value *fc_mul(const fp_value *a, const fp_value *b, fp_value *result) {
1579         if (result == NULL) result = calc_buffer;
1580
1581         TRACEPRINTF(("%s ", fc_print(a, buffer, sizeof(buffer), FC_PACKED)));
1582         TRACEPRINTF(("* %s ", fc_print(b, buffer, sizeof(buffer), FC_PACKED)));
1583
1584         _fmul(a, b, result);
1585
1586         TRACEPRINTF(("= %s\n", fc_print(result, buffer, sizeof(buffer), FC_PACKED)));
1587         return result;
1588 }
1589
1590 fp_value *fc_div(const fp_value *a, const fp_value *b, fp_value *result) {
1591         if (result == NULL) result = calc_buffer;
1592
1593         TRACEPRINTF(("%s ", fc_print(a, buffer, sizeof(buffer), FC_PACKED)));
1594         TRACEPRINTF(("/ %s ", fc_print(b, buffer, sizeof(buffer), FC_PACKED)));
1595
1596         _fdiv(a, b, result);
1597
1598         TRACEPRINTF(("= %s\n", fc_print(result, buffer, sizeof(buffer), FC_PACKED)));
1599         return result;
1600 }
1601
1602 fp_value *fc_neg(const fp_value *a, fp_value *result) {
1603         if (result == NULL) result = calc_buffer;
1604
1605         TRACEPRINTF(("- %s ", fc_print(a, buffer, sizeof(buffer), FC_PACKED)));
1606
1607         if (a != result)
1608                 memcpy(result, a, calc_buffer_size);
1609         result->sign = !a->sign;
1610
1611         TRACEPRINTF(("= %s\n", fc_print(result, buffer, sizeof(buffer), FC_PACKED)));
1612         return result;
1613 }
1614
1615 fp_value *fc_int(const fp_value *a, fp_value *result) {
1616         if (result == NULL) result = calc_buffer;
1617
1618         TRACEPRINTF(("%s ", fc_print(a, buffer, sizeof(buffer), FC_PACKED)));
1619         TRACEPRINTF(("truncated to integer "));
1620
1621         _trunc(a, result);
1622
1623         TRACEPRINTF(("= %s\n", fc_print(result, buffer, sizeof(buffer), FC_PACKED)));
1624         return result;
1625 }
1626
1627 fp_value *fc_rnd(const fp_value *a, fp_value *result) {
1628         if (result == NULL) result = calc_buffer;
1629
1630         TRACEPRINTF(("%s ", fc_print(a, buffer, sizeof(buffer), FC_PACKED)));
1631         TRACEPRINTF(("rounded to integer "));
1632
1633         assert(!"fc_rnd() not yet implemented");
1634
1635         TRACEPRINTF(("= %s\n", fc_print(result, buffer, sizeof(buffer), FC_PACKED)));
1636         return result;
1637 }
1638
1639 unsigned fc_set_immediate_precision(unsigned bits) {
1640         unsigned old = immediate_prec;
1641
1642         immediate_prec = bits;
1643         return old;
1644 }
1645
1646 int fc_is_exact(void) {
1647         return fc_exact;
1648 }