Protect buffer[] by #ifdef FLTCALC_TRACE_CALC. It is only used when this macro is...
[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         /* set the descriptor of the new value */
1214         result->desc.exponent_size = exp_size;
1215         result->desc.mantissa_size = mant_size;
1216         result->desc.clss = value->desc.clss;
1217
1218         result->sign = value->sign;
1219
1220         /* when the mantissa sizes differ normalizing has to shift to align it.
1221          * this would change the exponent, which is unwanted. So calculate this
1222          * offset and add it */
1223         val_bias = (1 << (value->desc.exponent_size - 1)) - 1;
1224         res_bias = (1 << (exp_size - 1)) - 1;
1225
1226         exp_offset = (res_bias - val_bias) - (value->desc.mantissa_size - mant_size);
1227         sc_val_from_long(exp_offset, temp);
1228         sc_add(_exp(value), temp, _exp(result));
1229
1230         /* _normalize expects normalized radix point */
1231         if (value->desc.clss == SUBNORMAL) {
1232                 sc_val_from_ulong(1, NULL);
1233                 _shift_left(_mant(value), sc_get_buffer(), _mant(result));
1234         } else if (value != result) {
1235                 memcpy(_mant(result), _mant(value), value_size);
1236         } else {
1237                 memmove(_mant(result), _mant(value), value_size);
1238         }
1239
1240         normalize(result, result, 0);
1241         TRACEPRINTF(("Cast results in %s\n", fc_print(result, temp, value_size, FC_PACKED)));
1242         return result;
1243 }
1244
1245 fp_value *fc_get_max(unsigned int exponent_size, unsigned int mantissa_size, fp_value *result) {
1246         if (result == NULL) result = calc_buffer;
1247
1248         result->desc.exponent_size = exponent_size;
1249         result->desc.mantissa_size = mantissa_size;
1250         result->desc.clss = NORMAL;
1251
1252         result->sign = 0;
1253
1254         sc_val_from_ulong((1<<exponent_size) - 2, _exp(result));
1255
1256         sc_max_from_bits(mantissa_size + 1, 0, _mant(result));
1257         sc_val_from_ulong(2, NULL);
1258         _shift_left(_mant(result), sc_get_buffer(), _mant(result));
1259
1260         return result;
1261 }
1262
1263 fp_value *fc_get_min(unsigned int exponent_size, unsigned int mantissa_size, fp_value *result) {
1264         if (result == NULL) result = calc_buffer;
1265
1266         fc_get_max(exponent_size, mantissa_size, result);
1267         result->sign = 1;
1268
1269         return result;
1270 }
1271
1272 fp_value *fc_get_snan(unsigned int exponent_size, unsigned int mantissa_size, fp_value *result) {
1273         if (result == NULL) result = calc_buffer;
1274
1275         result->desc.exponent_size = exponent_size;
1276         result->desc.mantissa_size = mantissa_size;
1277         result->desc.clss = NAN;
1278
1279         result->sign = 0;
1280
1281         sc_val_from_ulong((1<<exponent_size)-1, _exp(result));
1282
1283         /* signaling NaN has non-zero mantissa with msb not set */
1284         sc_val_from_ulong(1, _mant(result));
1285
1286         return result;
1287 }
1288
1289 fp_value *fc_get_qnan(unsigned int exponent_size, unsigned int mantissa_size, fp_value *result) {
1290         if (result == NULL) result = calc_buffer;
1291
1292         result->desc.exponent_size = exponent_size;
1293         result->desc.mantissa_size = mantissa_size;
1294         result->desc.clss = NAN;
1295
1296         result->sign = 0;
1297
1298         sc_val_from_ulong((1<<exponent_size)-1, _exp(result));
1299
1300         /* quiet NaN has the msb of the mantissa set, so shift one there */
1301         sc_val_from_ulong(1, _mant(result));
1302         /* mantissa_size >+< 1 because of two extra rounding bits */
1303         sc_val_from_ulong(mantissa_size + 1, NULL);
1304         _shift_left(_mant(result), sc_get_buffer(), _mant(result));
1305
1306         return result;
1307 }
1308
1309 fp_value *fc_get_plusinf(unsigned int exponent_size, unsigned int mantissa_size, fp_value *result) {
1310         if (result == NULL) result = calc_buffer;
1311
1312         result->desc.exponent_size = exponent_size;
1313         result->desc.mantissa_size = mantissa_size;
1314         result->desc.clss = NORMAL;
1315
1316         result->sign = 0;
1317
1318         sc_val_from_ulong((1<<exponent_size)-1, _exp(result));
1319
1320         sc_val_from_ulong(0, _mant(result));
1321
1322         return result;
1323 }
1324
1325 fp_value *fc_get_minusinf(unsigned int exponent_size, unsigned int mantissa_size, fp_value *result) {
1326         if (result == NULL) result = calc_buffer;
1327
1328         fc_get_plusinf(exponent_size, mantissa_size, result);
1329         result->sign = 1;
1330
1331         return result;
1332 }
1333
1334 int fc_comp(const fp_value *val_a, const fp_value *val_b) {
1335         int mul = 1;
1336
1337         /*
1338          * shortcut: if both values are identical, they are either
1339          * Unordered if NaN or equal
1340          */
1341         if (val_a == val_b)
1342                 return val_a->desc.clss == NAN ? 2 : 0;
1343
1344         /* unordered if one is a NaN */
1345         if (val_a->desc.clss == NAN || val_b->desc.clss == NAN)
1346                 return 2;
1347
1348         /* zero is equal independent of sign */
1349         if ((val_a->desc.clss == ZERO) && (val_b->desc.clss == ZERO))
1350                 return 0;
1351
1352         /* different signs make compare easy */
1353         if (val_a->sign != val_b->sign)
1354                 return (val_a->sign == 0) ? (1) : (-1);
1355
1356         mul = val_a->sign ? -1 : 1;
1357
1358         /* both infinity means equality */
1359         if ((val_a->desc.clss == INF) && (val_b->desc.clss == INF))
1360                 return 0;
1361
1362         /* infinity is bigger than the rest */
1363         if (val_a->desc.clss == INF)
1364                 return  1 * mul;
1365         if (val_b->desc.clss == INF)
1366                 return -1 * mul;
1367
1368         /* check first exponent, that mantissa if equal */
1369         switch (sc_comp(_exp(val_a), _exp(val_b))) {
1370         case -1:
1371                 return -1 * mul;
1372         case  1:
1373                 return  1 * mul;
1374         case  0:
1375                 return sc_comp(_mant(val_a), _mant(val_b)) * mul;
1376         default:
1377                 return 2;
1378         }
1379 }
1380
1381 int fc_is_zero(const fp_value *a) {
1382         return a->desc.clss == ZERO;
1383 }
1384
1385 int fc_is_negative(const fp_value *a) {
1386         return a->sign;
1387 }
1388
1389 int fc_is_inf(const fp_value *a) {
1390         return a->desc.clss == INF;
1391 }
1392
1393 int fc_is_nan(const fp_value *a) {
1394         return a->desc.clss == NAN;
1395 }
1396
1397 int fc_is_subnormal(const fp_value *a) {
1398         return a->desc.clss == SUBNORMAL;
1399 }
1400
1401 char *fc_print(const fp_value *val, char *buf, int buflen, unsigned base) {
1402         char *mul_1;
1403
1404         mul_1 = alloca(calc_buffer_size);
1405
1406         switch (base) {
1407         case FC_DEC:
1408                 switch (val->desc.clss) {
1409                 case INF:
1410                         if (buflen >= 8 + val->sign) sprintf(buf, "%sINFINITY", val->sign ? "-":"");
1411                         else snprintf(buf, buflen, "%sINF", val->sign ? "-":NULL);
1412                         break;
1413                 case NAN:
1414                         snprintf(buf, buflen, "NAN");
1415                         break;
1416                 case ZERO:
1417                         snprintf(buf, buflen, "0.0");
1418                         break;
1419                 default:
1420                         /* XXX to be implemented */
1421 #ifdef HAVE_LONG_DOUBLE
1422                         /* XXX 30 is arbitrary */
1423                         snprintf(buf, buflen, "%.30LE", fc_val_to_ieee754(val));
1424 #else
1425                         snprintf(buf, buflen, "%.18E", fc_val_to_ieee754(val));
1426 #endif
1427                 }
1428                 break;
1429
1430         case FC_HEX:
1431                 switch (val->desc.clss) {
1432                 case INF:
1433                         if (buflen >= 8+val->sign) sprintf(buf, "%sINFINITY", val->sign?"-":"");
1434                         else snprintf(buf, buflen, "%sINF", val->sign?"-":NULL);
1435                         break;
1436                 case NAN:
1437                         snprintf(buf, buflen, "NAN");
1438                         break;
1439                 case ZERO:
1440                         snprintf(buf, buflen, "0.0");
1441                         break;
1442                 default:
1443 #ifdef HAVE_LONG_DOUBLE
1444                         snprintf(buf, buflen, "%LA", fc_val_to_ieee754(val));
1445 #else
1446                         snprintf(buf, buflen, "%A", fc_val_to_ieee754(val));
1447 #endif
1448                 }
1449                 break;
1450
1451         case FC_PACKED:
1452         default:
1453                 snprintf(buf, buflen, "%s", sc_print(pack(val, mul_1), value_size*4, SC_HEX, 0));
1454                 buf[buflen - 1] = '\0';
1455                 break;
1456         }
1457         return buf;
1458 }
1459
1460 unsigned char fc_sub_bits(const fp_value *value, unsigned num_bits, unsigned byte_ofs) {
1461         /* this is used to cache the packed version of the value */
1462         static char *packed_value = NULL;
1463
1464         if (packed_value == NULL) packed_value = xmalloc(value_size);
1465
1466         if (value != NULL)
1467                 pack(value, packed_value);
1468
1469         return sc_sub_bits(packed_value, num_bits, byte_ofs);
1470 }
1471
1472 int fc_zero_mantissa(const fp_value *value) {
1473         return sc_get_lowest_set_bit(_mant(value)) == 2 + value->desc.mantissa_size;
1474 }
1475
1476 int fc_get_exponent(const fp_value *value) {
1477         int exp_bias = (1 << (value->desc.exponent_size - 1)) - 1;
1478         return sc_val_to_long(_exp(value)) - exp_bias;
1479 }
1480
1481
1482 fc_rounding_mode_t fc_set_rounding_mode(fc_rounding_mode_t mode) {
1483         if (mode == FC_TONEAREST || mode == FC_TOPOSITIVE || mode == FC_TONEGATIVE || mode == FC_TOZERO)
1484                 rounding_mode = mode;
1485
1486         return rounding_mode;
1487 }
1488
1489 fc_rounding_mode_t fc_get_rounding_mode(void) {
1490         return rounding_mode;
1491 }
1492
1493 void init_fltcalc(int precision) {
1494         if (calc_buffer == NULL) {
1495                 /* does nothing if already init */
1496                 if (precision == 0) precision = FC_DEFAULT_PRECISION;
1497
1498                 init_strcalc(precision + 4);
1499
1500                 /* needs additionally two bits to round, a bit as explicit 1., and one for
1501                  * addition overflow */
1502                 max_precision = sc_get_precision() - 4;
1503                 if (max_precision < precision)
1504                         printf("WARNING: not enough precision available, using %d\n", max_precision);
1505
1506                 rounding_mode    = FC_TONEAREST;
1507                 value_size       = sc_get_buffer_length();
1508                 calc_buffer_size = sizeof(fp_value) + 2*value_size - 1;
1509
1510                 calc_buffer = xmalloc(calc_buffer_size);
1511                 memset(calc_buffer, 0, calc_buffer_size);
1512                 DEBUGPRINTF(("init fltcalc:\n\tVALUE_SIZE = %d\ntCALC_BUFFER_SIZE = %d\n\tcalc_buffer = %p\n\n", value_size, calc_buffer_size, calc_buffer));
1513 #ifdef HAVE_LONG_DOUBLE
1514                 DEBUGPRINTF(("\tUsing long double (1-15-64) interface\n"));
1515 #else
1516                 DEBUGPRINTF(("\tUsing double (1-11-52) interface\n"));
1517 #endif
1518 #ifdef WORDS_BIGENDIAN
1519                 DEBUGPRINTF(("\tWord order is big endian\n\n"));
1520 #else
1521                 DEBUGPRINTF(("\tWord order is little endian\n\n"));
1522 #endif
1523         }
1524 }
1525
1526 void finish_fltcalc (void) {
1527         free(calc_buffer); calc_buffer = NULL;
1528 }
1529
1530 #ifdef FLTCALC_TRACE_CALC
1531 static char buffer[100];
1532 #endif
1533
1534 /* definition of interface functions */
1535 fp_value *fc_add(const fp_value *a, const fp_value *b, fp_value *result) {
1536         if (result == NULL) result = calc_buffer;
1537
1538         TRACEPRINTF(("%s ", fc_print(a, buffer, sizeof(buffer), FC_PACKED)));
1539         TRACEPRINTF(("+ %s ", fc_print(b, buffer, sizeof(buffer), FC_PACKED)));
1540
1541         /* make the value with the bigger exponent the first one */
1542         if (sc_comp(_exp(a), _exp(b)) == -1)
1543                 _fadd(b, a, result);
1544         else
1545                 _fadd(a, b, result);
1546
1547         TRACEPRINTF(("= %s\n", fc_print(result, buffer, sizeof(buffer), FC_PACKED)));
1548         return result;
1549 }
1550
1551 fp_value *fc_sub(const fp_value *a, const fp_value *b, fp_value *result) {
1552         fp_value *temp;
1553
1554         if (result == NULL) result = calc_buffer;
1555
1556         TRACEPRINTF(("%s ", fc_print(a, buffer, sizeof(buffer), FC_PACKED)));
1557         TRACEPRINTF(("- %s ", fc_print(b, buffer, sizeof(buffer), FC_PACKED)));
1558
1559         temp = alloca(calc_buffer_size);
1560         memcpy(temp, b, calc_buffer_size);
1561         temp->sign = !b->sign;
1562         if (sc_comp(_exp(a), _exp(temp)) == -1)
1563                 _fadd(temp, a, result);
1564         else
1565                 _fadd(a, temp, result);
1566
1567         TRACEPRINTF(("= %s\n", fc_print(result, buffer, sizeof(buffer), FC_PACKED)));
1568         return result;
1569 }
1570
1571 fp_value *fc_mul(const fp_value *a, const fp_value *b, fp_value *result) {
1572         if (result == NULL) result = calc_buffer;
1573
1574         TRACEPRINTF(("%s ", fc_print(a, buffer, sizeof(buffer), FC_PACKED)));
1575         TRACEPRINTF(("* %s ", fc_print(b, buffer, sizeof(buffer), FC_PACKED)));
1576
1577         _fmul(a, b, result);
1578
1579         TRACEPRINTF(("= %s\n", fc_print(result, buffer, sizeof(buffer), FC_PACKED)));
1580         return result;
1581 }
1582
1583 fp_value *fc_div(const fp_value *a, const fp_value *b, fp_value *result) {
1584         if (result == NULL) result = calc_buffer;
1585
1586         TRACEPRINTF(("%s ", fc_print(a, buffer, sizeof(buffer), FC_PACKED)));
1587         TRACEPRINTF(("/ %s ", fc_print(b, buffer, sizeof(buffer), FC_PACKED)));
1588
1589         _fdiv(a, b, result);
1590
1591         TRACEPRINTF(("= %s\n", fc_print(result, buffer, sizeof(buffer), FC_PACKED)));
1592         return result;
1593 }
1594
1595 fp_value *fc_neg(const fp_value *a, fp_value *result) {
1596         if (result == NULL) result = calc_buffer;
1597
1598         TRACEPRINTF(("- %s ", fc_print(a, buffer, sizeof(buffer), FC_PACKED)));
1599
1600         if (a != result)
1601                 memcpy(result, a, calc_buffer_size);
1602         result->sign = !a->sign;
1603
1604         TRACEPRINTF(("= %s\n", fc_print(result, buffer, sizeof(buffer), FC_PACKED)));
1605         return result;
1606 }
1607
1608 fp_value *fc_int(const fp_value *a, fp_value *result) {
1609         if (result == NULL) result = calc_buffer;
1610
1611         TRACEPRINTF(("%s ", fc_print(a, buffer, sizeof(buffer), FC_PACKED)));
1612         TRACEPRINTF(("truncated to integer "));
1613
1614         _trunc(a, result);
1615
1616         TRACEPRINTF(("= %s\n", fc_print(result, buffer, sizeof(buffer), FC_PACKED)));
1617         return result;
1618 }
1619
1620 fp_value *fc_rnd(const fp_value *a, fp_value *result) {
1621         if (result == NULL) result = calc_buffer;
1622
1623         TRACEPRINTF(("%s ", fc_print(a, buffer, sizeof(buffer), FC_PACKED)));
1624         TRACEPRINTF(("rounded to integer "));
1625
1626         assert(!"fc_rnd() not yet implemented");
1627
1628         TRACEPRINTF(("= %s\n", fc_print(result, buffer, sizeof(buffer), FC_PACKED)));
1629         return result;
1630 }
1631
1632 unsigned fc_set_immediate_precision(unsigned bits) {
1633         unsigned old = immediate_prec;
1634
1635         immediate_prec = bits;
1636         return old;
1637 }
1638
1639 int fc_is_exact(void) {
1640         return fc_exact;
1641 }