6 #include "cln/number.h"
7 #include "cln/malloc.h"
8 #include "base/cl_low.h"
9 #include "float/cl_F.h"
12 #include "base/cl_N.h"
13 #include "float/cl_F.h"
18 typedef uint32 ffloat; // 32-bit float in IEEE format
21 ffloat eksplicit; // explicit value
23 float machine_float; // value as a C `float'
27 #if defined(CL_WIDE_POINTERS)
28 #define FF_value_shift 32
29 inline ffloat cl_ffloat_value (const cl_FF& x)
31 return x.word >> FF_value_shift;
34 struct cl_heap_ffloat : cl_heap {
35 ffloatjanus representation;
37 inline cl_heap_ffloat* TheFfloat (const cl_number& obj)
38 { return (cl_heap_ffloat*)(obj.pointer); }
39 inline ffloat cl_ffloat_value (const cl_FF& x)
41 return TheFfloat(x)->representation.eksplicit;
46 // |..|.......|..........................|
47 // sign exponent mantissa
49 #define FF_exp_len 8 // number of bits in the exponent
50 #define FF_mant_len 23 // number of bits in the mantissa
51 // (excluding the hidden bit)
52 #define FF_exp_low 1 // minimum exponent
53 #define FF_exp_mid 126 // exponent bias
54 #define FF_exp_high 254 // maximum exponent, 255 is NaN/Inf
55 #define FF_exp_shift (FF_mant_len+FF_mant_shift) // lowest exponent bit
56 #define FF_mant_shift 0 // lowest mantissa bit
57 #define FF_sign_shift (32 - 1) // = (FF_exp_len+FF_mant_len)
59 // Private constructor.
60 #if !defined(CL_WIDE_POINTERS)
61 inline cl_FF::cl_FF (cl_heap_ffloat* ptr) : cl_F ((cl_private_thing) ptr) {}
64 extern cl_class cl_class_ffloat;
66 // Builds a float from the explicit word.
67 #if defined(CL_WIDE_POINTERS)
68 inline cl_FF::cl_FF (struct cl_heap_ffloat * null, cl_uint w)
69 : cl_F ((cl_private_thing) w) { unused null; }
70 inline const cl_FF allocate_ffloat (ffloat eksplicit)
72 return cl_FF((struct cl_heap_ffloat *) 0, ((cl_uint)eksplicit << FF_value_shift) | (cl_FF_tag << cl_tag_shift));
75 inline cl_heap_ffloat* allocate_ffloat (ffloat eksplicit)
77 cl_heap_ffloat* p = (cl_heap_ffloat*) malloc_hook(sizeof(cl_heap_ffloat));
79 p->type = &cl_class_ffloat;
80 p->representation.eksplicit = eksplicit;
85 // Builds a float word from sign (0 or -1), exponent and mantissa.
86 inline uint32 make_FF_word (cl_sint sign, unsigned int exp, cl_uint mant)
88 return (sign << FF_sign_shift)
89 | (exp << FF_exp_shift)
90 | ((mant & (bit(FF_mant_len)-1)) << FF_mant_shift);
93 // Builds a float from sign (0 or -1), exponent and mantissa.
94 inline const cl_FF make_FF (cl_sint sign, unsigned int exp, cl_uint mant)
96 return allocate_ffloat(make_FF_word(sign,exp,mant));
99 #if defined(CL_WIDE_POINTERS)
101 #define cl_FF_0 make_FF(0,0,0)
103 #define cl_FF_1 make_FF(0,FF_exp_mid+1,bit(FF_mant_len))
105 #define cl_FF_minus1 make_FF(-1,FF_exp_mid+1,bit(FF_mant_len))
108 extern const cl_FF cl_FF_0;
110 extern const cl_FF cl_FF_1;
112 extern const cl_FF cl_FF_minus1;
116 // Entpacken eines Single-Float:
117 // FF_decode(obj, zero_statement, sign=,exp=,mant=);
118 // zerlegt ein Single-Float obj.
119 // Ist obj=0.0, wird zero_statement ausgeführt.
120 // Sonst: cl_signean sign = Vorzeichen (0 = +, -1 = -),
121 // sintL exp = Exponent (vorzeichenbehaftet),
122 // uintL mant = Mantisse (>= 2^FF_mant_len, < 2^(FF_mant_len+1))
123 #define FF_uexp(x) (((x) >> FF_mant_len) & (bit(FF_exp_len)-1))
124 #define FF_decode(obj, zero_statement, sign_zuweisung,exp_zuweisung,mant_zuweisung) \
125 { var ffloat _x = cl_ffloat_value(obj); \
126 var uintL uexp = FF_uexp(_x); \
128 { zero_statement } /* e=0 -> Zahl 0.0 */ \
130 { exp_zuweisung (sintL)(uexp - FF_exp_mid); /* Exponent */ \
131 unused (sign_zuweisung sign_of((sint32)(_x))); /* Vorzeichen */\
132 mant_zuweisung (bit(FF_mant_len) | (_x & (bit(FF_mant_len)-1))); \
135 // Einpacken eines Single-Float:
136 // encode_FF(sign,exp,mant);
137 // liefert ein Single-Float.
138 // > cl_signean sign: Vorzeichen, 0 für +, -1 für negativ.
139 // > sintL exp: Exponent
140 // > uintL mant: Mantisse, sollte >= 2^FF_mant_len und < 2^(FF_mant_len+1) sein.
141 // < object ergebnis: ein Single-Float
142 // Der Exponent wird auf Überlauf/Unterlauf getestet.
143 inline const cl_FF encode_FF (cl_signean sign, sintL exp, uintL mant)
145 if (exp < (sintL)(FF_exp_low-FF_exp_mid))
146 { if (underflow_allowed())
147 { throw floating_point_underflow_exception(); }
152 if (exp > (sintL)(FF_exp_high-FF_exp_mid))
153 { throw floating_point_overflow_exception(); }
155 return make_FF(sign, exp+FF_exp_mid, mant & (bit(FF_mant_len)-1));
159 // Auspacken eines Floats:
160 inline float FF_to_float (const cl_FF& obj)
162 #if defined(CL_WIDE_POINTERS) // eines der beiden 32-Bit-Wörter
163 #if defined(__GNUC__)
164 return ((ffloatjanus) { eksplicit: cl_ffloat_value(obj) }).machine_float;
166 return *(float*)(&((uint32*)&(obj))[BIG_ENDIAN_P+(1-2*BIG_ENDIAN_P)*(FF_value_shift/32)]);
169 return TheFfloat(obj)->representation.machine_float;
172 // Überprüfen und Einpacken eines von den 'float'-Routinen gelieferten
175 // 1 <= e <= 254 : normalisierte Zahl
176 // e=0, m/=0: subnormale Zahl
177 // e=0, m=0: vorzeichenbehaftete 0.0
178 // e=255, m=0: vorzeichenbehaftete Infinity
180 // Angabe der möglicherweise auftretenden Sonderfälle:
181 // maybe_overflow: Operation läuft über, liefert IEEE-Infinity
182 // maybe_subnormal: Ergebnis sehr klein, liefert IEEE-subnormale Zahl
183 // maybe_underflow: Ergebnis sehr klein und /=0, liefert IEEE-Null
184 // maybe_divide_0: Ergebnis unbestimmt, liefert IEEE-Infinity
185 // maybe_nan: Ergebnis unbestimmt, liefert IEEE-NaN
186 #define float_to_FF(expr,ergebnis_zuweisung,maybe_overflow,maybe_subnormal,maybe_underflow,maybe_divide_0,maybe_nan) \
187 { var ffloatjanus _erg; _erg.machine_float = (expr); \
188 if ((_erg.eksplicit & ((uint32)bit(FF_exp_len+FF_mant_len)-bit(FF_mant_len))) == 0) /* e=0 ? */\
189 { if ((maybe_underflow \
190 || (maybe_subnormal && !((_erg.eksplicit << 1) == 0)) \
192 && underflow_allowed() \
194 { throw floating_point_underflow_exception(); } /* subnormal oder noch kleiner -> Underflow */\
196 { ergebnis_zuweisung cl_FF_0; } /* +/- 0.0 -> 0.0 */ \
198 elif ((maybe_overflow || maybe_divide_0) \
199 && (((~_erg.eksplicit) & ((uint32)bit(FF_exp_len+FF_mant_len)-bit(FF_mant_len))) == 0) /* e=255 ? */\
201 { if (maybe_nan && !((_erg.eksplicit << (32-FF_mant_len)) == 0)) \
202 { throw division_by_0_exception(); } /* NaN, also Singularität -> "Division durch 0" */\
203 else /* Infinity */ \
204 if (!maybe_overflow || maybe_divide_0) \
205 { throw division_by_0_exception(); } /* Infinity, Division durch 0 */\
207 { throw floating_point_overflow_exception(); } /* Infinity, Overflow */\
210 { ergebnis_zuweisung allocate_ffloat(_erg.eksplicit); } \
214 // Liefert zu einem Single-Float x : (futruncate x), ein FF.
215 // x wird von der 0 weg zur nächsten ganzen Zahl gerundet.
216 extern const cl_FF futruncate (const cl_FF& x);
218 // FF_to_I(x) wandelt ein Single-Float x, das eine ganze Zahl darstellt,
219 // in ein Integer um.
220 extern const cl_I cl_FF_to_I (const cl_FF& x);
222 // cl_I_to_FF(x) wandelt ein Integer x in ein Single-Float um und rundet dabei.
223 extern const cl_FF cl_I_to_FF (const cl_I& x);
225 // cl_RA_to_FF(x) wandelt eine rationale Zahl x in ein Single-Float um
227 extern const cl_FF cl_RA_to_FF (const cl_RA& x);
230 // IEEE-Single-Float:
231 // Bit 31 = s, Bits 30..23 = e, Bits 22..0 = m.
232 // e=0, m=0: vorzeichenbehaftete 0.0
233 // e=0, m/=0: subnormale Zahl,
234 // Wert = (-1)^s * 2^(1-126) * [ 0 . 0 m22 ... m0 ]
235 // 1 <= e <= 254 : normalisierte Zahl,
236 // Wert = (-1)^s * 2^(e-126) * [ 0 . 1 m22 ... m0 ]
237 // e=255, m=0: vorzeichenbehaftete Infinity
240 // cl_float_to_FF_pointer(val) wandelt ein IEEE-Single-Float val in ein Single-Float um.
241 extern cl_private_thing cl_float_to_FF_pointer (const float val);
243 // cl_FF_to_float(obj,&val);
244 // wandelt ein Single-Float obj in ein IEEE-Single-Float val um.
245 extern void cl_FF_to_float (const cl_FF& obj, ffloatjanus* val_);
249 #endif /* _CL_FF_H */