Changed inf/nan to remove non-partabel ieee754.h file
[libfirm] / ir / tv / fltcalc.c
1 /* fltcalc.c
2  * Authors: Matthias Heil
3  */
4
5 /*
6  * TODO:
7  *
8  * This code uses the C-type long double to respesent floating
9  * point values. This is bad because:
10  *
11  * 1.) It depends on IEEE arithmetic on the compilation engine (hardly a problem)
12  * 2.) The existance on the type and its bits size (may be identical to double or even float)
13  * 3.) Arithmetic operations will be done with "higher order" precision, which might be wrong
14  *
15  * Replace this code ASAP.
16  */
17 #include "fltcalc.h"
18 #include <string.h>
19 #include <float.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22
23 /* only defined in C99 mode */
24 extern long double strtold(const char *str, char **end);
25
26 /********
27  * globals
28  ********/
29 static long double value;
30
31 //#define CAST_IN(val) ({ long double xxx = *(long double *)(val); printf("CAST to %Lg\n", xxx); xxx; })
32
33 #define CAST_IN(val) (*((long double *)((val))))
34 #define CAST_OUT(val) ((void *)&(val))
35
36 #define CLEAR_BUFFER() memset((char*)&value, 0, sizeof(long double))
37 /********
38  * private functions
39  ********/
40
41 /********
42  * functions defined in fltcalc.h
43  ********/
44 const void *fc_get_buffer(void)
45 {
46   return CAST_OUT(value);
47 }
48
49 const int fc_get_buffer_length(void)
50 {
51   return sizeof(long double);
52 }
53
54 void fc_val_from_str(const char *str, unsigned int len)
55 {
56   CLEAR_BUFFER();
57   value = strtold(str, NULL);
58 }
59
60 void fc_val_from_float(long double l)
61 {
62   CLEAR_BUFFER();
63   value = l;
64 }
65
66 long double fc_val_to_float(const void *val)
67 {
68   return CAST_IN(val);
69 }
70
71 void fc_get_min(unsigned int num_bits)
72 {
73   CLEAR_BUFFER();
74   switch (num_bits)
75   {
76     case 32:
77       value = FLT_MIN;
78       break;
79     case 64:
80       value = DBL_MIN;
81       break;
82     case 80:
83     default:
84       value = LDBL_MIN;
85       break;
86   }
87 }
88
89 void fc_get_max(unsigned int num_bits)
90 {
91   CLEAR_BUFFER();
92   switch (num_bits)
93   {
94     case 32:
95       value = FLT_MAX;
96       break;
97     case 64:
98       value = DBL_MAX;
99       break;
100     case 80:
101     default:
102       value = LDBL_MAX;
103       break;
104   }
105 }
106
107 void fc_get_nan(void)
108 {
109   value = strtold("nan", NULL);
110
111 }
112
113 void fc_get_inf(void)
114 {
115   value = strtold("inf", NULL);
116 }
117
118 void fc_calc(const void *a, const void *b, int opcode)
119 {
120   CLEAR_BUFFER();
121   switch (opcode)
122   {
123     case FC_ADD:
124       value = CAST_IN(a) + CAST_IN(b);
125       break;
126     case FC_SUB:
127       value = CAST_IN(a) - CAST_IN(b);
128       break;
129     case FC_MUL:
130       value = CAST_IN(a) * CAST_IN(b);
131       break;
132     case FC_DIV:
133       value = CAST_IN(a) / CAST_IN(b);
134       break;
135     case FC_NEG:
136       value = -CAST_IN(a);
137       break;
138   }
139 }
140
141 int fc_comp(const void *a, const void *b)
142 {
143   if (CAST_IN(a) == CAST_IN(b)) return 0;
144   else return (CAST_IN(a) > CAST_IN(b))?(1):(-1);
145 }
146
147 char *fc_print_dec(const void *a, char *buf, int buflen)
148 {
149   snprintf(buf, buflen, "%1.30Lg", CAST_IN(a));
150   return buf;
151 }
152
153 unsigned char fc_sub_bits(const void *value, unsigned num_bits, unsigned byte_ofs)
154 {
155   long double val = CAST_IN(value);
156   float f;
157   double d;
158
159   unsigned char *p;
160   unsigned len;
161
162   switch (num_bits) {
163   case 32:
164     f = (float)val;
165     p = (unsigned char *)&f;
166     len = 4;
167     break;
168
169   case 64:
170     d = (double)val;
171     p = (unsigned char *)&d;
172     len = 8;
173     break;
174
175   case 80:
176     p = (unsigned char *)&val;
177     len = 10;
178     break;
179
180   default:
181     return 0;
182   }
183
184   if (byte_ofs > len)
185     return 0;
186   return p[byte_ofs];
187 }