1 | // Public float operations. |
2 | |
3 | #ifndef _CL_FLOAT_H |
4 | #define _CL_FLOAT_H |
5 | |
6 | #include "cln/number.h" |
7 | #include "cln/float_class.h" |
8 | #include "cln/floatformat.h" |
9 | #include "cln/random.h" |
10 | #include "cln/integer_class.h" |
11 | #include "cln/sfloat_class.h" |
12 | #include "cln/ffloat_class.h" |
13 | #include "cln/dfloat_class.h" |
14 | #include "cln/lfloat_class.h" |
15 | #include "cln/exception.h" |
16 | |
17 | namespace cln { |
18 | |
19 | CL_DEFINE_AS_CONVERSION(cl_F) |
20 | |
21 | |
22 | // Return type for integer_decode_float: |
23 | struct cl_idecoded_float { |
24 | cl_I mantissa; |
25 | cl_I exponent; |
26 | cl_I sign; |
27 | // Constructor. |
28 | cl_idecoded_float () {} |
29 | cl_idecoded_float (const cl_I& m, const cl_I& e, const cl_I& s) : mantissa(m), exponent(e), sign(s) {} |
30 | }; |
31 | |
32 | |
33 | // zerop(x) testet, ob (= x 0). |
34 | extern bool zerop (const cl_F& x); |
35 | |
36 | // minusp(x) testet, ob (< x 0). |
37 | extern bool minusp (const cl_F& x); |
38 | |
39 | // plusp(x) testet, ob (> x 0). |
40 | extern bool plusp (const cl_F& x); |
41 | |
42 | |
43 | // cl_F_to_SF(x) wandelt ein Float x in ein Short-Float um und rundet dabei. |
44 | extern const cl_SF cl_F_to_SF (const cl_F& x); |
45 | |
46 | // cl_F_to_FF(x) wandelt ein Float x in ein Single-Float um und rundet dabei. |
47 | extern const cl_FF cl_F_to_FF (const cl_F& x); |
48 | |
49 | // cl_F_to_DF(x) wandelt ein Float x in ein Double-Float um und rundet dabei. |
50 | extern const cl_DF cl_F_to_DF (const cl_F& x); |
51 | |
52 | // cl_F_to_LF(x,len) wandelt ein Float x in ein Long-Float mit len Digits um |
53 | // und rundet dabei. |
54 | // > uintC len: gewünschte Anzahl Digits, >=LF_minlen |
55 | extern const cl_LF cl_F_to_LF (const cl_F& x, uintC len); |
56 | |
57 | |
58 | // The default float format used when converting rational numbers to floats. |
59 | extern float_format_t default_float_format; |
60 | |
61 | // Returns the smallest float format which guarantees at least n decimal digits |
62 | // in the mantissa (after the decimal point). |
63 | extern float_format_t float_format (uintE n); |
64 | |
65 | // cl_float(x,y) wandelt ein Float x in das Float-Format des Floats y um |
66 | // und rundet dabei nötigenfalls. |
67 | // > x,y: Floats |
68 | // < ergebnis: (float x y) |
69 | extern const cl_F cl_float (const cl_F& x, const cl_F& y); |
70 | |
71 | // cl_float(x,f) wandelt ein Float x in das Float-Format f um |
72 | // und rundet dabei nötigenfalls. |
73 | // > x: ein Float |
74 | // > f: eine Float-Format-Spezifikation |
75 | // < ergebnis: (float x f) |
76 | extern const cl_F cl_float (const cl_F& x, float_format_t f); |
77 | |
78 | // cl_float(x) wandelt eine reelle Zahl x in ein Float um |
79 | // und rundet dabei nötigenfalls. |
80 | // > x: eine reelle Zahl |
81 | // < ergebnis: (float x) |
82 | // Abhängig von default_float_format. |
83 | inline const cl_F cl_float (const cl_F& x) { return x; } |
84 | |
85 | // cl_float(x,y) wandelt ein Integer x in das Float-Format des Floats y um |
86 | // und rundet dabei nötigenfalls. |
87 | // > x: ein Integer |
88 | // > y: ein Float |
89 | // < ergebnis: (float x y) |
90 | extern const cl_F cl_float (const cl_I& x, const cl_F& y); |
91 | |
92 | // cl_float(x,y) wandelt ein Integer x in das Float-Format f um |
93 | // und rundet dabei nötigenfalls. |
94 | // > x: ein Integer |
95 | // > f: eine Float-Format-Spezifikation |
96 | // < ergebnis: (float x f) |
97 | extern const cl_F cl_float (const cl_I& x, float_format_t f); |
98 | |
99 | // cl_float(x) wandelt ein Integer x in ein Float um und rundet dabei. |
100 | // > x: ein Integer |
101 | // < ergebnis: (float x) |
102 | // Abhängig von default_float_format. |
103 | extern const cl_F cl_float (const cl_I& x); |
104 | |
105 | // cl_float(x,y) wandelt eine rationale Zahl x in das Float-Format des |
106 | // Floats y um und rundet dabei nötigenfalls. |
107 | // > x: eine rationale Zahl |
108 | // > y: ein Float |
109 | // < ergebnis: (float x y) |
110 | extern const cl_F cl_float (const cl_RA& x, const cl_F& y); |
111 | |
112 | // cl_float(x,y) wandelt eine rationale Zahl x in das Float-Format f um |
113 | // und rundet dabei nötigenfalls. |
114 | // > x: eine rationale Zahl |
115 | // > f: eine Float-Format-Spezifikation |
116 | // < ergebnis: (float x f) |
117 | extern const cl_F cl_float (const cl_RA& x, float_format_t f); |
118 | |
119 | // cl_float(x) wandelt eine rationale Zahl x in ein Float um und rundet dabei. |
120 | // > x: eine rationale Zahl |
121 | // < ergebnis: (float x) |
122 | // Abhängig von default_float_format. |
123 | extern const cl_F cl_float (const cl_RA& x); |
124 | |
125 | // The C++ compilers are not clever enough to guess this: |
126 | inline const cl_F cl_float (int x, const cl_F& y) |
127 | { return cl_float(cl_I(x),y); } |
128 | inline const cl_F cl_float (unsigned int x, const cl_F& y) |
129 | { return cl_float(cl_I(x),y); } |
130 | inline const cl_F cl_float (int x, float_format_t y) |
131 | { return cl_float(cl_I(x),y); } |
132 | inline const cl_F cl_float (unsigned int x, float_format_t y) |
133 | { return cl_float(cl_I(x),y); } |
134 | inline const cl_F cl_float (int x) |
135 | { return cl_float(cl_I(x)); } |
136 | inline const cl_F cl_float (unsigned int x) |
137 | { return cl_float(cl_I(x)); } |
138 | // The C++ compilers could hardly guess the following: |
139 | inline const cl_F cl_float (float x, const cl_F& y) |
140 | { return cl_float(cl_FF(x),y); } |
141 | inline const cl_F cl_float (double x, const cl_F& y) |
142 | { return cl_float(cl_DF(x),y); } |
143 | inline const cl_F cl_float (float x, float_format_t y) |
144 | { return cl_float(cl_FF(x),y); } |
145 | inline const cl_F cl_float (double x, float_format_t y) |
146 | { return cl_float(cl_DF(x),y); } |
147 | inline const cl_F cl_float (float x) |
148 | { return cl_float(cl_FF(x)); } |
149 | inline const cl_F cl_float (double x) |
150 | { return cl_float(cl_DF(x)); } |
151 | |
152 | |
153 | // Liefert (- x), wo x ein Float ist. |
154 | extern const cl_F operator- (const cl_F& x); |
155 | |
156 | // Liefert (+ x y), wo x und y Floats sind. |
157 | extern const cl_F operator+ (const cl_F& x, const cl_F& y); |
158 | // The C++ compilers could hardly guess the following: |
159 | inline const cl_F operator+ (const cl_RA& x, const cl_F& y) |
160 | { return cl_float(x,y) + y; } |
161 | inline const cl_F operator+ (const cl_I& x, const cl_F& y) |
162 | { return cl_float(x,y) + y; } |
163 | inline const cl_F operator+ (const cl_F& x, const cl_RA& y) |
164 | { return x + cl_float(y,x); } |
165 | inline const cl_F operator+ (const cl_F& x, const cl_I& y) |
166 | { return x + cl_float(y,x); } |
167 | // Dem C++-Compiler muß man nun auch das Folgende sagen: |
168 | inline const cl_F operator+ (const int x, const cl_F& y) |
169 | { return cl_I(x) + y; } |
170 | inline const cl_F operator+ (const unsigned int x, const cl_F& y) |
171 | { return cl_I(x) + y; } |
172 | inline const cl_F operator+ (const long x, const cl_F& y) |
173 | { return cl_I(x) + y; } |
174 | inline const cl_F operator+ (const unsigned long x, const cl_F& y) |
175 | { return cl_I(x) + y; } |
176 | #ifdef HAVE_LONGLONG |
177 | inline const cl_F operator+ (const long long x, const cl_F& y) |
178 | { return cl_I(x) + y; } |
179 | inline const cl_F operator+ (const unsigned long long x, const cl_F& y) |
180 | { return cl_I(x) + y; } |
181 | #endif |
182 | inline const cl_F operator+ (const float x, const cl_F& y) |
183 | { return cl_F(x) + y; } |
184 | inline const cl_F operator+ (const double x, const cl_F& y) |
185 | { return cl_F(x) + y; } |
186 | inline const cl_F operator+ (const cl_F& x, const int y) |
187 | { return x + cl_I(y); } |
188 | inline const cl_F operator+ (const cl_F& x, const unsigned int y) |
189 | { return x + cl_I(y); } |
190 | inline const cl_F operator+ (const cl_F& x, const long y) |
191 | { return x + cl_I(y); } |
192 | inline const cl_F operator+ (const cl_F& x, const unsigned long y) |
193 | { return x + cl_I(y); } |
194 | #ifdef HAVE_LONGLONG |
195 | inline const cl_F operator+ (const cl_F& x, const long long y) |
196 | { return x + cl_I(y); } |
197 | inline const cl_F operator+ (const cl_F& x, const unsigned long long y) |
198 | { return x + cl_I(y); } |
199 | #endif |
200 | inline const cl_F operator+ (const cl_F& x, const float y) |
201 | { return x + cl_F(y); } |
202 | inline const cl_F operator+ (const cl_F& x, const double y) |
203 | { return x + cl_F(y); } |
204 | |
205 | // Liefert (- x y), wo x und y Floats sind. |
206 | extern const cl_F operator- (const cl_F& x, const cl_F& y); |
207 | // The C++ compilers could hardly guess the following: |
208 | inline const cl_F operator- (const cl_RA& x, const cl_F& y) |
209 | { return cl_float(x,y) - y; } |
210 | inline const cl_F operator- (const cl_I& x, const cl_F& y) |
211 | { return cl_float(x,y) - y; } |
212 | inline const cl_F operator- (const cl_F& x, const cl_RA& y) |
213 | { return x - cl_float(y,x); } |
214 | inline const cl_F operator- (const cl_F& x, const cl_I& y) |
215 | { return x - cl_float(y,x); } |
216 | // Dem C++-Compiler muß man nun auch das Folgende sagen: |
217 | inline const cl_F operator- (const int x, const cl_F& y) |
218 | { return cl_I(x) - y; } |
219 | inline const cl_F operator- (const unsigned int x, const cl_F& y) |
220 | { return cl_I(x) - y; } |
221 | inline const cl_F operator- (const long x, const cl_F& y) |
222 | { return cl_I(x) - y; } |
223 | inline const cl_F operator- (const unsigned long x, const cl_F& y) |
224 | { return cl_I(x) - y; } |
225 | #ifdef HAVE_LONGLONG |
226 | inline const cl_F operator- (const long long x, const cl_F& y) |
227 | { return cl_I(x) - y; } |
228 | inline const cl_F operator- (const unsigned long long x, const cl_F& y) |
229 | { return cl_I(x) - y; } |
230 | #endif |
231 | inline const cl_F operator- (const float x, const cl_F& y) |
232 | { return cl_F(x) - y; } |
233 | inline const cl_F operator- (const double x, const cl_F& y) |
234 | { return cl_F(x) - y; } |
235 | inline const cl_F operator- (const cl_F& x, const int y) |
236 | { return x - cl_I(y); } |
237 | inline const cl_F operator- (const cl_F& x, const unsigned int y) |
238 | { return x - cl_I(y); } |
239 | inline const cl_F operator- (const cl_F& x, const long y) |
240 | { return x - cl_I(y); } |
241 | inline const cl_F operator- (const cl_F& x, const unsigned long y) |
242 | { return x - cl_I(y); } |
243 | #ifdef HAVE_LONGLONG |
244 | inline const cl_F operator- (const cl_F& x, const long long y) |
245 | { return x - cl_I(y); } |
246 | inline const cl_F operator- (const cl_F& x, const unsigned long long y) |
247 | { return x - cl_I(y); } |
248 | #endif |
249 | inline const cl_F operator- (const cl_F& x, const float y) |
250 | { return x - cl_F(y); } |
251 | inline const cl_F operator- (const cl_F& x, const double y) |
252 | { return x - cl_F(y); } |
253 | |
254 | // Liefert (* x y), wo x und y Floats sind. |
255 | extern const cl_F operator* (const cl_F& x, const cl_F& y); |
256 | // Spezialfall x oder y Integer oder rationale Zahl. |
257 | inline const cl_R operator* (const cl_F& x, const cl_I& y) |
258 | { |
259 | extern const cl_R cl_F_I_mul (const cl_F&, const cl_I&); |
260 | return cl_F_I_mul(x,y); |
261 | } |
262 | inline const cl_R operator* (const cl_I& x, const cl_F& y) |
263 | { |
264 | extern const cl_R cl_F_I_mul (const cl_F&, const cl_I&); |
265 | return cl_F_I_mul(y,x); |
266 | } |
267 | inline const cl_R operator* (const cl_F& x, const cl_RA& y) |
268 | { |
269 | extern const cl_R cl_F_RA_mul (const cl_F&, const cl_RA&); |
270 | return cl_F_RA_mul(x,y); |
271 | } |
272 | inline const cl_R operator* (const cl_RA& x, const cl_F& y) |
273 | { |
274 | extern const cl_R cl_F_RA_mul (const cl_F&, const cl_RA&); |
275 | return cl_F_RA_mul(y,x); |
276 | } |
277 | // Dem C++-Compiler muß man nun auch das Folgende sagen: |
278 | inline const cl_R operator* (const int x, const cl_F& y) |
279 | { return cl_I(x) * y; } |
280 | inline const cl_R operator* (const unsigned int x, const cl_F& y) |
281 | { return cl_I(x) * y; } |
282 | inline const cl_R operator* (const long x, const cl_F& y) |
283 | { return cl_I(x) * y; } |
284 | inline const cl_R operator* (const unsigned long x, const cl_F& y) |
285 | { return cl_I(x) * y; } |
286 | #ifdef HAVE_LONGLONG |
287 | inline const cl_R operator* (const long long x, const cl_F& y) |
288 | { return cl_I(x) * y; } |
289 | inline const cl_R operator* (const unsigned long long x, const cl_F& y) |
290 | { return cl_I(x) * y; } |
291 | #endif |
292 | inline const cl_F operator* (const float x, const cl_F& y) |
293 | { return cl_F(x) * y; } |
294 | inline const cl_F operator* (const double x, const cl_F& y) |
295 | { return cl_F(x) * y; } |
296 | inline const cl_R operator* (const cl_F& x, const int y) |
297 | { return x * cl_I(y); } |
298 | inline const cl_R operator* (const cl_F& x, const unsigned int y) |
299 | { return x * cl_I(y); } |
300 | inline const cl_R operator* (const cl_F& x, const long y) |
301 | { return x * cl_I(y); } |
302 | inline const cl_R operator* (const cl_F& x, const unsigned long y) |
303 | { return x * cl_I(y); } |
304 | #ifdef HAVE_LONGLONG |
305 | inline const cl_R operator* (const cl_F& x, const long long y) |
306 | { return x * cl_I(y); } |
307 | inline const cl_R operator* (const cl_F& x, const unsigned long long y) |
308 | { return x * cl_I(y); } |
309 | #endif |
310 | inline const cl_F operator* (const cl_F& x, const float y) |
311 | { return x * cl_F(y); } |
312 | inline const cl_F operator* (const cl_F& x, const double y) |
313 | { return x * cl_F(y); } |
314 | |
315 | // Liefert (* x x), wo x ein Float ist. |
316 | extern const cl_F square (const cl_F& x); |
317 | |
318 | // Liefert (/ x y), wo x und y Floats sind. |
319 | extern const cl_F operator/ (const cl_F& x, const cl_F& y); |
320 | // Liefert (/ x y), wo x und y ein Float und eine rationale Zahl sind. |
321 | extern const cl_F operator/ (const cl_F& x, const cl_RA& y); |
322 | extern const cl_F operator/ (const cl_F& x, const cl_I& y); |
323 | extern const cl_R operator/ (const cl_RA& x, const cl_F& y); |
324 | extern const cl_R operator/ (const cl_I& x, const cl_F& y); |
325 | // The C++ compilers could hardly guess the following: |
326 | inline const cl_F operator/ (const cl_F& x, const int y) |
327 | { return x / cl_I(y); } |
328 | inline const cl_F operator/ (const cl_F& x, const unsigned int y) |
329 | { return x / cl_I(y); } |
330 | inline const cl_F operator/ (const cl_F& x, const long y) |
331 | { return x / cl_I(y); } |
332 | inline const cl_F operator/ (const cl_F& x, const unsigned long y) |
333 | { return x / cl_I(y); } |
334 | #ifdef HAVE_LONGLONG |
335 | inline const cl_F operator/ (const cl_F& x, const long long y) |
336 | { return x / cl_I(y); } |
337 | inline const cl_F operator/ (const cl_F& x, const unsigned long long y) |
338 | { return x / cl_I(y); } |
339 | #endif |
340 | inline const cl_F operator/ (const cl_F& x, const float y) |
341 | { return x / cl_F(y); } |
342 | inline const cl_F operator/ (const cl_F& x, const double y) |
343 | { return x / cl_F(y); } |
344 | inline const cl_R operator/ (const int x, const cl_F& y) |
345 | { return cl_I(x) / y; } |
346 | inline const cl_R operator/ (const unsigned int x, const cl_F& y) |
347 | { return cl_I(x) / y; } |
348 | inline const cl_R operator/ (const long x, const cl_F& y) |
349 | { return cl_I(x) / y; } |
350 | inline const cl_R operator/ (const unsigned long x, const cl_F& y) |
351 | { return cl_I(x) / y; } |
352 | #ifdef HAVE_LONGLONG |
353 | inline const cl_R operator/ (const long long x, const cl_F& y) |
354 | { return cl_I(x) / y; } |
355 | inline const cl_R operator/ (const unsigned long long x, const cl_F& y) |
356 | { return cl_I(x) / y; } |
357 | #endif |
358 | inline const cl_F operator/ (const float x, const cl_F& y) |
359 | { return cl_F(x) / y; } |
360 | inline const cl_F operator/ (const double x, const cl_F& y) |
361 | { return cl_F(x) / y; } |
362 | |
363 | // Liefert (abs x), wo x ein Float ist. |
364 | extern const cl_F abs (const cl_F& x); |
365 | |
366 | // Liefert zu einem Float x>=0 : (sqrt x), ein Float. |
367 | extern const cl_F sqrt (const cl_F& x); |
368 | |
369 | // recip(x) liefert (/ x), wo x ein Float ist. |
370 | extern const cl_F recip (const cl_F& x); |
371 | |
372 | // (1+ x), wo x ein Float ist. |
373 | inline const cl_F plus1 (const cl_F& x) // { return x + cl_I(1); } |
374 | { |
375 | return x + cl_float(1,x); |
376 | } |
377 | |
378 | // (1- x), wo x ein Float ist. |
379 | inline const cl_F minus1 (const cl_F& x) // { return x + cl_I(-1); } |
380 | { |
381 | return x + cl_float(-1,x); |
382 | } |
383 | |
384 | // compare(x,y) vergleicht zwei Floats x und y. |
385 | // Ergebnis: 0 falls x=y, +1 falls x>y, -1 falls x<y. |
386 | extern cl_signean compare (const cl_F& x, const cl_F& y); |
387 | |
388 | // equal_hashcode(x) liefert einen equal-invarianten Hashcode für x. |
389 | extern uint32 equal_hashcode (const cl_F& x); |
390 | |
391 | inline bool operator== (const cl_F& x, const cl_F& y) |
392 | { return compare(x,y)==0; } |
393 | inline bool operator!= (const cl_F& x, const cl_F& y) |
394 | { return compare(x,y)!=0; } |
395 | inline bool operator<= (const cl_F& x, const cl_F& y) |
396 | { return compare(x,y)<=0; } |
397 | inline bool operator< (const cl_F& x, const cl_F& y) |
398 | { return compare(x,y)<0; } |
399 | inline bool operator>= (const cl_F& x, const cl_F& y) |
400 | { return compare(x,y)>=0; } |
401 | inline bool operator> (const cl_F& x, const cl_F& y) |
402 | { return compare(x,y)>0; } |
403 | |
404 | |
405 | // ffloor(x) liefert (ffloor x), wo x ein Float ist. |
406 | extern const cl_F ffloor (const cl_F& x); |
407 | |
408 | // fceiling(x) liefert (fceiling x), wo x ein Float ist. |
409 | extern const cl_F fceiling (const cl_F& x); |
410 | |
411 | // ftruncate(x) liefert (ftruncate x), wo x ein Float ist. |
412 | extern const cl_F ftruncate (const cl_F& x); |
413 | |
414 | // fround(x) liefert (fround x), wo x ein Float ist. |
415 | extern const cl_F fround (const cl_F& x); |
416 | |
417 | |
418 | // Return type for frounding operators. |
419 | // x / y --> (q,r) with x = y*q+r. |
420 | struct cl_F_fdiv_t { |
421 | cl_F quotient; |
422 | cl_F remainder; |
423 | // Constructor. |
424 | cl_F_fdiv_t () {} |
425 | cl_F_fdiv_t (const cl_F& q, const cl_F& r) : quotient(q), remainder(r) {} |
426 | }; |
427 | |
428 | // ffloor2(x) liefert (ffloor x), wo x ein F ist. |
429 | extern const cl_F_fdiv_t ffloor2 (const cl_F& x); |
430 | |
431 | // fceiling2(x) liefert (fceiling x), wo x ein F ist. |
432 | extern const cl_F_fdiv_t fceiling2 (const cl_F& x); |
433 | |
434 | // ftruncate2(x) liefert (ftruncate x), wo x ein F ist. |
435 | extern const cl_F_fdiv_t ftruncate2 (const cl_F& x); |
436 | |
437 | // fround2(x) liefert (fround x), wo x ein F ist. |
438 | extern const cl_F_fdiv_t fround2 (const cl_F& x); |
439 | |
440 | |
441 | // Return type for rounding operators. |
442 | // x / y --> (q,r) with x = y*q+r. |
443 | struct cl_F_div_t { |
444 | cl_I quotient; |
445 | cl_F remainder; |
446 | // Constructor. |
447 | cl_F_div_t () {} |
448 | cl_F_div_t (const cl_I& q, const cl_F& r) : quotient(q), remainder(r) {} |
449 | }; |
450 | |
451 | // floor2(x) liefert (floor x), wo x ein F ist. |
452 | extern const cl_F_div_t floor2 (const cl_F& x); |
453 | extern const cl_I floor1 (const cl_F& x); |
454 | |
455 | // ceiling2(x) liefert (ceiling x), wo x ein F ist. |
456 | extern const cl_F_div_t ceiling2 (const cl_F& x); |
457 | extern const cl_I ceiling1 (const cl_F& x); |
458 | |
459 | // truncate2(x) liefert (truncate x), wo x ein F ist. |
460 | extern const cl_F_div_t truncate2 (const cl_F& x); |
461 | extern const cl_I truncate1 (const cl_F& x); |
462 | |
463 | // round2(x) liefert (round x), wo x ein F ist. |
464 | extern const cl_F_div_t round2 (const cl_F& x); |
465 | extern const cl_I round1 (const cl_F& x); |
466 | |
467 | // floor2(x,y) liefert (floor x y), wo x und y Floats sind. |
468 | extern const cl_F_div_t floor2 (const cl_F& x, const cl_F& y); |
469 | inline const cl_I floor1 (const cl_F& x, const cl_F& y) { return floor1(x/y); } |
470 | |
471 | // ceiling2(x,y) liefert (ceiling x y), wo x und y Floats sind. |
472 | extern const cl_F_div_t ceiling2 (const cl_F& x, const cl_F& y); |
473 | inline const cl_I ceiling1 (const cl_F& x, const cl_F& y) { return ceiling1(x/y); } |
474 | |
475 | // truncate2(x,y) liefert (truncate x y), wo x und y Floats sind. |
476 | extern const cl_F_div_t truncate2 (const cl_F& x, const cl_F& y); |
477 | inline const cl_I truncate1 (const cl_F& x, const cl_F& y) { return truncate1(x/y); } |
478 | |
479 | // round2(x,y) liefert (round x y), wo x und y Floats sind. |
480 | extern const cl_F_div_t round2 (const cl_F& x, const cl_F& y); |
481 | inline const cl_I round1 (const cl_F& x, const cl_F& y) { return round1(x/y); } |
482 | |
483 | |
484 | // Return type for decode_float: |
485 | struct decoded_float { |
486 | cl_F mantissa; |
487 | cl_I exponent; |
488 | cl_F sign; |
489 | // Constructor. |
490 | decoded_float () {} |
491 | decoded_float (const cl_F& m, const cl_I& e, const cl_F& s) : mantissa(m), exponent(e), sign(s) {} |
492 | }; |
493 | |
494 | // decode_float(x) liefert zu einem Float x: (decode-float x). |
495 | // x = 0.0 liefert (0.0, 0, 1.0). |
496 | // x = (-1)^s * 2^e * m liefert ((-1)^0 * 2^0 * m, e als Integer, (-1)^s). |
497 | extern const decoded_float decode_float (const cl_F& x); |
498 | |
499 | // float_exponent(x) liefert zu einem Float x: |
500 | // den Exponenten von (decode-float x). |
501 | // x = 0.0 liefert 0. |
502 | // x = (-1)^s * 2^e * m liefert e. |
503 | extern sintE float_exponent (const cl_F& x); |
504 | |
505 | // float_radix(x) liefert (float-radix x), wo x ein Float ist. |
506 | inline sintL float_radix (const cl_F& x) |
507 | { |
508 | (void)x; // unused x |
509 | return 2; |
510 | } |
511 | |
512 | // float_sign(x) liefert (float-sign x), wo x ein Float ist. |
513 | extern const cl_F float_sign (const cl_F& x); |
514 | |
515 | // float_sign(x,y) liefert (float-sign x y), wo x und y Floats sind. |
516 | extern const cl_F float_sign (const cl_F& x, const cl_F& y); |
517 | |
518 | // float_digits(x) liefert (float-digits x), wo x ein Float ist. |
519 | // < ergebnis: ein uintC >0 |
520 | extern uintC float_digits (const cl_F& x); |
521 | |
522 | // float_precision(x) liefert (float-precision x), wo x ein Float ist. |
523 | // < ergebnis: ein uintC >=0 |
524 | extern uintC float_precision (const cl_F& x); |
525 | |
526 | // Returns the floating point format of a float. |
527 | inline float_format_t float_format (const cl_F& x) |
528 | { return (float_format_t) float_digits(x); } |
529 | |
530 | |
531 | // integer_decode_float(x) liefert zu einem Float x: (integer-decode-float x). |
532 | // x = 0.0 liefert (0, 0, 1). |
533 | // x = (-1)^s * 2^e * m bei Float-Precision p liefert |
534 | // (Mantisse 2^p * m als Integer, e-p als Integer, (-1)^s als Fixnum). |
535 | extern const cl_idecoded_float integer_decode_float (const cl_F& x); |
536 | |
537 | |
538 | // rational(x) liefert (rational x), wo x ein Float ist. |
539 | extern const cl_RA rational (const cl_F& x); |
540 | |
541 | |
542 | // scale_float(x,delta) liefert x*2^delta, wo x ein Float ist. |
543 | extern const cl_F scale_float (const cl_F& x, sintC delta); |
544 | extern const cl_F scale_float (const cl_F& x, const cl_I& delta); |
545 | |
546 | |
547 | // max(x,y) liefert (max x y), wo x und y Floats sind. |
548 | extern const cl_F max (const cl_F& x, const cl_F& y); |
549 | |
550 | // min(x,y) liefert (min x y), wo x und y Floats sind. |
551 | extern const cl_F min (const cl_F& x, const cl_F& y); |
552 | |
553 | // signum(x) liefert (signum x), wo x ein Float ist. |
554 | extern const cl_F signum (const cl_F& x); |
555 | |
556 | |
557 | // Returns the largest (most positive) floating point number in float format f. |
558 | extern const cl_F most_positive_float (float_format_t f); |
559 | |
560 | // Returns the smallest (most negative) floating point number in float format f. |
561 | extern const cl_F most_negative_float (float_format_t f); |
562 | |
563 | // Returns the least positive floating point number (i.e. > 0 but closest to 0) |
564 | // in float format f. |
565 | extern const cl_F least_positive_float (float_format_t f); |
566 | |
567 | // Returns the least negative floating point number (i.e. < 0 but closest to 0) |
568 | // in float format f. |
569 | extern const cl_F least_negative_float (float_format_t f); |
570 | |
571 | // Returns the smallest floating point number e > 0 such that 1+e != 1. |
572 | extern const cl_F float_epsilon (float_format_t f); |
573 | |
574 | // Returns the smallest floating point number e > 0 such that 1-e != 1. |
575 | extern const cl_F float_negative_epsilon (float_format_t f); |
576 | |
577 | |
578 | // Konversion zu einem C "float". |
579 | extern float float_approx (const cl_F& x); |
580 | |
581 | // Konversion zu einem C "double". |
582 | extern double double_approx (const cl_F& x); |
583 | |
584 | |
585 | // Transcendental functions |
586 | |
587 | |
588 | // pi(y) liefert die Zahl pi im selben Float-Format wie y. |
589 | // > y: ein Float |
590 | extern const cl_F pi (const cl_F& y); |
591 | |
592 | // pi(y) liefert die Zahl pi im Float-Format f. |
593 | // > f: eine Float-Format-Spezifikation |
594 | extern const cl_F pi (float_format_t f); |
595 | |
596 | // pi() liefert die Zahl pi im Default-Float-Format. |
597 | extern const cl_F pi (void); |
598 | |
599 | |
600 | // sin(x) liefert den Sinus (sin x) eines Float x. |
601 | extern const cl_F sin (const cl_F& x); |
602 | |
603 | // cos(x) liefert den Cosinus (cos x) eines Float x. |
604 | extern const cl_F cos (const cl_F& x); |
605 | |
606 | // Return type for cos_sin(): |
607 | struct cos_sin_t { |
608 | cl_R cos; |
609 | cl_R sin; |
610 | // Constructor: |
611 | cos_sin_t () {} |
612 | cos_sin_t (const cl_R& u, const cl_R& v) : cos (u), sin (v) {} |
613 | }; |
614 | |
615 | // cos_sin(x) liefert ((cos x),(sin x)), beide Werte. |
616 | extern const cos_sin_t cos_sin (const cl_F& x); |
617 | |
618 | // tan(x) liefert den Tangens (tan x) eines Float x. |
619 | extern const cl_F tan (const cl_F& x); |
620 | |
621 | |
622 | // exp1(y) liefert die Zahl e = exp(1) im selben Float-Format wie y. |
623 | // > y: ein Float |
624 | extern const cl_F exp1 (const cl_F& y); |
625 | |
626 | // exp1(y) liefert die Zahl e = exp(1) im Float-Format f. |
627 | // > f: eine Float-Format-Spezifikation |
628 | extern const cl_F exp1 (float_format_t f); |
629 | |
630 | // exp1() liefert die Zahl e = exp(1) im Default-Float-Format. |
631 | extern const cl_F exp1 (void); |
632 | |
633 | |
634 | // ln(x) liefert zu einem Float x>0 die Zahl ln(x). |
635 | extern const cl_F ln (const cl_F& x); |
636 | // Spezialfall: x Long-Float -> Ergebnis Long-Float |
637 | inline const cl_LF ln (const cl_LF& x) { return The(cl_LF)(ln(The(cl_F)(x))); } |
638 | |
639 | // exp(x) liefert zu einem Float x die Zahl exp(x). |
640 | extern const cl_F exp (const cl_F& x); |
641 | |
642 | // sinh(x) liefert zu einem Float x die Zahl sinh(x). |
643 | extern const cl_F sinh (const cl_F& x); |
644 | |
645 | // cosh(x) liefert zu einem Float x die Zahl cosh(x). |
646 | extern const cl_F cosh (const cl_F& x); |
647 | |
648 | // Return type for cosh_sinh(): |
649 | struct cosh_sinh_t { |
650 | cl_R cosh; |
651 | cl_R sinh; |
652 | // Constructor: |
653 | cosh_sinh_t () {} |
654 | cosh_sinh_t (const cl_R& u, const cl_R& v) : cosh (u), sinh (v) {} |
655 | }; |
656 | |
657 | // cosh_sinh(x) liefert ((cosh x),(sinh x)), beide Werte. |
658 | extern const cosh_sinh_t cosh_sinh (const cl_F& x); |
659 | |
660 | // tanh(x) liefert zu einem Float x die Zahl tanh(x). |
661 | extern const cl_F tanh (const cl_F& x); |
662 | |
663 | |
664 | // eulerconst(y) liefert die Eulersche Konstante |
665 | // im selben Float-Format wie y. |
666 | // > y: ein Float |
667 | extern const cl_F eulerconst (const cl_F& y); |
668 | |
669 | // eulerconst(y) liefert die Eulersche Konstante im Float-Format f. |
670 | // > f: eine Float-Format-Spezifikation |
671 | extern const cl_F eulerconst (float_format_t f); |
672 | |
673 | // eulerconst() liefert die Eulersche Konstante im Default-Float-Format. |
674 | extern const cl_F eulerconst (void); |
675 | |
676 | // catalanconst(y) liefert die Catalansche Konstante |
677 | // im selben Float-Format wie y. |
678 | // > y: ein Float |
679 | extern const cl_F catalanconst (const cl_F& y); |
680 | |
681 | // catalanconst(y) liefert die Catalansche Konstante im Float-Format f. |
682 | // > f: eine Float-Format-Spezifikation |
683 | extern const cl_F catalanconst (float_format_t f); |
684 | |
685 | // catalanconst() liefert die Catalansche Konstante im Default-Float-Format. |
686 | extern const cl_F catalanconst (void); |
687 | |
688 | // zeta(s) returns the Riemann zeta function at s>1. |
689 | extern const cl_F zeta (int s, const cl_F& y); |
690 | extern const cl_F zeta (int s, float_format_t f); |
691 | extern const cl_F zeta (int s); |
692 | |
693 | |
694 | // random_F(randomstate,n) liefert zu einem Float n>0 ein zufälliges |
695 | // Float x mit 0 <= x < n. |
696 | // > randomstate: ein Random-State, wird verändert |
697 | extern const cl_F random_F (random_state& randomstate, const cl_F& n); |
698 | |
699 | inline const cl_F random_F (const cl_F& n) |
700 | { return random_F(default_random_state,n); } |
701 | |
702 | |
703 | // This could be optimized to use in-place operations. |
704 | inline cl_F& operator+= (cl_F& x, const cl_F& y) { return x = x + y; } |
705 | inline cl_F& operator+= (cl_F& x, const float y) { return x = x + y; } |
706 | inline cl_F& operator+= (cl_F& x, const double y) { return x = x + y; } |
707 | inline cl_F& operator++ /* prefix */ (cl_F& x) { return x = plus1(x); } |
708 | inline void operator++ /* postfix */ (cl_F& x, int dummy) { (void)dummy; x = plus1(x); } |
709 | inline cl_F& operator-= (cl_F& x, const cl_F& y) { return x = x - y; } |
710 | inline cl_F& operator-= (cl_F& x, const float y) { return x = x - y; } |
711 | inline cl_F& operator-= (cl_F& x, const double y) { return x = x - y; } |
712 | inline cl_F& operator-- /* prefix */ (cl_F& x) { return x = minus1(x); } |
713 | inline void operator-- /* postfix */ (cl_F& x, int dummy) { (void)dummy; x = minus1(x); } |
714 | inline cl_F& operator*= (cl_F& x, const cl_F& y) { return x = x * y; } |
715 | inline cl_F& operator*= (cl_F& x, const float y) { return x = x * y; } |
716 | inline cl_F& operator*= (cl_F& x, const double y) { return x = x * y; } |
717 | inline cl_F& operator/= (cl_F& x, const cl_F& y) { return x = x / y; } |
718 | inline cl_F& operator/= (cl_F& x, const float y) { return x = x / y; } |
719 | inline cl_F& operator/= (cl_F& x, const double y) { return x = x / y; } |
720 | |
721 | // Thrown when a floating-point exception occurs. |
722 | class floating_point_exception : public runtime_exception { |
723 | public: |
724 | explicit floating_point_exception(const std::string & what) |
725 | : runtime_exception(what) {} |
726 | }; |
727 | |
728 | // Thrown when NaN occurs. |
729 | class floating_point_nan_exception : public floating_point_exception { |
730 | public: |
731 | floating_point_nan_exception(); |
732 | }; |
733 | |
734 | // Thrown when overflow occurs. |
735 | class floating_point_overflow_exception : public floating_point_exception { |
736 | public: |
737 | floating_point_overflow_exception(); |
738 | }; |
739 | |
740 | // Thrown when underflow occurs. |
741 | class floating_point_underflow_exception : public floating_point_exception { |
742 | public: |
743 | floating_point_underflow_exception(); |
744 | }; |
745 | |
746 | |
747 | |
748 | |
749 | // If this is true, floating point underflow returns zero instead of throwing an exception. |
750 | extern bool cl_inhibit_floating_point_underflow; |
751 | |
752 | } // namespace cln |
753 | |
754 | #endif /* _CL_FLOAT_H */ |
755 | |