261226c55366c8ec98e99c750b358c4e85d09391
[sfpy.git] / sfpy / float.pyx
1 from libc.stdint cimport *
2 cimport cfloat
3
4
5 # low-level access to rounding modes
6
7 ROUND_NEAREST_EVEN = cfloat.softfloat_round_near_even
8 ROUND_TO_ZERO = cfloat.softfloat_round_minMag
9 ROUND_DOWN = cfloat.softfloat_round_min
10 ROUND_UP = cfloat.softfloat_round_max
11 ROUND_NEAREST_AWAY = cfloat.softfloat_round_near_maxMag
12
13 cpdef uint_fast8_t round_get_mode():
14 return cfloat.softfloat_roundingMode
15
16 cpdef void round_set_mode(uint_fast8_t mode):
17 cfloat.softfloat_roundingMode = mode
18
19 cpdef bint round_is_nearest_even():
20 return cfloat.softfloat_roundingMode == cfloat.softfloat_round_near_even
21
22 cpdef void round_set_nearest_even():
23 cfloat.softfloat_roundingMode = cfloat.softfloat_round_near_even
24
25 cpdef bint round_is_to_zero():
26 return cfloat.softfloat_roundingMode == cfloat.softfloat_round_minMag
27
28 cpdef void round_set_to_zero():
29 cfloat.softfloat_roundingMode = cfloat.softfloat_round_minMag
30
31 cpdef bint round_is_down():
32 return cfloat.softfloat_roundingMode == cfloat.softfloat_round_min
33
34 cpdef void round_set_down():
35 cfloat.softfloat_roundingMode = cfloat.softfloat_round_min
36
37 cpdef bint round_is_up():
38 return cfloat.softfloat_roundingMode == cfloat.softfloat_round_max
39
40 cpdef void round_set_up():
41 cfloat.softfloat_roundingMode = cfloat.softfloat_round_max
42
43 cpdef bint round_is_nearest_away():
44 return cfloat.softfloat_roundingMode == cfloat.softfloat_round_near_maxMag
45
46 cpdef void round_set_nearest_away():
47 cfloat.softfloat_roundingMode = cfloat.softfloat_round_near_maxMag
48
49
50 # low-level access to exception flags
51
52 FLAG_INEXACT = cfloat.softfloat_flag_inexact
53 FLAG_UNDERFLOW = cfloat.softfloat_flag_underflow
54 FLAG_OVERFLOW = cfloat.softfloat_flag_overflow
55 FLAG_INFINITE = cfloat.softfloat_flag_infinite
56 FLAG_INVALID = cfloat.softfloat_flag_invalid
57
58 cpdef uint_fast8_t flag_get():
59 return cfloat.softfloat_exceptionFlags
60
61 cpdef void flag_set(uint_fast8_t flags):
62 cfloat.softfloat_exceptionFlags = flags
63
64 cpdef void flag_reset():
65 cfloat.softfloat_exceptionFlags = 0
66
67 cpdef bint flag_get_inexact():
68 return (cfloat.softfloat_exceptionFlags & cfloat.softfloat_flag_inexact) != 0
69
70 cpdef void flag_raise_inexact():
71 cfloat.softfloat_raiseFlags(cfloat.softfloat_flag_inexact)
72
73 cpdef void flag_clear_inexact():
74 cfloat.softfloat_exceptionFlags &= ~cfloat.softfloat_flag_inexact
75
76 cpdef bint flag_get_underflow():
77 return (cfloat.softfloat_exceptionFlags & cfloat.softfloat_flag_underflow) != 0
78
79 cpdef void flag_raise_underflow():
80 cfloat.softfloat_raiseFlags(cfloat.softfloat_flag_underflow)
81
82 cpdef void flag_clear_underflow():
83 cfloat.softfloat_exceptionFlags &= ~cfloat.softfloat_flag_underflow
84
85 cpdef bint flag_get_overflow():
86 return (cfloat.softfloat_exceptionFlags & cfloat.softfloat_flag_overflow) != 0
87
88 cpdef void flag_raise_overflow():
89 cfloat.softfloat_raiseFlags(cfloat.softfloat_flag_overflow)
90
91 cpdef void flag_clear_overflow():
92 cfloat.softfloat_exceptionFlags &= ~cfloat.softfloat_flag_overflow
93
94 cpdef bint flag_get_infinite():
95 return (cfloat.softfloat_exceptionFlags & cfloat.softfloat_flag_infinite) != 0
96
97 cpdef void flag_raise_infinite():
98 cfloat.softfloat_raiseFlags(cfloat.softfloat_flag_infinite)
99
100 cpdef void flag_clear_infinite():
101 cfloat.softfloat_exceptionFlags &= ~cfloat.softfloat_flag_infinite
102
103 cpdef bint flag_get_invalid():
104 return (cfloat.softfloat_exceptionFlags & cfloat.softfloat_flag_invalid) != 0
105
106 cpdef void flag_raise_invalid():
107 cfloat.softfloat_raiseFlags(cfloat.softfloat_flag_invalid)
108
109 cpdef void flag_clear_invalid():
110 cfloat.softfloat_exceptionFlags &= ~cfloat.softfloat_flag_invalid
111
112
113 cdef class Float16:
114
115 # the wrapped float value
116 cdef cfloat.float16_t _c_float
117
118 # factory function constructors that bypass __init__
119
120 @staticmethod
121 cdef Float16 from_c_float(cfloat.float16_t f):
122 """Factory function to create a Float16 object directly from
123 a C float16_t.
124 """
125 cdef Float16 obj = Float16.__new__(Float16)
126 obj._c_float = f
127 return obj
128
129 @staticmethod
130 def from_bits(uint16_t value):
131 """Factory function to create a Float16 object from a bit pattern
132 represented as an integer.
133 """
134 cdef Float16 obj = Float16.__new__(Float16)
135 obj._c_float.v = value
136 return obj
137
138 @staticmethod
139 def from_double(double value):
140 """Factory function to create a Float16 object from a double.
141 """
142 cdef Float16 obj = Float16.__new__(Float16)
143 cdef cfloat.ui64_double ud
144 cdef cfloat.float64_t d
145
146 ud.d = value
147 d.v = ud.u
148 obj._c_float = cfloat.f64_to_f16(d)
149
150 return obj
151
152 # convenience interface for use inside Python
153
154 def __init__(self, value):
155 cdef cfloat.ui64_double ud
156 cdef cfloat.float64_t d
157
158 if isinstance(value, int):
159 self._c_float.v = value
160 else:
161 ud.d = float(value)
162 d.v = ud.u
163 self._c_float = cfloat.f64_to_f16(d)
164
165 def __float__(self):
166 cdef cfloat.ui64_double ud
167 ud.u = cfloat.f16_to_f64(self._c_float).v
168 return ud.d
169
170 def __int__(self):
171 cdef cfloat.ui64_double ud
172 ud.u = cfloat.f16_to_f64(self._c_float).v
173 return int(ud.d)
174
175 def __str__(self):
176 cdef cfloat.ui64_double ud
177 ud.u = cfloat.f16_to_f64(self._c_float).v
178 return repr(ud.d)
179
180 def __repr__(self):
181 cdef cfloat.ui64_double ud
182 ud.u = cfloat.f16_to_f64(self._c_float).v
183 return 'Float16(' + repr(ud.d) + ')'
184
185 cpdef uint16_t get_bits(self):
186 return self._c_float.v
187 bits = property(get_bits)
188
189 # arithmetic
190
191 cpdef Float16 round_to(self, uint_fast8_t rm, bint exact):
192 cdef cfloat.float16_t f = cfloat.f16_roundToInt(self._c_float, rm, exact)
193 return Float16.from_c_float(f)
194
195 cpdef Float16 round(self):
196 cdef cfloat.float16_t f = cfloat.f16_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True)
197 return Float16.from_c_float(f)
198
199 def __round__(self):
200 return self.round()
201
202 cpdef Float16 add(self, Float16 other):
203 cdef cfloat.float16_t f = cfloat.f16_add(self._c_float, other._c_float)
204 return Float16.from_c_float(f)
205
206 def __add__(self, Float16 other):
207 return self.add(other)
208
209 cpdef Float16 sub(self, Float16 other):
210 cdef cfloat.float16_t f = cfloat.f16_sub(self._c_float, other._c_float)
211 return Float16.from_c_float(f)
212
213 def __sub__(self, Float16 other):
214 return self.sub(other)
215
216 cpdef Float16 mul(self, Float16 other):
217 cdef cfloat.float16_t f = cfloat.f16_mul(self._c_float, other._c_float)
218 return Float16.from_c_float(f)
219
220 def __mul__(self, Float16 other):
221 return self.mul(other)
222
223 cpdef Float16 fma(self, Float16 a2, Float16 a3):
224 cdef cfloat.float16_t f = cfloat.f16_mulAdd(self._c_float, a2._c_float, a3._c_float)
225 return Float16.from_c_float(f)
226
227 cpdef Float16 qma(self, Float16 a1, Float16 a2):
228 cdef cfloat.float16_t f = cfloat.f16_mulAdd(a1._c_float, a2._c_float, self._c_float)
229 return Float16.from_c_float(f)
230
231 cpdef Float16 div(self, Float16 other):
232 cdef cfloat.float16_t f = cfloat.f16_div(self._c_float, other._c_float)
233 return Float16.from_c_float(f)
234
235 def __truediv__(self, Float16 other):
236 return self.div(other)
237
238 cpdef Float16 rem(self, Float16 other):
239 cdef cfloat.float16_t f = cfloat.f16_rem(self._c_float, other._c_float)
240 return Float16.from_c_float(f)
241
242 cpdef Float16 sqrt(self):
243 cdef cfloat.float16_t f = cfloat.f16_sqrt(self._c_float)
244 return Float16.from_c_float(f)
245
246 # in-place arithmetic
247
248 cpdef void iround_to(self, uint_fast8_t rm, bint exact):
249 self._c_float = cfloat.f16_roundToInt(self._c_float, rm, exact)
250
251 cpdef void iround(self):
252 self._c_float = cfloat.f16_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True)
253
254 cpdef void iadd(self, Float16 other):
255 self._c_float = cfloat.f16_add(self._c_float, other._c_float)
256
257 def __iadd__(self, Float16 other):
258 self.iadd(other)
259 return self
260
261 cpdef void isub(self, Float16 other):
262 self._c_float = cfloat.f16_sub(self._c_float, other._c_float)
263
264 def __isub__(self, Float16 other):
265 self.isub(other)
266 return self
267
268 cpdef void imul(self, Float16 other):
269 self._c_float = cfloat.f16_mul(self._c_float, other._c_float)
270
271 def __imul__(self, Float16 other):
272 self.imul(other)
273 return self
274
275 cpdef void ifma(self, Float16 a2, Float16 a3):
276 self._c_float = cfloat.f16_mulAdd(self._c_float, a2._c_float, a3._c_float)
277
278 cpdef void iqma(self, Float16 a1, Float16 a2):
279 self._c_float = cfloat.f16_mulAdd(a1._c_float, a2._c_float, self._c_float)
280
281 cpdef void idiv(self, Float16 other):
282 self._c_float = cfloat.f16_div(self._c_float, other._c_float)
283
284 def __itruediv__(self, Float16 other):
285 self.idiv(other)
286 return self
287
288 cpdef void irem(self, Float16 other):
289 self._c_float = cfloat.f16_rem(self._c_float, other._c_float)
290
291 cpdef void isqrt(self):
292 self._c_float = cfloat.f16_sqrt(self._c_float)
293
294 # comparison
295
296 cpdef bint eq(self, Float16 other):
297 return cfloat.f16_eq(self._c_float, other._c_float)
298
299 cpdef bint le(self, Float16 other):
300 return cfloat.f16_le(self._c_float, other._c_float)
301
302 cpdef bint lt(self, Float16 other):
303 return cfloat.f16_lt(self._c_float, other._c_float)
304
305 def __lt__(self, Float16 other):
306 return self.lt(other)
307
308 def __le__(self, Float16 other):
309 return self.le(other)
310
311 def __eq__(self, Float16 other):
312 return self.eq(other)
313
314 def __ne__(self, Float16 other):
315 return not self.eq(other)
316
317 def __ge__(self, Float16 other):
318 return other.le(self)
319
320 def __gt__(self, Float16 other):
321 return other.lt(self)
322
323 # conversion to other float types
324
325 cpdef Float32 to_f32(self):
326 cdef cfloat.float32_t f = cfloat.f16_to_f32(self._c_float)
327 return Float32.from_c_float(f)
328
329 cpdef Float64 to_f64(self):
330 cdef cfloat.float64_t f = cfloat.f16_to_f64(self._c_float)
331 return Float64.from_c_float(f)
332
333
334 # external, non-method arithmetic
335
336 cpdef Float16 f16_round_to(Float16 a1, uint_fast8_t rm, bint exact):
337 cdef cfloat.float16_t f = cfloat.f16_roundToInt(a1._c_float, rm, exact)
338 return Float16.from_c_float(f)
339
340 cpdef Float16 f16_round(Float16 a1):
341 cdef cfloat.float16_t f = cfloat.f16_roundToInt(a1._c_float, cfloat.softfloat_roundingMode, True)
342 return Float16.from_c_float(f)
343
344 cpdef Float16 f16_add(Float16 a1, Float16 a2):
345 cdef cfloat.float16_t f = cfloat.f16_add(a1._c_float, a2._c_float)
346 return Float16.from_c_float(f)
347
348 cpdef Float16 f16_sub(Float16 a1, Float16 a2):
349 cdef cfloat.float16_t f = cfloat.f16_sub(a1._c_float, a2._c_float)
350 return Float16.from_c_float(f)
351
352 cpdef Float16 f16_mul(Float16 a1, Float16 a2):
353 cdef cfloat.float16_t f = cfloat.f16_mul(a1._c_float, a2._c_float)
354 return Float16.from_c_float(f)
355
356 cpdef Float16 f16_fma(Float16 a1, Float16 a2, Float16 a3):
357 cdef cfloat.float16_t f = cfloat.f16_mulAdd(a1._c_float, a2._c_float, a3._c_float)
358 return Float16.from_c_float(f)
359
360 cpdef Float16 f16_qma(Float16 a3, Float16 a1, Float16 a2):
361 cdef cfloat.float16_t f = cfloat.f16_mulAdd(a1._c_float, a2._c_float, a3._c_float)
362 return Float16.from_c_float(f)
363
364 cpdef Float16 f16_div(Float16 a1, Float16 a2):
365 cdef cfloat.float16_t f = cfloat.f16_div(a1._c_float, a2._c_float)
366 return Float16.from_c_float(f)
367
368 cpdef Float16 f16_rem(Float16 a1, Float16 a2):
369 cdef cfloat.float16_t f = cfloat.f16_rem(a1._c_float, a2._c_float)
370 return Float16.from_c_float(f)
371
372 cpdef Float16 f16_sqrt(Float16 a1):
373 cdef cfloat.float16_t f = cfloat.f16_sqrt(a1._c_float)
374 return Float16.from_c_float(f)
375
376 cpdef bint f16_eq(Float16 a1, Float16 a2):
377 return cfloat.f16_eq(a1._c_float, a2._c_float)
378
379 cpdef bint f16_le(Float16 a1, Float16 a2):
380 return cfloat.f16_le(a1._c_float, a2._c_float)
381
382 cpdef bint f16_lt(Float16 a1, Float16 a2):
383 return cfloat.f16_lt(a1._c_float, a2._c_float)
384
385 cpdef Float32 f16_to_f32(Float16 a1):
386 cdef cfloat.float32_t f = cfloat.f16_to_f32(a1._c_float)
387 return Float32.from_c_float(f)
388
389 cpdef Float64 f16_to_f64(Float16 a1):
390 cdef cfloat.float64_t f = cfloat.f16_to_f64(a1._c_float)
391 return Float64.from_c_float(f)
392
393
394 cdef class Float32:
395
396 # the wrapped float value
397 cdef cfloat.float32_t _c_float
398
399 # factory function constructors that bypass __init__
400
401 @staticmethod
402 cdef Float32 from_c_float(cfloat.float32_t f):
403 """Factory function to create a Float32 object directly from
404 a C float32_t.
405 """
406 cdef Float32 obj = Float32.__new__(Float32)
407 obj._c_float = f
408 return obj
409
410 @staticmethod
411 def from_bits(uint32_t value):
412 """Factory function to create a Float32 object from a bit pattern
413 represented as an integer.
414 """
415 cdef Float32 obj = Float32.__new__(Float32)
416 obj._c_float.v = value
417 return obj
418
419 @staticmethod
420 def from_double(double value):
421 """Factory function to create a Float32 object from a double.
422 """
423 cdef Float32 obj = Float32.__new__(Float32)
424 cdef cfloat.ui64_double ud
425 cdef cfloat.float64_t d
426
427 ud.d = value
428 d.v = ud.u
429 obj._c_float = cfloat.f64_to_f32(d)
430
431 return obj
432
433 # convenience interface for use inside Python
434
435 def __init__(self, value):
436 cdef cfloat.ui64_double ud
437 cdef cfloat.float64_t d
438
439 if isinstance(value, int):
440 self._c_float.v = value
441 else:
442 ud.d = float(value)
443 d.v = ud.u
444 self._c_float = cfloat.f64_to_f32(d)
445
446 def __float__(self):
447 cdef cfloat.ui64_double ud
448 ud.u = cfloat.f32_to_f64(self._c_float).v
449 return ud.d
450
451 def __int__(self):
452 cdef cfloat.ui64_double ud
453 ud.u = cfloat.f32_to_f64(self._c_float).v
454 return int(ud.d)
455
456 def __str__(self):
457 cdef cfloat.ui64_double ud
458 ud.u = cfloat.f32_to_f64(self._c_float).v
459 return repr(ud.d)
460
461 def __repr__(self):
462 cdef cfloat.ui64_double ud
463 ud.u = cfloat.f32_to_f64(self._c_float).v
464 return 'Float32(' + repr(ud.d) + ')'
465
466 cpdef uint32_t get_bits(self):
467 return self._c_float.v
468 bits = property(get_bits)
469
470 # arithmetic
471
472 cpdef Float32 round_to(self, uint_fast8_t rm, bint exact):
473 cdef cfloat.float32_t f = cfloat.f32_roundToInt(self._c_float, rm, exact)
474 return Float32.from_c_float(f)
475
476 cpdef Float32 round(self):
477 cdef cfloat.float32_t f = cfloat.f32_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True)
478 return Float32.from_c_float(f)
479
480 def __round__(self):
481 return self.round()
482
483 cpdef Float32 add(self, Float32 other):
484 cdef cfloat.float32_t f = cfloat.f32_add(self._c_float, other._c_float)
485 return Float32.from_c_float(f)
486
487 def __add__(self, Float32 other):
488 return self.add(other)
489
490 cpdef Float32 sub(self, Float32 other):
491 cdef cfloat.float32_t f = cfloat.f32_sub(self._c_float, other._c_float)
492 return Float32.from_c_float(f)
493
494 def __sub__(self, Float32 other):
495 return self.sub(other)
496
497 cpdef Float32 mul(self, Float32 other):
498 cdef cfloat.float32_t f = cfloat.f32_mul(self._c_float, other._c_float)
499 return Float32.from_c_float(f)
500
501 def __mul__(self, Float32 other):
502 return self.mul(other)
503
504 cpdef Float32 fma(self, Float32 a2, Float32 a3):
505 cdef cfloat.float32_t f = cfloat.f32_mulAdd(self._c_float, a2._c_float, a3._c_float)
506 return Float32.from_c_float(f)
507
508 cpdef Float32 qma(self, Float32 a1, Float32 a2):
509 cdef cfloat.float32_t f = cfloat.f32_mulAdd(a1._c_float, a2._c_float, self._c_float)
510 return Float32.from_c_float(f)
511
512 cpdef Float32 div(self, Float32 other):
513 cdef cfloat.float32_t f = cfloat.f32_div(self._c_float, other._c_float)
514 return Float32.from_c_float(f)
515
516 def __truediv__(self, Float32 other):
517 return self.div(other)
518
519 cpdef Float32 rem(self, Float32 other):
520 cdef cfloat.float32_t f = cfloat.f32_rem(self._c_float, other._c_float)
521 return Float32.from_c_float(f)
522
523 cpdef Float32 sqrt(self):
524 cdef cfloat.float32_t f = cfloat.f32_sqrt(self._c_float)
525 return Float32.from_c_float(f)
526
527 # in-place arithmetic
528
529 cpdef void iround_to(self, uint_fast8_t rm, bint exact):
530 self._c_float = cfloat.f32_roundToInt(self._c_float, rm, exact)
531
532 cpdef void iround(self):
533 self._c_float = cfloat.f32_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True)
534
535 cpdef void iadd(self, Float32 other):
536 self._c_float = cfloat.f32_add(self._c_float, other._c_float)
537
538 def __iadd__(self, Float32 other):
539 self.iadd(other)
540 return self
541
542 cpdef void isub(self, Float32 other):
543 self._c_float = cfloat.f32_sub(self._c_float, other._c_float)
544
545 def __isub__(self, Float32 other):
546 self.isub(other)
547 return self
548
549 cpdef void imul(self, Float32 other):
550 self._c_float = cfloat.f32_mul(self._c_float, other._c_float)
551
552 def __imul__(self, Float32 other):
553 self.imul(other)
554 return self
555
556 cpdef void ifma(self, Float32 a2, Float32 a3):
557 self._c_float = cfloat.f32_mulAdd(self._c_float, a2._c_float, a3._c_float)
558
559 cpdef void iqma(self, Float32 a1, Float32 a2):
560 self._c_float = cfloat.f32_mulAdd(a1._c_float, a2._c_float, self._c_float)
561
562 cpdef void idiv(self, Float32 other):
563 self._c_float = cfloat.f32_div(self._c_float, other._c_float)
564
565 def __itruediv__(self, Float32 other):
566 self.idiv(other)
567 return self
568
569 cpdef void irem(self, Float32 other):
570 self._c_float = cfloat.f32_rem(self._c_float, other._c_float)
571
572 cpdef void isqrt(self):
573 self._c_float = cfloat.f32_sqrt(self._c_float)
574
575 # comparison
576
577 cpdef bint eq(self, Float32 other):
578 return cfloat.f32_eq(self._c_float, other._c_float)
579
580 cpdef bint le(self, Float32 other):
581 return cfloat.f32_le(self._c_float, other._c_float)
582
583 cpdef bint lt(self, Float32 other):
584 return cfloat.f32_lt(self._c_float, other._c_float)
585
586 def __lt__(self, Float32 other):
587 return self.lt(other)
588
589 def __le__(self, Float32 other):
590 return self.le(other)
591
592 def __eq__(self, Float32 other):
593 return self.eq(other)
594
595 def __ne__(self, Float32 other):
596 return not self.eq(other)
597
598 def __ge__(self, Float32 other):
599 return other.le(self)
600
601 def __gt__(self, Float32 other):
602 return other.lt(self)
603
604 # conversion to other float types
605
606 cpdef Float16 to_f16(self):
607 cdef cfloat.float16_t f = cfloat.f32_to_f16(self._c_float)
608 return Float16.from_c_float(f)
609
610 cpdef Float64 to_f64(self):
611 cdef cfloat.float64_t f = cfloat.f32_to_f64(self._c_float)
612 return Float64.from_c_float(f)
613
614
615 # external, non-method arithmetic
616
617 cpdef Float32 f32_round_to(Float32 a1, uint_fast8_t rm, bint exact):
618 cdef cfloat.float32_t f = cfloat.f32_roundToInt(a1._c_float, rm, exact)
619 return Float32.from_c_float(f)
620
621 cpdef Float32 f32_round(Float32 a1):
622 cdef cfloat.float32_t f = cfloat.f32_roundToInt(a1._c_float, cfloat.softfloat_roundingMode, True)
623 return Float32.from_c_float(f)
624
625 cpdef Float32 f32_add(Float32 a1, Float32 a2):
626 cdef cfloat.float32_t f = cfloat.f32_add(a1._c_float, a2._c_float)
627 return Float32.from_c_float(f)
628
629 cpdef Float32 f32_sub(Float32 a1, Float32 a2):
630 cdef cfloat.float32_t f = cfloat.f32_sub(a1._c_float, a2._c_float)
631 return Float32.from_c_float(f)
632
633 cpdef Float32 f32_mul(Float32 a1, Float32 a2):
634 cdef cfloat.float32_t f = cfloat.f32_mul(a1._c_float, a2._c_float)
635 return Float32.from_c_float(f)
636
637 cpdef Float32 f32_fma(Float32 a1, Float32 a2, Float32 a3):
638 cdef cfloat.float32_t f = cfloat.f32_mulAdd(a1._c_float, a2._c_float, a3._c_float)
639 return Float32.from_c_float(f)
640
641 cpdef Float32 f32_qma(Float32 a3, Float32 a1, Float32 a2):
642 cdef cfloat.float32_t f = cfloat.f32_mulAdd(a1._c_float, a2._c_float, a3._c_float)
643 return Float32.from_c_float(f)
644
645 cpdef Float32 f32_div(Float32 a1, Float32 a2):
646 cdef cfloat.float32_t f = cfloat.f32_div(a1._c_float, a2._c_float)
647 return Float32.from_c_float(f)
648
649 cpdef Float32 f32_rem(Float32 a1, Float32 a2):
650 cdef cfloat.float32_t f = cfloat.f32_rem(a1._c_float, a2._c_float)
651 return Float32.from_c_float(f)
652
653 cpdef Float32 f32_sqrt(Float32 a1):
654 cdef cfloat.float32_t f = cfloat.f32_sqrt(a1._c_float)
655 return Float32.from_c_float(f)
656
657 cpdef bint f32_eq(Float32 a1, Float32 a2):
658 return cfloat.f32_eq(a1._c_float, a2._c_float)
659
660 cpdef bint f32_le(Float32 a1, Float32 a2):
661 return cfloat.f32_le(a1._c_float, a2._c_float)
662
663 cpdef bint f32_lt(Float32 a1, Float32 a2):
664 return cfloat.f32_lt(a1._c_float, a2._c_float)
665
666 cpdef Float16 f32_to_f16(Float32 a1):
667 cdef cfloat.float16_t f = cfloat.f32_to_f16(a1._c_float)
668 return Float16.from_c_float(f)
669
670 cpdef Float64 f32_to_f64(Float32 a1):
671 cdef cfloat.float64_t f = cfloat.f32_to_f64(a1._c_float)
672 return Float64.from_c_float(f)
673
674
675 cdef class Float64:
676
677 # the wrapped float value
678 cdef cfloat.float64_t _c_float
679
680 # factory function constructors that bypass __init__
681
682 @staticmethod
683 cdef Float64 from_c_float(cfloat.float64_t f):
684 """Factory function to create a Float64 object directly from
685 a C float64_t.
686 """
687 cdef Float64 obj = Float64.__new__(Float64)
688 obj._c_float = f
689 return obj
690
691 @staticmethod
692 def from_bits(uint64_t value):
693 """Factory function to create a Float64 object from a bit pattern
694 represented as an integer.
695 """
696 cdef Float64 obj = Float64.__new__(Float64)
697 obj._c_float.v = value
698 return obj
699
700 @staticmethod
701 def from_double(double value):
702 """Factory function to create a Float64 object from a double.
703 """
704 cdef Float64 obj = Float64.__new__(Float64)
705 cdef cfloat.ui64_double ud
706 cdef cfloat.float64_t d
707
708 ud.d = value
709 obj._c_float.v = ud.u
710
711 return obj
712
713 # convenience interface for use inside Python
714
715 def __init__(self, value):
716 cdef cfloat.ui64_double ud
717 cdef cfloat.float64_t d
718
719 if isinstance(value, int):
720 self._c_float.v = value
721 else:
722 ud.d = float(value)
723 self._c_float.v = ud.u
724
725 def __float__(self):
726 cdef cfloat.ui64_double ud
727 ud.u = self._c_float.v
728 return ud.d
729
730 def __int__(self):
731 cdef cfloat.ui64_double ud
732 ud.u = self._c_float.v
733 return int(ud.d)
734
735 def __str__(self):
736 cdef cfloat.ui64_double ud
737 ud.u = self._c_float.v
738 return repr(ud.d)
739
740 def __repr__(self):
741 cdef cfloat.ui64_double ud
742 ud.u = self._c_float.v
743 return 'Float64(' + repr(ud.d) + ')'
744
745 cpdef uint64_t get_bits(self):
746 return self._c_float.v
747 bits = property(get_bits)
748
749 # arithmetic
750
751 cpdef Float64 round_to(self, uint_fast8_t rm, bint exact):
752 cdef cfloat.float64_t f = cfloat.f64_roundToInt(self._c_float, rm, exact)
753 return Float64.from_c_float(f)
754
755 cpdef Float64 round(self):
756 cdef cfloat.float64_t f = cfloat.f64_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True)
757 return Float64.from_c_float(f)
758
759 def __round__(self):
760 return self.round()
761
762 cpdef Float64 add(self, Float64 other):
763 cdef cfloat.float64_t f = cfloat.f64_add(self._c_float, other._c_float)
764 return Float64.from_c_float(f)
765
766 def __add__(self, Float64 other):
767 return self.add(other)
768
769 cpdef Float64 sub(self, Float64 other):
770 cdef cfloat.float64_t f = cfloat.f64_sub(self._c_float, other._c_float)
771 return Float64.from_c_float(f)
772
773 def __sub__(self, Float64 other):
774 return self.sub(other)
775
776 cpdef Float64 mul(self, Float64 other):
777 cdef cfloat.float64_t f = cfloat.f64_mul(self._c_float, other._c_float)
778 return Float64.from_c_float(f)
779
780 def __mul__(self, Float64 other):
781 return self.mul(other)
782
783 cpdef Float64 fma(self, Float64 a2, Float64 a3):
784 cdef cfloat.float64_t f = cfloat.f64_mulAdd(self._c_float, a2._c_float, a3._c_float)
785 return Float64.from_c_float(f)
786
787 cpdef Float64 qma(self, Float64 a1, Float64 a2):
788 cdef cfloat.float64_t f = cfloat.f64_mulAdd(a1._c_float, a2._c_float, self._c_float)
789 return Float64.from_c_float(f)
790
791 cpdef Float64 div(self, Float64 other):
792 cdef cfloat.float64_t f = cfloat.f64_div(self._c_float, other._c_float)
793 return Float64.from_c_float(f)
794
795 def __truediv__(self, Float64 other):
796 return self.div(other)
797
798 cpdef Float64 rem(self, Float64 other):
799 cdef cfloat.float64_t f = cfloat.f64_rem(self._c_float, other._c_float)
800 return Float64.from_c_float(f)
801
802 cpdef Float64 sqrt(self):
803 cdef cfloat.float64_t f = cfloat.f64_sqrt(self._c_float)
804 return Float64.from_c_float(f)
805
806 # in-place arithmetic
807
808 cpdef void iround_to(self, uint_fast8_t rm, bint exact):
809 self._c_float = cfloat.f64_roundToInt(self._c_float, rm, exact)
810
811 cpdef void iround(self):
812 self._c_float = cfloat.f64_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True)
813
814 cpdef void iadd(self, Float64 other):
815 self._c_float = cfloat.f64_add(self._c_float, other._c_float)
816
817 def __iadd__(self, Float64 other):
818 self.iadd(other)
819 return self
820
821 cpdef void isub(self, Float64 other):
822 self._c_float = cfloat.f64_sub(self._c_float, other._c_float)
823
824 def __isub__(self, Float64 other):
825 self.isub(other)
826 return self
827
828 cpdef void imul(self, Float64 other):
829 self._c_float = cfloat.f64_mul(self._c_float, other._c_float)
830
831 def __imul__(self, Float64 other):
832 self.imul(other)
833 return self
834
835 cpdef void ifma(self, Float64 a2, Float64 a3):
836 self._c_float = cfloat.f64_mulAdd(self._c_float, a2._c_float, a3._c_float)
837
838 cpdef void iqma(self, Float64 a1, Float64 a2):
839 self._c_float = cfloat.f64_mulAdd(a1._c_float, a2._c_float, self._c_float)
840
841 cpdef void idiv(self, Float64 other):
842 self._c_float = cfloat.f64_div(self._c_float, other._c_float)
843
844 def __itruediv__(self, Float64 other):
845 self.idiv(other)
846 return self
847
848 cpdef void irem(self, Float64 other):
849 self._c_float = cfloat.f64_rem(self._c_float, other._c_float)
850
851 cpdef void isqrt(self):
852 self._c_float = cfloat.f64_sqrt(self._c_float)
853
854 # comparison
855
856 cpdef bint eq(self, Float64 other):
857 return cfloat.f64_eq(self._c_float, other._c_float)
858
859 cpdef bint le(self, Float64 other):
860 return cfloat.f64_le(self._c_float, other._c_float)
861
862 cpdef bint lt(self, Float64 other):
863 return cfloat.f64_lt(self._c_float, other._c_float)
864
865 def __lt__(self, Float64 other):
866 return self.lt(other)
867
868 def __le__(self, Float64 other):
869 return self.le(other)
870
871 def __eq__(self, Float64 other):
872 return self.eq(other)
873
874 def __ne__(self, Float64 other):
875 return not self.eq(other)
876
877 def __ge__(self, Float64 other):
878 return other.le(self)
879
880 def __gt__(self, Float64 other):
881 return other.lt(self)
882
883 # conversion to other float types
884
885 cpdef Float16 to_f16(self):
886 cdef cfloat.float16_t f = cfloat.f64_to_f16(self._c_float)
887 return Float16.from_c_float(f)
888
889 cpdef Float32 to_f32(self):
890 cdef cfloat.float32_t f = cfloat.f64_to_f32(self._c_float)
891 return Float32.from_c_float(f)
892
893
894 # external, non-method arithmetic
895
896 cpdef Float64 f64_round_to(Float64 a1, uint_fast8_t rm, bint exact):
897 cdef cfloat.float64_t f = cfloat.f64_roundToInt(a1._c_float, rm, exact)
898 return Float64.from_c_float(f)
899
900 cpdef Float64 f64_round(Float64 a1):
901 cdef cfloat.float64_t f = cfloat.f64_roundToInt(a1._c_float, cfloat.softfloat_roundingMode, True)
902 return Float64.from_c_float(f)
903
904 cpdef Float64 f64_add(Float64 a1, Float64 a2):
905 cdef cfloat.float64_t f = cfloat.f64_add(a1._c_float, a2._c_float)
906 return Float64.from_c_float(f)
907
908 cpdef Float64 f64_sub(Float64 a1, Float64 a2):
909 cdef cfloat.float64_t f = cfloat.f64_sub(a1._c_float, a2._c_float)
910 return Float64.from_c_float(f)
911
912 cpdef Float64 f64_mul(Float64 a1, Float64 a2):
913 cdef cfloat.float64_t f = cfloat.f64_mul(a1._c_float, a2._c_float)
914 return Float64.from_c_float(f)
915
916 cpdef Float64 f64_fma(Float64 a1, Float64 a2, Float64 a3):
917 cdef cfloat.float64_t f = cfloat.f64_mulAdd(a1._c_float, a2._c_float, a3._c_float)
918 return Float64.from_c_float(f)
919
920 cpdef Float64 f64_qma(Float64 a3, Float64 a1, Float64 a2):
921 cdef cfloat.float64_t f = cfloat.f64_mulAdd(a1._c_float, a2._c_float, a3._c_float)
922 return Float64.from_c_float(f)
923
924 cpdef Float64 f64_div(Float64 a1, Float64 a2):
925 cdef cfloat.float64_t f = cfloat.f64_div(a1._c_float, a2._c_float)
926 return Float64.from_c_float(f)
927
928 cpdef Float64 f64_rem(Float64 a1, Float64 a2):
929 cdef cfloat.float64_t f = cfloat.f64_rem(a1._c_float, a2._c_float)
930 return Float64.from_c_float(f)
931
932 cpdef Float64 f64_sqrt(Float64 a1):
933 cdef cfloat.float64_t f = cfloat.f64_sqrt(a1._c_float)
934 return Float64.from_c_float(f)
935
936 cpdef bint f64_eq(Float64 a1, Float64 a2):
937 return cfloat.f64_eq(a1._c_float, a2._c_float)
938
939 cpdef bint f64_le(Float64 a1, Float64 a2):
940 return cfloat.f64_le(a1._c_float, a2._c_float)
941
942 cpdef bint f64_lt(Float64 a1, Float64 a2):
943 return cfloat.f64_lt(a1._c_float, a2._c_float)
944
945 cpdef Float16 f64_to_f16(Float64 a1):
946 cdef cfloat.float16_t f = cfloat.f64_to_f16(a1._c_float)
947 return Float16.from_c_float(f)
948
949 cpdef Float32 f64_to_f32(Float64 a1):
950 cdef cfloat.float32_t f = cfloat.f64_to_f32(a1._c_float)
951 return Float32.from_c_float(f)