*** empty log message ***
[libfirm] / ir / tv / fltcalc.c
1 /* fltcalc.c
2  * Authors: Matthias Heil
3  */
4
5 #include "fltcalc.h"
6 #include "ieee754.h"
7 #include <string.h>
8 #include <float.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11
12 /********
13  * globals
14  ********/
15 static long double value;
16
17 #define CAST_IN(val) (*((long double *)((val))))
18 #define CAST_OUT(val) ((void *)&(val))
19
20 #define CLEAR_BUFFER() memset((char*)&value, 0, sizeof(long double))
21 /********
22  * private functions
23  ********/
24
25 /********
26  * functions defined in fltcalc.h
27  ********/
28 const void *fc_get_buffer(void)
29 {
30   return CAST_OUT(value);
31 }
32
33 const int fc_get_buffer_length(void)
34 {
35   return sizeof(long double);
36 }
37
38 void fc_val_from_str(const char *str, unsigned int len)
39 {
40   CLEAR_BUFFER();
41   value = strtold(str, NULL);
42 }
43
44 void fc_val_from_float(long double l)
45 {
46   CLEAR_BUFFER();
47   value = l;
48 }
49
50 long double fc_val_to_float(const void *val)
51 {
52   return CAST_IN(val);
53 }
54
55 void fc_get_min(unsigned int num_bits)
56 {
57   CLEAR_BUFFER();
58   switch (num_bits)
59   {
60     case 32:
61       value = FLT_MIN;
62       break;
63     case 64:
64       value = DBL_MIN;
65       break;
66     case 80:
67     default:
68       value = LDBL_MIN;
69       break;
70   }
71 }
72
73 void fc_get_max(unsigned int num_bits)
74 {
75   CLEAR_BUFFER();
76   switch (num_bits)
77   {
78     case 32:
79       value = FLT_MAX;
80       break;
81     case 64:
82       value = DBL_MAX;
83       break;
84     case 80:
85     default:
86       value = LDBL_MAX;
87       break;
88   }
89 }
90
91 void fc_get_nan(void)
92 {
93   /* nan: all exponent bit set, non-zero mantissa. not signalling wheni
94    * msb of mantissa is set (easily found using this struct */
95   union ieee854_long_double ld;
96
97   CLEAR_BUFFER();
98   ld.ieee_nan.negative = 0;
99   ld.ieee_nan.exponent = 0x7FFF;
100   ld.ieee_nan.quiet_nan = 1;
101   ld.ieee_nan.mantissa0 = 42;
102
103   value = ld.d;
104 }
105
106 void fc_get_inf(void)
107 {
108   /* +-inf: all exponent bit set, sign is easy, one is strange XXX */
109   union ieee854_long_double ld;
110
111   CLEAR_BUFFER();
112   ld.ieee_nan.negative = 0;
113   ld.ieee_nan.exponent = 0x7FFF;
114   ld.ieee_nan.quiet_nan = 0;
115   ld.ieee_nan.one = 1;
116   ld.ieee_nan.mantissa0 = 0;
117   ld.ieee_nan.mantissa1 = 0;
118
119   value = ld.d;
120 }
121
122 void fc_calc(const void *a, const void *b, int opcode)
123 {
124   CLEAR_BUFFER();
125   switch (opcode)
126   {
127     case FC_ADD:
128       value = CAST_IN(a) + CAST_IN(b);
129       break;
130     case FC_SUB:
131       value = CAST_IN(a) - CAST_IN(b);
132       break;
133     case FC_MUL:
134       value = CAST_IN(a) * CAST_IN(b);
135       break;
136     case FC_DIV:
137       value = CAST_IN(a) / CAST_IN(b);
138       break;
139     case FC_NEG:
140       value = -CAST_IN(a);
141   }
142 }
143
144 int fc_comp(const void *a, const void *b)
145 {
146   if (CAST_IN(a) == CAST_IN(b)) return 0;
147   else return (CAST_IN(a) > CAST_IN(b))?(1):(-1);
148 }
149
150 char *fc_print_dec(const void *a)
151 {
152   static char buf[100];
153
154   snprintf(buf, 100, "%1.30Lg", CAST_IN(a));
155   return buf;
156 }