revise fma/qma interface to match SoftPosit
[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 # C helpers
114
115 cdef inline cfloat.float16_t _f16_neg(cfloat.float16_t f):
116 f.v ^= 0x8000
117 return f
118
119 cdef inline cfloat.float32_t _f32_neg(cfloat.float32_t f):
120 f.v ^= 0x80000000
121 return f
122
123 cdef inline cfloat.float64_t _f64_neg(cfloat.float64_t f):
124 f.v ^= 0x8000000000000000
125 return f
126
127 cdef inline cfloat.float16_t _f16_abs(cfloat.float16_t f):
128 f.v &= 0x7fff
129 return f
130
131 cdef inline cfloat.float32_t _f32_abs(cfloat.float32_t f):
132 f.v &= 0x7fffffff
133 return f
134
135 cdef inline cfloat.float64_t _f64_abs(cfloat.float64_t f):
136 f.v &= 0x7fffffffffffffff
137 return f
138
139
140 cdef class Float16:
141
142 # the wrapped float value
143 cdef cfloat.float16_t _c_float
144
145 # factory function constructors that bypass __init__
146
147 @staticmethod
148 cdef Float16 from_c_float(cfloat.float16_t f):
149 """Factory function to create a Float16 object directly from
150 a C float16_t.
151 """
152 cdef Float16 obj = Float16.__new__(Float16)
153 obj._c_float = f
154 return obj
155
156 @staticmethod
157 def from_bits(uint16_t value):
158 """Factory function to create a Float16 object from a bit pattern
159 represented as an integer.
160 """
161 cdef Float16 obj = Float16.__new__(Float16)
162 obj._c_float.v = value
163 return obj
164
165 @staticmethod
166 def from_double(double value):
167 """Factory function to create a Float16 object from a double.
168 """
169 cdef Float16 obj = Float16.__new__(Float16)
170 cdef cfloat.ui64_double ud
171 cdef cfloat.float64_t d
172
173 ud.d = value
174 d.v = ud.u
175 obj._c_float = cfloat.f64_to_f16(d)
176
177 return obj
178
179 # convenience interface for use inside Python
180
181 def __init__(self, value):
182 cdef cfloat.ui64_double ud
183 cdef cfloat.float64_t d
184
185 if isinstance(value, int):
186 self._c_float.v = value
187 else:
188 ud.d = float(value)
189 d.v = ud.u
190 self._c_float = cfloat.f64_to_f16(d)
191
192 def __float__(self):
193 cdef cfloat.ui64_double ud
194 ud.u = cfloat.f16_to_f64(self._c_float).v
195 return ud.d
196
197 def __int__(self):
198 cdef cfloat.ui64_double ud
199 ud.u = cfloat.f16_to_f64(self._c_float).v
200 return int(ud.d)
201
202 def __str__(self):
203 cdef cfloat.ui64_double ud
204 ud.u = cfloat.f16_to_f64(self._c_float).v
205 return repr(ud.d)
206
207 def __repr__(self):
208 cdef cfloat.ui64_double ud
209 ud.u = cfloat.f16_to_f64(self._c_float).v
210 return 'Float16(' + repr(ud.d) + ')'
211
212 cpdef uint16_t get_bits(self):
213 return self._c_float.v
214 bits = property(get_bits)
215
216 # arithmetic
217
218 cpdef Float16 neg(self):
219 cdef cfloat.float16_t f = _f16_neg(self._c_float)
220 return Float16.from_c_float(f)
221
222 def __neg__(self):
223 return self.neg()
224
225 cpdef Float16 abs(self):
226 cdef cfloat.float16_t f = _f16_abs(self._c_float)
227 return Float16.from_c_float(f)
228
229 def __abs__(self):
230 return self.abs()
231
232 cpdef Float16 round_to(self, uint_fast8_t rm, bint exact):
233 cdef cfloat.float16_t f = cfloat.f16_roundToInt(self._c_float, rm, exact)
234 return Float16.from_c_float(f)
235
236 cpdef Float16 round(self):
237 cdef cfloat.float16_t f = cfloat.f16_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True)
238 return Float16.from_c_float(f)
239
240 def __round__(self):
241 return self.round()
242
243 cpdef Float16 add(self, Float16 other):
244 cdef cfloat.float16_t f = cfloat.f16_add(self._c_float, other._c_float)
245 return Float16.from_c_float(f)
246
247 def __add__(self, Float16 other):
248 return self.add(other)
249
250 cpdef Float16 sub(self, Float16 other):
251 cdef cfloat.float16_t f = cfloat.f16_sub(self._c_float, other._c_float)
252 return Float16.from_c_float(f)
253
254 def __sub__(self, Float16 other):
255 return self.sub(other)
256
257 cpdef Float16 mul(self, Float16 other):
258 cdef cfloat.float16_t f = cfloat.f16_mul(self._c_float, other._c_float)
259 return Float16.from_c_float(f)
260
261 def __mul__(self, Float16 other):
262 return self.mul(other)
263
264 cpdef Float16 fma(self, Float16 a1, Float16 a2):
265 cdef cfloat.float16_t f = cfloat.f16_mulAdd(a1._c_float, a2._c_float, self._c_float)
266 return Float16.from_c_float(f)
267
268 cpdef Float16 div(self, Float16 other):
269 cdef cfloat.float16_t f = cfloat.f16_div(self._c_float, other._c_float)
270 return Float16.from_c_float(f)
271
272 def __truediv__(self, Float16 other):
273 return self.div(other)
274
275 cpdef Float16 rem(self, Float16 other):
276 cdef cfloat.float16_t f = cfloat.f16_rem(self._c_float, other._c_float)
277 return Float16.from_c_float(f)
278
279 cpdef Float16 sqrt(self):
280 cdef cfloat.float16_t f = cfloat.f16_sqrt(self._c_float)
281 return Float16.from_c_float(f)
282
283 # in-place arithmetic
284
285 cpdef void ineg(self):
286 self._c_float = _f16_neg(self._c_float)
287
288 cpdef void iabs(self):
289 self._c_float = _f16_abs(self._c_float)
290
291 cpdef void iround_to(self, uint_fast8_t rm, bint exact):
292 self._c_float = cfloat.f16_roundToInt(self._c_float, rm, exact)
293
294 cpdef void iround(self):
295 self._c_float = cfloat.f16_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True)
296
297 cpdef void iadd(self, Float16 other):
298 self._c_float = cfloat.f16_add(self._c_float, other._c_float)
299
300 def __iadd__(self, Float16 other):
301 self.iadd(other)
302 return self
303
304 cpdef void isub(self, Float16 other):
305 self._c_float = cfloat.f16_sub(self._c_float, other._c_float)
306
307 def __isub__(self, Float16 other):
308 self.isub(other)
309 return self
310
311 cpdef void imul(self, Float16 other):
312 self._c_float = cfloat.f16_mul(self._c_float, other._c_float)
313
314 def __imul__(self, Float16 other):
315 self.imul(other)
316 return self
317
318 cpdef void ifma(self, Float16 a1, Float16 a2):
319 self._c_float = cfloat.f16_mulAdd(a1._c_float, a2._c_float, self._c_float)
320
321 cpdef void idiv(self, Float16 other):
322 self._c_float = cfloat.f16_div(self._c_float, other._c_float)
323
324 def __itruediv__(self, Float16 other):
325 self.idiv(other)
326 return self
327
328 cpdef void irem(self, Float16 other):
329 self._c_float = cfloat.f16_rem(self._c_float, other._c_float)
330
331 cpdef void isqrt(self):
332 self._c_float = cfloat.f16_sqrt(self._c_float)
333
334 # comparison
335
336 cpdef bint eq(self, Float16 other):
337 return cfloat.f16_eq(self._c_float, other._c_float)
338
339 cpdef bint le(self, Float16 other):
340 return cfloat.f16_le(self._c_float, other._c_float)
341
342 cpdef bint lt(self, Float16 other):
343 return cfloat.f16_lt(self._c_float, other._c_float)
344
345 def __lt__(self, Float16 other):
346 return self.lt(other)
347
348 def __le__(self, Float16 other):
349 return self.le(other)
350
351 def __eq__(self, Float16 other):
352 return self.eq(other)
353
354 def __ne__(self, Float16 other):
355 return not self.eq(other)
356
357 def __ge__(self, Float16 other):
358 return other.le(self)
359
360 def __gt__(self, Float16 other):
361 return other.lt(self)
362
363 # conversion to other float types
364
365 cpdef Float32 to_f32(self):
366 cdef cfloat.float32_t f = cfloat.f16_to_f32(self._c_float)
367 return Float32.from_c_float(f)
368
369 cpdef Float64 to_f64(self):
370 cdef cfloat.float64_t f = cfloat.f16_to_f64(self._c_float)
371 return Float64.from_c_float(f)
372
373
374 # external, non-method arithmetic
375
376 cpdef Float16 f16_neg(Float16 a1):
377 cdef cfloat.float16_t f = _f16_neg(a1._c_float)
378 return Float16.from_c_float(f)
379
380 cpdef Float16 f16_abs(Float16 a1):
381 cdef cfloat.float16_t f = _f16_abs(a1._c_float)
382 return Float16.from_c_float(f)
383
384 cpdef Float16 f16_round_to(Float16 a1, uint_fast8_t rm, bint exact):
385 cdef cfloat.float16_t f = cfloat.f16_roundToInt(a1._c_float, rm, exact)
386 return Float16.from_c_float(f)
387
388 cpdef Float16 f16_round(Float16 a1):
389 cdef cfloat.float16_t f = cfloat.f16_roundToInt(a1._c_float, cfloat.softfloat_roundingMode, True)
390 return Float16.from_c_float(f)
391
392 cpdef Float16 f16_add(Float16 a1, Float16 a2):
393 cdef cfloat.float16_t f = cfloat.f16_add(a1._c_float, a2._c_float)
394 return Float16.from_c_float(f)
395
396 cpdef Float16 f16_sub(Float16 a1, Float16 a2):
397 cdef cfloat.float16_t f = cfloat.f16_sub(a1._c_float, a2._c_float)
398 return Float16.from_c_float(f)
399
400 cpdef Float16 f16_mul(Float16 a1, Float16 a2):
401 cdef cfloat.float16_t f = cfloat.f16_mul(a1._c_float, a2._c_float)
402 return Float16.from_c_float(f)
403
404 cpdef Float16 f16_fma(Float16 acc, Float16 a1, Float16 a2):
405 cdef cfloat.float16_t f = cfloat.f16_mulAdd(a1._c_float, a2._c_float, acc._c_float)
406 return Float16.from_c_float(f)
407
408 cpdef Float16 f16_div(Float16 a1, Float16 a2):
409 cdef cfloat.float16_t f = cfloat.f16_div(a1._c_float, a2._c_float)
410 return Float16.from_c_float(f)
411
412 cpdef Float16 f16_rem(Float16 a1, Float16 a2):
413 cdef cfloat.float16_t f = cfloat.f16_rem(a1._c_float, a2._c_float)
414 return Float16.from_c_float(f)
415
416 cpdef Float16 f16_sqrt(Float16 a1):
417 cdef cfloat.float16_t f = cfloat.f16_sqrt(a1._c_float)
418 return Float16.from_c_float(f)
419
420 cpdef bint f16_eq(Float16 a1, Float16 a2):
421 return cfloat.f16_eq(a1._c_float, a2._c_float)
422
423 cpdef bint f16_le(Float16 a1, Float16 a2):
424 return cfloat.f16_le(a1._c_float, a2._c_float)
425
426 cpdef bint f16_lt(Float16 a1, Float16 a2):
427 return cfloat.f16_lt(a1._c_float, a2._c_float)
428
429 cpdef Float32 f16_to_f32(Float16 a1):
430 cdef cfloat.float32_t f = cfloat.f16_to_f32(a1._c_float)
431 return Float32.from_c_float(f)
432
433 cpdef Float64 f16_to_f64(Float16 a1):
434 cdef cfloat.float64_t f = cfloat.f16_to_f64(a1._c_float)
435 return Float64.from_c_float(f)
436
437
438 cdef class Float32:
439
440 # the wrapped float value
441 cdef cfloat.float32_t _c_float
442
443 # factory function constructors that bypass __init__
444
445 @staticmethod
446 cdef Float32 from_c_float(cfloat.float32_t f):
447 """Factory function to create a Float32 object directly from
448 a C float32_t.
449 """
450 cdef Float32 obj = Float32.__new__(Float32)
451 obj._c_float = f
452 return obj
453
454 @staticmethod
455 def from_bits(uint32_t value):
456 """Factory function to create a Float32 object from a bit pattern
457 represented as an integer.
458 """
459 cdef Float32 obj = Float32.__new__(Float32)
460 obj._c_float.v = value
461 return obj
462
463 @staticmethod
464 def from_double(double value):
465 """Factory function to create a Float32 object from a double.
466 """
467 cdef Float32 obj = Float32.__new__(Float32)
468 cdef cfloat.ui64_double ud
469 cdef cfloat.float64_t d
470
471 ud.d = value
472 d.v = ud.u
473 obj._c_float = cfloat.f64_to_f32(d)
474
475 return obj
476
477 # convenience interface for use inside Python
478
479 def __init__(self, value):
480 cdef cfloat.ui64_double ud
481 cdef cfloat.float64_t d
482
483 if isinstance(value, int):
484 self._c_float.v = value
485 else:
486 ud.d = float(value)
487 d.v = ud.u
488 self._c_float = cfloat.f64_to_f32(d)
489
490 def __float__(self):
491 cdef cfloat.ui64_double ud
492 ud.u = cfloat.f32_to_f64(self._c_float).v
493 return ud.d
494
495 def __int__(self):
496 cdef cfloat.ui64_double ud
497 ud.u = cfloat.f32_to_f64(self._c_float).v
498 return int(ud.d)
499
500 def __str__(self):
501 cdef cfloat.ui64_double ud
502 ud.u = cfloat.f32_to_f64(self._c_float).v
503 return repr(ud.d)
504
505 def __repr__(self):
506 cdef cfloat.ui64_double ud
507 ud.u = cfloat.f32_to_f64(self._c_float).v
508 return 'Float32(' + repr(ud.d) + ')'
509
510 cpdef uint32_t get_bits(self):
511 return self._c_float.v
512 bits = property(get_bits)
513
514 # arithmetic
515
516 cpdef Float32 neg(self):
517 cdef cfloat.float32_t f = _f32_neg(self._c_float)
518 return Float32.from_c_float(f)
519
520 def __neg__(self):
521 return self.neg()
522
523 cpdef Float32 abs(self):
524 cdef cfloat.float32_t f = _f32_abs(self._c_float)
525 return Float32.from_c_float(f)
526
527 def __abs__(self):
528 return self.abs()
529
530 cpdef Float32 round_to(self, uint_fast8_t rm, bint exact):
531 cdef cfloat.float32_t f = cfloat.f32_roundToInt(self._c_float, rm, exact)
532 return Float32.from_c_float(f)
533
534 cpdef Float32 round(self):
535 cdef cfloat.float32_t f = cfloat.f32_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True)
536 return Float32.from_c_float(f)
537
538 def __round__(self):
539 return self.round()
540
541 cpdef Float32 add(self, Float32 other):
542 cdef cfloat.float32_t f = cfloat.f32_add(self._c_float, other._c_float)
543 return Float32.from_c_float(f)
544
545 def __add__(self, Float32 other):
546 return self.add(other)
547
548 cpdef Float32 sub(self, Float32 other):
549 cdef cfloat.float32_t f = cfloat.f32_sub(self._c_float, other._c_float)
550 return Float32.from_c_float(f)
551
552 def __sub__(self, Float32 other):
553 return self.sub(other)
554
555 cpdef Float32 mul(self, Float32 other):
556 cdef cfloat.float32_t f = cfloat.f32_mul(self._c_float, other._c_float)
557 return Float32.from_c_float(f)
558
559 def __mul__(self, Float32 other):
560 return self.mul(other)
561
562 cpdef Float32 fma(self, Float32 a1, Float32 a2):
563 cdef cfloat.float32_t f = cfloat.f32_mulAdd(a1._c_float, a2._c_float, self._c_float)
564 return Float32.from_c_float(f)
565
566 cpdef Float32 div(self, Float32 other):
567 cdef cfloat.float32_t f = cfloat.f32_div(self._c_float, other._c_float)
568 return Float32.from_c_float(f)
569
570 def __truediv__(self, Float32 other):
571 return self.div(other)
572
573 cpdef Float32 rem(self, Float32 other):
574 cdef cfloat.float32_t f = cfloat.f32_rem(self._c_float, other._c_float)
575 return Float32.from_c_float(f)
576
577 cpdef Float32 sqrt(self):
578 cdef cfloat.float32_t f = cfloat.f32_sqrt(self._c_float)
579 return Float32.from_c_float(f)
580
581 # in-place arithmetic
582
583 cpdef void ineg(self):
584 self._c_float = _f32_neg(self._c_float)
585
586 cpdef void iabs(self):
587 self._c_float = _f32_abs(self._c_float)
588
589 cpdef void iround_to(self, uint_fast8_t rm, bint exact):
590 self._c_float = cfloat.f32_roundToInt(self._c_float, rm, exact)
591
592 cpdef void iround(self):
593 self._c_float = cfloat.f32_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True)
594
595 cpdef void iadd(self, Float32 other):
596 self._c_float = cfloat.f32_add(self._c_float, other._c_float)
597
598 def __iadd__(self, Float32 other):
599 self.iadd(other)
600 return self
601
602 cpdef void isub(self, Float32 other):
603 self._c_float = cfloat.f32_sub(self._c_float, other._c_float)
604
605 def __isub__(self, Float32 other):
606 self.isub(other)
607 return self
608
609 cpdef void imul(self, Float32 other):
610 self._c_float = cfloat.f32_mul(self._c_float, other._c_float)
611
612 def __imul__(self, Float32 other):
613 self.imul(other)
614 return self
615
616 cpdef void ifma(self, Float32 a1, Float32 a2):
617 self._c_float = cfloat.f32_mulAdd(a1._c_float, a2._c_float, self._c_float)
618
619 cpdef void idiv(self, Float32 other):
620 self._c_float = cfloat.f32_div(self._c_float, other._c_float)
621
622 def __itruediv__(self, Float32 other):
623 self.idiv(other)
624 return self
625
626 cpdef void irem(self, Float32 other):
627 self._c_float = cfloat.f32_rem(self._c_float, other._c_float)
628
629 cpdef void isqrt(self):
630 self._c_float = cfloat.f32_sqrt(self._c_float)
631
632 # comparison
633
634 cpdef bint eq(self, Float32 other):
635 return cfloat.f32_eq(self._c_float, other._c_float)
636
637 cpdef bint le(self, Float32 other):
638 return cfloat.f32_le(self._c_float, other._c_float)
639
640 cpdef bint lt(self, Float32 other):
641 return cfloat.f32_lt(self._c_float, other._c_float)
642
643 def __lt__(self, Float32 other):
644 return self.lt(other)
645
646 def __le__(self, Float32 other):
647 return self.le(other)
648
649 def __eq__(self, Float32 other):
650 return self.eq(other)
651
652 def __ne__(self, Float32 other):
653 return not self.eq(other)
654
655 def __ge__(self, Float32 other):
656 return other.le(self)
657
658 def __gt__(self, Float32 other):
659 return other.lt(self)
660
661 # conversion to other float types
662
663 cpdef Float16 to_f16(self):
664 cdef cfloat.float16_t f = cfloat.f32_to_f16(self._c_float)
665 return Float16.from_c_float(f)
666
667 cpdef Float64 to_f64(self):
668 cdef cfloat.float64_t f = cfloat.f32_to_f64(self._c_float)
669 return Float64.from_c_float(f)
670
671
672 # external, non-method arithmetic
673
674 cpdef Float32 f32_neg(Float32 a1):
675 cdef cfloat.float32_t f = _f32_neg(a1._c_float)
676 return Float32.from_c_float(f)
677
678 cpdef Float32 f32_abs(Float32 a1):
679 cdef cfloat.float32_t f = _f32_abs(a1._c_float)
680 return Float32.from_c_float(f)
681
682 cpdef Float32 f32_round_to(Float32 a1, uint_fast8_t rm, bint exact):
683 cdef cfloat.float32_t f = cfloat.f32_roundToInt(a1._c_float, rm, exact)
684 return Float32.from_c_float(f)
685
686 cpdef Float32 f32_round(Float32 a1):
687 cdef cfloat.float32_t f = cfloat.f32_roundToInt(a1._c_float, cfloat.softfloat_roundingMode, True)
688 return Float32.from_c_float(f)
689
690 cpdef Float32 f32_add(Float32 a1, Float32 a2):
691 cdef cfloat.float32_t f = cfloat.f32_add(a1._c_float, a2._c_float)
692 return Float32.from_c_float(f)
693
694 cpdef Float32 f32_sub(Float32 a1, Float32 a2):
695 cdef cfloat.float32_t f = cfloat.f32_sub(a1._c_float, a2._c_float)
696 return Float32.from_c_float(f)
697
698 cpdef Float32 f32_mul(Float32 a1, Float32 a2):
699 cdef cfloat.float32_t f = cfloat.f32_mul(a1._c_float, a2._c_float)
700 return Float32.from_c_float(f)
701
702 cpdef Float32 f32_fma(Float32 acc, Float32 a1, Float32 a2):
703 cdef cfloat.float32_t f = cfloat.f32_mulAdd(a1._c_float, a2._c_float, acc._c_float)
704 return Float32.from_c_float(f)
705
706 cpdef Float32 f32_div(Float32 a1, Float32 a2):
707 cdef cfloat.float32_t f = cfloat.f32_div(a1._c_float, a2._c_float)
708 return Float32.from_c_float(f)
709
710 cpdef Float32 f32_rem(Float32 a1, Float32 a2):
711 cdef cfloat.float32_t f = cfloat.f32_rem(a1._c_float, a2._c_float)
712 return Float32.from_c_float(f)
713
714 cpdef Float32 f32_sqrt(Float32 a1):
715 cdef cfloat.float32_t f = cfloat.f32_sqrt(a1._c_float)
716 return Float32.from_c_float(f)
717
718 cpdef bint f32_eq(Float32 a1, Float32 a2):
719 return cfloat.f32_eq(a1._c_float, a2._c_float)
720
721 cpdef bint f32_le(Float32 a1, Float32 a2):
722 return cfloat.f32_le(a1._c_float, a2._c_float)
723
724 cpdef bint f32_lt(Float32 a1, Float32 a2):
725 return cfloat.f32_lt(a1._c_float, a2._c_float)
726
727 cpdef Float16 f32_to_f16(Float32 a1):
728 cdef cfloat.float16_t f = cfloat.f32_to_f16(a1._c_float)
729 return Float16.from_c_float(f)
730
731 cpdef Float64 f32_to_f64(Float32 a1):
732 cdef cfloat.float64_t f = cfloat.f32_to_f64(a1._c_float)
733 return Float64.from_c_float(f)
734
735
736 cdef class Float64:
737
738 # the wrapped float value
739 cdef cfloat.float64_t _c_float
740
741 # factory function constructors that bypass __init__
742
743 @staticmethod
744 cdef Float64 from_c_float(cfloat.float64_t f):
745 """Factory function to create a Float64 object directly from
746 a C float64_t.
747 """
748 cdef Float64 obj = Float64.__new__(Float64)
749 obj._c_float = f
750 return obj
751
752 @staticmethod
753 def from_bits(uint64_t value):
754 """Factory function to create a Float64 object from a bit pattern
755 represented as an integer.
756 """
757 cdef Float64 obj = Float64.__new__(Float64)
758 obj._c_float.v = value
759 return obj
760
761 @staticmethod
762 def from_double(double value):
763 """Factory function to create a Float64 object from a double.
764 """
765 cdef Float64 obj = Float64.__new__(Float64)
766 cdef cfloat.ui64_double ud
767 cdef cfloat.float64_t d
768
769 ud.d = value
770 obj._c_float.v = ud.u
771
772 return obj
773
774 # convenience interface for use inside Python
775
776 def __init__(self, value):
777 cdef cfloat.ui64_double ud
778 cdef cfloat.float64_t d
779
780 if isinstance(value, int):
781 self._c_float.v = value
782 else:
783 ud.d = float(value)
784 self._c_float.v = ud.u
785
786 def __float__(self):
787 cdef cfloat.ui64_double ud
788 ud.u = self._c_float.v
789 return ud.d
790
791 def __int__(self):
792 cdef cfloat.ui64_double ud
793 ud.u = self._c_float.v
794 return int(ud.d)
795
796 def __str__(self):
797 cdef cfloat.ui64_double ud
798 ud.u = self._c_float.v
799 return repr(ud.d)
800
801 def __repr__(self):
802 cdef cfloat.ui64_double ud
803 ud.u = self._c_float.v
804 return 'Float64(' + repr(ud.d) + ')'
805
806 cpdef uint64_t get_bits(self):
807 return self._c_float.v
808 bits = property(get_bits)
809
810 # arithmetic
811
812 cpdef Float64 neg(self):
813 cdef cfloat.float64_t f = _f64_neg(self._c_float)
814 return Float64.from_c_float(f)
815
816 def __neg__(self):
817 return self.neg()
818
819 cpdef Float64 abs(self):
820 cdef cfloat.float64_t f = _f64_abs(self._c_float)
821 return Float64.from_c_float(f)
822
823 def __abs__(self):
824 return self.abs()
825
826 cpdef Float64 round_to(self, uint_fast8_t rm, bint exact):
827 cdef cfloat.float64_t f = cfloat.f64_roundToInt(self._c_float, rm, exact)
828 return Float64.from_c_float(f)
829
830 cpdef Float64 round(self):
831 cdef cfloat.float64_t f = cfloat.f64_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True)
832 return Float64.from_c_float(f)
833
834 def __round__(self):
835 return self.round()
836
837 cpdef Float64 add(self, Float64 other):
838 cdef cfloat.float64_t f = cfloat.f64_add(self._c_float, other._c_float)
839 return Float64.from_c_float(f)
840
841 def __add__(self, Float64 other):
842 return self.add(other)
843
844 cpdef Float64 sub(self, Float64 other):
845 cdef cfloat.float64_t f = cfloat.f64_sub(self._c_float, other._c_float)
846 return Float64.from_c_float(f)
847
848 def __sub__(self, Float64 other):
849 return self.sub(other)
850
851 cpdef Float64 mul(self, Float64 other):
852 cdef cfloat.float64_t f = cfloat.f64_mul(self._c_float, other._c_float)
853 return Float64.from_c_float(f)
854
855 def __mul__(self, Float64 other):
856 return self.mul(other)
857
858 cpdef Float64 fma(self, Float64 a1, Float64 a2):
859 cdef cfloat.float64_t f = cfloat.f64_mulAdd(a1._c_float, a2._c_float, self._c_float)
860 return Float64.from_c_float(f)
861
862 cpdef Float64 div(self, Float64 other):
863 cdef cfloat.float64_t f = cfloat.f64_div(self._c_float, other._c_float)
864 return Float64.from_c_float(f)
865
866 def __truediv__(self, Float64 other):
867 return self.div(other)
868
869 cpdef Float64 rem(self, Float64 other):
870 cdef cfloat.float64_t f = cfloat.f64_rem(self._c_float, other._c_float)
871 return Float64.from_c_float(f)
872
873 cpdef Float64 sqrt(self):
874 cdef cfloat.float64_t f = cfloat.f64_sqrt(self._c_float)
875 return Float64.from_c_float(f)
876
877 # in-place arithmetic
878
879 cpdef void ineg(self):
880 self._c_float = _f64_neg(self._c_float)
881
882 cpdef void iabs(self):
883 self._c_float = _f64_abs(self._c_float)
884
885 cpdef void iround_to(self, uint_fast8_t rm, bint exact):
886 self._c_float = cfloat.f64_roundToInt(self._c_float, rm, exact)
887
888 cpdef void iround(self):
889 self._c_float = cfloat.f64_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True)
890
891 cpdef void iadd(self, Float64 other):
892 self._c_float = cfloat.f64_add(self._c_float, other._c_float)
893
894 def __iadd__(self, Float64 other):
895 self.iadd(other)
896 return self
897
898 cpdef void isub(self, Float64 other):
899 self._c_float = cfloat.f64_sub(self._c_float, other._c_float)
900
901 def __isub__(self, Float64 other):
902 self.isub(other)
903 return self
904
905 cpdef void imul(self, Float64 other):
906 self._c_float = cfloat.f64_mul(self._c_float, other._c_float)
907
908 def __imul__(self, Float64 other):
909 self.imul(other)
910 return self
911
912 cpdef void ifma(self, Float64 a1, Float64 a2):
913 self._c_float = cfloat.f64_mulAdd(a1._c_float, a2._c_float, self._c_float)
914
915 cpdef void idiv(self, Float64 other):
916 self._c_float = cfloat.f64_div(self._c_float, other._c_float)
917
918 def __itruediv__(self, Float64 other):
919 self.idiv(other)
920 return self
921
922 cpdef void irem(self, Float64 other):
923 self._c_float = cfloat.f64_rem(self._c_float, other._c_float)
924
925 cpdef void isqrt(self):
926 self._c_float = cfloat.f64_sqrt(self._c_float)
927
928 # comparison
929
930 cpdef bint eq(self, Float64 other):
931 return cfloat.f64_eq(self._c_float, other._c_float)
932
933 cpdef bint le(self, Float64 other):
934 return cfloat.f64_le(self._c_float, other._c_float)
935
936 cpdef bint lt(self, Float64 other):
937 return cfloat.f64_lt(self._c_float, other._c_float)
938
939 def __lt__(self, Float64 other):
940 return self.lt(other)
941
942 def __le__(self, Float64 other):
943 return self.le(other)
944
945 def __eq__(self, Float64 other):
946 return self.eq(other)
947
948 def __ne__(self, Float64 other):
949 return not self.eq(other)
950
951 def __ge__(self, Float64 other):
952 return other.le(self)
953
954 def __gt__(self, Float64 other):
955 return other.lt(self)
956
957 # conversion to other float types
958
959 cpdef Float16 to_f16(self):
960 cdef cfloat.float16_t f = cfloat.f64_to_f16(self._c_float)
961 return Float16.from_c_float(f)
962
963 cpdef Float32 to_f32(self):
964 cdef cfloat.float32_t f = cfloat.f64_to_f32(self._c_float)
965 return Float32.from_c_float(f)
966
967
968 # external, non-method arithmetic
969
970 cpdef Float64 f64_neg(Float64 a1):
971 cdef cfloat.float64_t f = _f64_neg(a1._c_float)
972 return Float64.from_c_float(f)
973
974 cpdef Float64 f64_abs(Float64 a1):
975 cdef cfloat.float64_t f = _f64_abs(a1._c_float)
976 return Float64.from_c_float(f)
977
978 cpdef Float64 f64_round_to(Float64 a1, uint_fast8_t rm, bint exact):
979 cdef cfloat.float64_t f = cfloat.f64_roundToInt(a1._c_float, rm, exact)
980 return Float64.from_c_float(f)
981
982 cpdef Float64 f64_round(Float64 a1):
983 cdef cfloat.float64_t f = cfloat.f64_roundToInt(a1._c_float, cfloat.softfloat_roundingMode, True)
984 return Float64.from_c_float(f)
985
986 cpdef Float64 f64_add(Float64 a1, Float64 a2):
987 cdef cfloat.float64_t f = cfloat.f64_add(a1._c_float, a2._c_float)
988 return Float64.from_c_float(f)
989
990 cpdef Float64 f64_sub(Float64 a1, Float64 a2):
991 cdef cfloat.float64_t f = cfloat.f64_sub(a1._c_float, a2._c_float)
992 return Float64.from_c_float(f)
993
994 cpdef Float64 f64_mul(Float64 a1, Float64 a2):
995 cdef cfloat.float64_t f = cfloat.f64_mul(a1._c_float, a2._c_float)
996 return Float64.from_c_float(f)
997
998 cpdef Float64 f64_fma(Float64 acc, Float64 a1, Float64 a2):
999 cdef cfloat.float64_t f = cfloat.f64_mulAdd(a1._c_float, a2._c_float, acc._c_float)
1000 return Float64.from_c_float(f)
1001
1002 cpdef Float64 f64_div(Float64 a1, Float64 a2):
1003 cdef cfloat.float64_t f = cfloat.f64_div(a1._c_float, a2._c_float)
1004 return Float64.from_c_float(f)
1005
1006 cpdef Float64 f64_rem(Float64 a1, Float64 a2):
1007 cdef cfloat.float64_t f = cfloat.f64_rem(a1._c_float, a2._c_float)
1008 return Float64.from_c_float(f)
1009
1010 cpdef Float64 f64_sqrt(Float64 a1):
1011 cdef cfloat.float64_t f = cfloat.f64_sqrt(a1._c_float)
1012 return Float64.from_c_float(f)
1013
1014 cpdef bint f64_eq(Float64 a1, Float64 a2):
1015 return cfloat.f64_eq(a1._c_float, a2._c_float)
1016
1017 cpdef bint f64_le(Float64 a1, Float64 a2):
1018 return cfloat.f64_le(a1._c_float, a2._c_float)
1019
1020 cpdef bint f64_lt(Float64 a1, Float64 a2):
1021 return cfloat.f64_lt(a1._c_float, a2._c_float)
1022
1023 cpdef Float16 f64_to_f16(Float64 a1):
1024 cdef cfloat.float16_t f = cfloat.f64_to_f16(a1._c_float)
1025 return Float16.from_c_float(f)
1026
1027 cpdef Float32 f64_to_f32(Float64 a1):
1028 cdef cfloat.float32_t f = cfloat.f64_to_f32(a1._c_float)
1029 return Float32.from_c_float(f)