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