11 nonreturning_function(extern, cl_error_floating_point_overflow, (void));
12 nonreturning_function(extern, cl_error_floating_point_underflow, (void));
14 #define underflow_allowed() (! cl_inhibit_floating_point_underflow)
17 // For all floating-point formats:
18 // Sign s, Exponent e, Mantissa mk-1,...,m0
19 // represents the number (-1)^s * 2^(e-_EXP_MID) * [0 . 1 mk-1 ... m0]
20 // e=0 represents the number 0, always with sign s=0 (and mantissa =0).
21 // _exp_low and _exp_high are (inclusive) bounds for e.
22 // Bits for Sign s Exponent e Mantissa m (= k)
26 // LF 1 32 intDsize*n >= 53
29 // Konversionen ohne Rundung:
31 // cl_SF_to_FF(x) wandelt ein Short-Float x in ein Single-Float um.
32 extern const cl_FF cl_SF_to_FF (const cl_SF& x);
34 // cl_SF_to_DF(x) wandelt ein Short-Float x in ein Double-Float um.
35 extern const cl_DF cl_SF_to_DF (const cl_SF& x);
37 // cl_SF_to_LF(x,len) wandelt ein Short-Float x in ein Long-Float mit len Digits um.
38 // > uintC len: gewünschte Anzahl Digits, >=LF_minlen
39 extern const cl_LF cl_SF_to_LF (const cl_SF& x, uintC len);
41 // cl_FF_to_DF(x) wandelt ein Single-Float x in ein Double-Float um.
42 extern const cl_DF cl_FF_to_DF (const cl_FF& x);
44 // cl_FF_to_LF(x,len) wandelt ein Single-Float x in ein Long-Float mit len Digits um.
45 // > uintC len: gewünschte Anzahl Digits, >=LF_minlen
46 extern const cl_LF cl_FF_to_LF (const cl_FF& x, uintC len);
48 // cl_DF_to_LF(x,len) wandelt ein Double-Float x in ein Long-Float mit len Digits um.
49 // > uintC len: gewünschte Anzahl Digits, >=LF_minlen
50 extern const cl_LF cl_DF_to_LF (const cl_DF& x, uintC len);
53 // Konversionen mit Rundung:
55 // cl_FF_to_SF(x) wandelt ein Single-Float x in ein Short-Float um.
56 extern const cl_SF cl_FF_to_SF (const cl_FF& x);
58 // cl_DF_to_SF(x) wandelt ein Double-Float x in ein Short-Float um.
59 extern const cl_SF cl_DF_to_SF (const cl_DF& x);
61 // cl_LF_to_SF(x) wandelt ein Long-Float x in ein Short-Float um.
62 extern const cl_SF cl_LF_to_SF (const cl_LF& x);
64 // cl_DF_to_FF(x) wandelt ein Double-Float x in ein Single-Float um.
65 extern const cl_FF cl_DF_to_FF (const cl_DF& x);
67 // cl_LF_to_FF(x) wandelt ein Long-Float x in ein Single-Float um.
68 extern const cl_FF cl_LF_to_FF (const cl_LF& x);
70 // cl_LF_to_DF(x) wandelt ein Long-Float x in ein Double-Float um.
71 extern const cl_DF cl_LF_to_DF (const cl_LF& x);
74 // Fehlermeldung wegen NaN
75 nonreturning_function(extern, cl_error_floating_point_nan, (void));
78 // Runtime typing support.
79 extern cl_class cl_class_ffloat;
80 extern cl_class cl_class_dfloat;
81 extern cl_class cl_class_lfloat;
84 inline cl_boolean longfloatp (const cl_F& x)
87 if (x.pointer_type() == &cl_class_lfloat)
92 // Macro: verteilt je nach Float-Typ eines Floats x auf 4 Statements.
93 // floattypecase(x, SF_statement,FF_statement,DF_statement,LF_statement);
94 // x sollte eine Variable sein.
95 #ifdef CL_WIDE_POINTERS
96 #define floattypecase(x, SF_statement,FF_statement,DF_statement,LF_statement) \
97 if (!(x).pointer_p()) \
98 switch ((x).nonpointer_tag()) \
99 { case cl_SF_tag: { SF_statement } break; \
100 case cl_FF_tag: { FF_statement } break; \
101 default: NOTREACHED \
104 if ((x).pointer_type() == &cl_class_dfloat) { DF_statement } \
105 else if ((x).pointer_type() == &cl_class_lfloat) { LF_statement } \
109 #define floattypecase(x, SF_statement,FF_statement,DF_statement,LF_statement) \
110 if (!(x).pointer_p()) \
111 switch ((x).nonpointer_tag()) \
112 { case cl_SF_tag: { SF_statement } break; \
113 default: NOTREACHED \
116 if ((x).pointer_type() == &cl_class_ffloat) { FF_statement } \
117 else if ((x).pointer_type() == &cl_class_dfloat) { DF_statement } \
118 else if ((x).pointer_type() == &cl_class_lfloat) { LF_statement } \
123 // Macro: verteilt je nach Float-Typ eines Floats x auf 4 Statements,
124 // die x vom jeweiligen Float-Typ benutzen dürfen.
125 // floatcase(x, SF_statement,FF_statement,DF_statement,LF_statement);
126 // x sollte eine Variable sein.
127 #define floatcase(x, SF_statement,FF_statement,DF_statement,LF_statement) \
129 , var cl_SF& __tmp = *(cl_SF*)&x; var cl_SF& x = __tmp; SF_statement \
130 , var cl_FF& __tmp = *(cl_FF*)&x; var cl_FF& x = __tmp; FF_statement \
131 , var cl_DF& __tmp = *(cl_DF*)&x; var cl_DF& x = __tmp; DF_statement \
132 , var cl_LF& __tmp = *(cl_LF*)&x; var cl_LF& x = __tmp; LF_statement \
136 // GEN_F_OP1(arg1,F_OP,ergebnis_zuweisung)
137 // generates the body of a float operation with one argument.
138 // LF_OP is executed once the argument has been converted to its exact
140 #define GEN_F_OP1(arg1,F_OP,ergebnis_zuweisung) \
143 , /* SF */ ergebnis_zuweisung F_OP(arg1); \
144 , /* FF */ ergebnis_zuweisung F_OP(arg1); \
145 , /* DF */ ergebnis_zuweisung F_OP(arg1); \
146 , /* LF */ ergebnis_zuweisung F_OP(arg1); \
151 // GEN_F_OP2(arg1,arg2,F_OP,r,s,ergebnis_zuweisung)
152 // generates the body of a float operation with two arguments.
153 // F_OP is executed once both arguments have been converted to the same
154 // float format (the longer one of arg1 and arg2). The r results are then
155 // converted the shorter of the two float formats. (r = 0,1,2.)
156 // s = 0,1. s=0 means the LF operation needs two long-floats of the same size.
157 // s=1 means they may be of different sizes.
158 #define GEN_F_OP2(arg1,arg2,F_OP,r,s,ergebnis_zuweisung) \
164 ergebnis_zuweisung CONCAT(NOMAP,r)(SF, \
167 ergebnis_zuweisung CONCAT(MAP,r)(FF,cl_FF_to_SF,\
168 F_OP(cl_SF_to_FF(arg1),arg2) ); \
170 ergebnis_zuweisung CONCAT(MAP,r)(DF,cl_DF_to_SF,\
171 F_OP(cl_SF_to_DF(arg1),arg2) ); \
173 ergebnis_zuweisung CONCAT(MAP,r)(LF,cl_LF_to_SF,\
174 F_OP(cl_SF_to_LF(arg1,CONCAT(LFlen,s)(arg2)),arg2) ); \
179 ergebnis_zuweisung CONCAT(MAP,r)(FF,cl_FF_to_SF,\
180 F_OP(arg1,cl_SF_to_FF(arg2)) ); \
182 ergebnis_zuweisung CONCAT(NOMAP,r)(FF, \
185 ergebnis_zuweisung CONCAT(MAP,r)(DF,cl_DF_to_FF,\
186 F_OP(cl_FF_to_DF(arg1),arg2) ); \
188 ergebnis_zuweisung CONCAT(MAP,r)(LF,cl_LF_to_FF,\
189 F_OP(cl_FF_to_LF(arg1,CONCAT(LFlen,s)(arg2)),arg2) ); \
194 ergebnis_zuweisung CONCAT(MAP,r)(DF,cl_DF_to_SF,\
195 F_OP(arg1,cl_SF_to_DF(arg2)) ); \
197 ergebnis_zuweisung CONCAT(MAP,r)(DF,cl_DF_to_FF,\
198 F_OP(arg1,cl_FF_to_DF(arg2)) ); \
200 ergebnis_zuweisung CONCAT(NOMAP,r)(DF, \
203 ergebnis_zuweisung CONCAT(MAP,r)(LF,cl_LF_to_DF,\
204 F_OP(cl_DF_to_LF(arg1,CONCAT(LFlen,s)(arg2)),arg2) ); \
209 ergebnis_zuweisung CONCAT(MAP,r)(LF,cl_LF_to_SF,\
210 F_OP(arg1,cl_SF_to_LF(arg2,CONCAT(LFlen,s)(arg1))) ); \
212 ergebnis_zuweisung CONCAT(MAP,r)(LF,cl_LF_to_FF,\
213 F_OP(arg1,cl_FF_to_LF(arg2,CONCAT(LFlen,s)(arg1))) ); \
215 ergebnis_zuweisung CONCAT(MAP,r)(LF,cl_LF_to_DF,\
216 F_OP(arg1,cl_DF_to_LF(arg2,CONCAT(LFlen,s)(arg1))) ); \
218 GEN_LF_OP2_AUX(arg1,arg2,F_OP,r,s,ergebnis_zuweisung) \
222 #define GEN_LF_OP2_AUX(arg1,arg2,F_OP,r,s,ergebnis_zuweisung) \
223 CONCAT(GEN_LF_OP2_AUX,s)(arg1,arg2,F_OP,r,ergebnis_zuweisung)
224 #define GEN_LF_OP2_AUX0(arg1,arg2,F_OP,r,ergebnis_zuweisung) \
225 var uintC len1 = TheLfloat(arg1)->len; \
226 var uintC len2 = TheLfloat(arg2)->len; \
227 if (len1 == len2) /* gleich -> direkt ausführen */ \
228 { ergebnis_zuweisung CONCAT(NOMAP,r) (LF, F_OP(arg1,arg2)); } \
229 elif (len1 > len2) /* -> arg2 auf die Länge von arg1 bringen */ \
230 { ergebnis_zuweisung CONCAT(MAP,r) (LF, LF_shorten_len2, \
231 F_OP(arg1,extend(arg2,len1)) ); \
233 else /* (len1 < len2) -> arg1 auf die Länge von arg2 bringen */ \
234 { ergebnis_zuweisung CONCAT(MAP,r) (LF, LF_shorten_len1, \
235 F_OP(extend(arg1,len2),arg2) ); \
237 #define LF_shorten_len1(arg) shorten(arg,len1)
238 #define LF_shorten_len2(arg) shorten(arg,len2)
239 #define GEN_LF_OP2_AUX1(arg1,arg2,F_OP,r,ergebnis_zuweisung) \
240 ergebnis_zuweisung CONCAT(NOMAP,r) (LF, F_OP(arg1,arg2));
242 #define NOMAP0(F,EXPR) EXPR
243 #define NOMAP1(F,EXPR) EXPR
244 #define MAP0(F,FN,EXPR) EXPR
245 #define MAP1(F,FN,EXPR) FN(EXPR)
247 #define LFlen0(arg) TheLfloat(arg)->len
248 #define LFlen1(arg) LF_minlen
251 // cl_F_extendsqrt(x) erweitert die Genauigkeit eines Floats x um eine Stufe
252 // SF -> FF -> DF -> LF(4) -> LF(5) -> LF(6) -> ...
253 // Ein Float mit d Mantissenbits wird so zu einem Float mit
254 // mindestens d+sqrt(d)+2 Mantissenbits.
255 extern const cl_F cl_F_extendsqrt (const cl_F& x);
257 // cl_F_extendsqrtx(x) erweitert die Genauigkeit eines Floats x um eine Stufe
258 // SF -> FF -> DF -> LF(4) -> LF(5) -> LF(6) -> ...
259 // Ein Float mit d Mantissenbits und l Exponentenbits wird so zu einem Float
260 // mit mindestens d+sqrt(d)+2+(l-1) Mantissenbits.
261 extern const cl_F cl_F_extendsqrtx (const cl_F& x);
263 // cl_F_shortenrelative(x,y) tries to reduce the size of x, such that one
264 // wouldn't notice it when adding x to y. y must be /= 0. More precisely,
265 // this returns a float approximation of x, such that 1 ulp(x) < 1 ulp(y).
266 extern const cl_F cl_F_shortenrelative (const cl_F& x, const cl_F& y);
269 // Macro: dispatches according to a cl_float_format_t value.
270 // floatformatcase(value, SF_statement,FF_statement,DF_statement,LF_statement)
271 // LF_statement darf auf `len' zugreifen, die zu `value' korrespondierende
272 // Mantissenlänge (gemessen in Digits).
273 #define floatformatcase(value, SF_statement,FF_statement,DF_statement,LF_statement) \
274 { if ((value) <= cl_float_format_sfloat) { SF_statement } \
275 elif ((value) <= cl_float_format_ffloat) { FF_statement } \
276 elif ((value) <= cl_float_format_dfloat) { DF_statement } \
277 else { var uintL len = ceiling((uintL)(value),intDsize); LF_statement } \