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