7367696b916a37dca42c9e8d71e21e93bb4822b5
[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 """Given an int, create a Float16 from the bitpattern represented by
183 that int. Otherwise, given some value, create a Float16 by rounding
184 float(value).
185 """
186 cdef cfloat.ui64_double ud
187 cdef cfloat.float64_t d
188
189 if isinstance(value, int):
190 self._c_float.v = value
191 else:
192 ud.d = float(value)
193 d.v = ud.u
194 self._c_float = cfloat.f64_to_f16(d)
195
196 def __float__(self):
197 cdef cfloat.ui64_double ud
198 ud.u = cfloat.f16_to_f64(self._c_float).v
199 return ud.d
200
201 def __int__(self):
202 cdef cfloat.ui64_double ud
203 ud.u = cfloat.f16_to_f64(self._c_float).v
204 return int(ud.d)
205
206 def __str__(self):
207 cdef cfloat.ui64_double ud
208 ud.u = cfloat.f16_to_f64(self._c_float).v
209 return repr(ud.d)
210
211 def __repr__(self):
212 cdef cfloat.ui64_double ud
213 ud.u = cfloat.f16_to_f64(self._c_float).v
214 return 'Float16(' + repr(ud.d) + ')'
215
216 cpdef uint16_t get_bits(self):
217 return self._c_float.v
218 bits = property(get_bits)
219
220 # arithmetic
221
222 cpdef Float16 neg(self):
223 cdef cfloat.float16_t f = _f16_neg(self._c_float)
224 return Float16.from_c_float(f)
225
226 def __neg__(self):
227 return self.neg()
228
229 cpdef Float16 abs(self):
230 cdef cfloat.float16_t f = _f16_abs(self._c_float)
231 return Float16.from_c_float(f)
232
233 def __abs__(self):
234 return self.abs()
235
236 cpdef Float16 round_to(self, uint_fast8_t rm, bint exact):
237 cdef cfloat.float16_t f = cfloat.f16_roundToInt(self._c_float, rm, exact)
238 return Float16.from_c_float(f)
239
240 cpdef Float16 round(self):
241 cdef cfloat.float16_t f = cfloat.f16_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True)
242 return Float16.from_c_float(f)
243
244 def __round__(self):
245 return self.round()
246
247 cpdef Float16 add(self, Float16 other):
248 cdef cfloat.float16_t f = cfloat.f16_add(self._c_float, other._c_float)
249 return Float16.from_c_float(f)
250
251 def __add__(self, Float16 other):
252 return self.add(other)
253
254 cpdef Float16 sub(self, Float16 other):
255 cdef cfloat.float16_t f = cfloat.f16_sub(self._c_float, other._c_float)
256 return Float16.from_c_float(f)
257
258 def __sub__(self, Float16 other):
259 return self.sub(other)
260
261 cpdef Float16 mul(self, Float16 other):
262 cdef cfloat.float16_t f = cfloat.f16_mul(self._c_float, other._c_float)
263 return Float16.from_c_float(f)
264
265 def __mul__(self, Float16 other):
266 return self.mul(other)
267
268 cpdef Float16 fma(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 a1, Float16 a2):
323 self._c_float = cfloat.f16_mulAdd(a1._c_float, a2._c_float, self._c_float)
324
325 cpdef void idiv(self, Float16 other):
326 self._c_float = cfloat.f16_div(self._c_float, other._c_float)
327
328 def __itruediv__(self, Float16 other):
329 self.idiv(other)
330 return self
331
332 cpdef void irem(self, Float16 other):
333 self._c_float = cfloat.f16_rem(self._c_float, other._c_float)
334
335 cpdef void isqrt(self):
336 self._c_float = cfloat.f16_sqrt(self._c_float)
337
338 # comparison
339
340 cpdef bint eq(self, Float16 other):
341 return cfloat.f16_eq(self._c_float, other._c_float)
342
343 cpdef bint le(self, Float16 other):
344 return cfloat.f16_le(self._c_float, other._c_float)
345
346 cpdef bint lt(self, Float16 other):
347 return cfloat.f16_lt(self._c_float, other._c_float)
348
349 def __lt__(self, Float16 other):
350 return self.lt(other)
351
352 def __le__(self, Float16 other):
353 return self.le(other)
354
355 def __eq__(self, Float16 other):
356 return self.eq(other)
357
358 def __ne__(self, Float16 other):
359 return not self.eq(other)
360
361 def __ge__(self, Float16 other):
362 return other.le(self)
363
364 def __gt__(self, Float16 other):
365 return other.lt(self)
366
367 # conversion to other float types
368
369 cpdef Float32 to_f32(self):
370 cdef cfloat.float32_t f = cfloat.f16_to_f32(self._c_float)
371 return Float32.from_c_float(f)
372
373 cpdef Float64 to_f64(self):
374 cdef cfloat.float64_t f = cfloat.f16_to_f64(self._c_float)
375 return Float64.from_c_float(f)
376
377
378 # external, non-method arithmetic
379
380 cpdef Float16 f16_neg(Float16 a1):
381 cdef cfloat.float16_t f = _f16_neg(a1._c_float)
382 return Float16.from_c_float(f)
383
384 cpdef Float16 f16_abs(Float16 a1):
385 cdef cfloat.float16_t f = _f16_abs(a1._c_float)
386 return Float16.from_c_float(f)
387
388 cpdef Float16 f16_round_to(Float16 a1, uint_fast8_t rm, bint exact):
389 cdef cfloat.float16_t f = cfloat.f16_roundToInt(a1._c_float, rm, exact)
390 return Float16.from_c_float(f)
391
392 cpdef Float16 f16_round(Float16 a1):
393 cdef cfloat.float16_t f = cfloat.f16_roundToInt(a1._c_float, cfloat.softfloat_roundingMode, True)
394 return Float16.from_c_float(f)
395
396 cpdef Float16 f16_add(Float16 a1, Float16 a2):
397 cdef cfloat.float16_t f = cfloat.f16_add(a1._c_float, a2._c_float)
398 return Float16.from_c_float(f)
399
400 cpdef Float16 f16_sub(Float16 a1, Float16 a2):
401 cdef cfloat.float16_t f = cfloat.f16_sub(a1._c_float, a2._c_float)
402 return Float16.from_c_float(f)
403
404 cpdef Float16 f16_mul(Float16 a1, Float16 a2):
405 cdef cfloat.float16_t f = cfloat.f16_mul(a1._c_float, a2._c_float)
406 return Float16.from_c_float(f)
407
408 cpdef Float16 f16_fma(Float16 acc, Float16 a1, Float16 a2):
409 cdef cfloat.float16_t f = cfloat.f16_mulAdd(a1._c_float, a2._c_float, acc._c_float)
410 return Float16.from_c_float(f)
411
412 cpdef Float16 f16_div(Float16 a1, Float16 a2):
413 cdef cfloat.float16_t f = cfloat.f16_div(a1._c_float, a2._c_float)
414 return Float16.from_c_float(f)
415
416 cpdef Float16 f16_rem(Float16 a1, Float16 a2):
417 cdef cfloat.float16_t f = cfloat.f16_rem(a1._c_float, a2._c_float)
418 return Float16.from_c_float(f)
419
420 cpdef Float16 f16_sqrt(Float16 a1):
421 cdef cfloat.float16_t f = cfloat.f16_sqrt(a1._c_float)
422 return Float16.from_c_float(f)
423
424 cpdef bint f16_eq(Float16 a1, Float16 a2):
425 return cfloat.f16_eq(a1._c_float, a2._c_float)
426
427 cpdef bint f16_le(Float16 a1, Float16 a2):
428 return cfloat.f16_le(a1._c_float, a2._c_float)
429
430 cpdef bint f16_lt(Float16 a1, Float16 a2):
431 return cfloat.f16_lt(a1._c_float, a2._c_float)
432
433 cpdef Float32 f16_to_f32(Float16 a1):
434 cdef cfloat.float32_t f = cfloat.f16_to_f32(a1._c_float)
435 return Float32.from_c_float(f)
436
437 cpdef Float64 f16_to_f64(Float16 a1):
438 cdef cfloat.float64_t f = cfloat.f16_to_f64(a1._c_float)
439 return Float64.from_c_float(f)
440
441
442 cdef class Float32:
443
444 # the wrapped float value
445 cdef cfloat.float32_t _c_float
446
447 # factory function constructors that bypass __init__
448
449 @staticmethod
450 cdef Float32 from_c_float(cfloat.float32_t f):
451 """Factory function to create a Float32 object directly from
452 a C float32_t.
453 """
454 cdef Float32 obj = Float32.__new__(Float32)
455 obj._c_float = f
456 return obj
457
458 @staticmethod
459 def from_bits(uint32_t value):
460 """Factory function to create a Float32 object from a bit pattern
461 represented as an integer.
462 """
463 cdef Float32 obj = Float32.__new__(Float32)
464 obj._c_float.v = value
465 return obj
466
467 @staticmethod
468 def from_double(double value):
469 """Factory function to create a Float32 object from a double.
470 """
471 cdef Float32 obj = Float32.__new__(Float32)
472 cdef cfloat.ui64_double ud
473 cdef cfloat.float64_t d
474
475 ud.d = value
476 d.v = ud.u
477 obj._c_float = cfloat.f64_to_f32(d)
478
479 return obj
480
481 # convenience interface for use inside Python
482
483 def __init__(self, value):
484 """Given an int, create a Float32 from the bitpattern represented by
485 that int. Otherwise, given some value, create a Float32 by rounding
486 float(value).
487 """
488 cdef cfloat.ui64_double ud
489 cdef cfloat.float64_t d
490
491 if isinstance(value, int):
492 self._c_float.v = value
493 else:
494 ud.d = float(value)
495 d.v = ud.u
496 self._c_float = cfloat.f64_to_f32(d)
497
498 def __float__(self):
499 cdef cfloat.ui64_double ud
500 ud.u = cfloat.f32_to_f64(self._c_float).v
501 return ud.d
502
503 def __int__(self):
504 cdef cfloat.ui64_double ud
505 ud.u = cfloat.f32_to_f64(self._c_float).v
506 return int(ud.d)
507
508 def __str__(self):
509 cdef cfloat.ui64_double ud
510 ud.u = cfloat.f32_to_f64(self._c_float).v
511 return repr(ud.d)
512
513 def __repr__(self):
514 cdef cfloat.ui64_double ud
515 ud.u = cfloat.f32_to_f64(self._c_float).v
516 return 'Float32(' + repr(ud.d) + ')'
517
518 cpdef uint32_t get_bits(self):
519 return self._c_float.v
520 bits = property(get_bits)
521
522 # arithmetic
523
524 cpdef Float32 neg(self):
525 cdef cfloat.float32_t f = _f32_neg(self._c_float)
526 return Float32.from_c_float(f)
527
528 def __neg__(self):
529 return self.neg()
530
531 cpdef Float32 abs(self):
532 cdef cfloat.float32_t f = _f32_abs(self._c_float)
533 return Float32.from_c_float(f)
534
535 def __abs__(self):
536 return self.abs()
537
538 cpdef Float32 round_to(self, uint_fast8_t rm, bint exact):
539 cdef cfloat.float32_t f = cfloat.f32_roundToInt(self._c_float, rm, exact)
540 return Float32.from_c_float(f)
541
542 cpdef Float32 round(self):
543 cdef cfloat.float32_t f = cfloat.f32_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True)
544 return Float32.from_c_float(f)
545
546 def __round__(self):
547 return self.round()
548
549 cpdef Float32 add(self, Float32 other):
550 cdef cfloat.float32_t f = cfloat.f32_add(self._c_float, other._c_float)
551 return Float32.from_c_float(f)
552
553 def __add__(self, Float32 other):
554 return self.add(other)
555
556 cpdef Float32 sub(self, Float32 other):
557 cdef cfloat.float32_t f = cfloat.f32_sub(self._c_float, other._c_float)
558 return Float32.from_c_float(f)
559
560 def __sub__(self, Float32 other):
561 return self.sub(other)
562
563 cpdef Float32 mul(self, Float32 other):
564 cdef cfloat.float32_t f = cfloat.f32_mul(self._c_float, other._c_float)
565 return Float32.from_c_float(f)
566
567 def __mul__(self, Float32 other):
568 return self.mul(other)
569
570 cpdef Float32 fma(self, Float32 a1, Float32 a2):
571 cdef cfloat.float32_t f = cfloat.f32_mulAdd(a1._c_float, a2._c_float, self._c_float)
572 return Float32.from_c_float(f)
573
574 cpdef Float32 div(self, Float32 other):
575 cdef cfloat.float32_t f = cfloat.f32_div(self._c_float, other._c_float)
576 return Float32.from_c_float(f)
577
578 def __truediv__(self, Float32 other):
579 return self.div(other)
580
581 cpdef Float32 rem(self, Float32 other):
582 cdef cfloat.float32_t f = cfloat.f32_rem(self._c_float, other._c_float)
583 return Float32.from_c_float(f)
584
585 cpdef Float32 sqrt(self):
586 cdef cfloat.float32_t f = cfloat.f32_sqrt(self._c_float)
587 return Float32.from_c_float(f)
588
589 # in-place arithmetic
590
591 cpdef void ineg(self):
592 self._c_float = _f32_neg(self._c_float)
593
594 cpdef void iabs(self):
595 self._c_float = _f32_abs(self._c_float)
596
597 cpdef void iround_to(self, uint_fast8_t rm, bint exact):
598 self._c_float = cfloat.f32_roundToInt(self._c_float, rm, exact)
599
600 cpdef void iround(self):
601 self._c_float = cfloat.f32_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True)
602
603 cpdef void iadd(self, Float32 other):
604 self._c_float = cfloat.f32_add(self._c_float, other._c_float)
605
606 def __iadd__(self, Float32 other):
607 self.iadd(other)
608 return self
609
610 cpdef void isub(self, Float32 other):
611 self._c_float = cfloat.f32_sub(self._c_float, other._c_float)
612
613 def __isub__(self, Float32 other):
614 self.isub(other)
615 return self
616
617 cpdef void imul(self, Float32 other):
618 self._c_float = cfloat.f32_mul(self._c_float, other._c_float)
619
620 def __imul__(self, Float32 other):
621 self.imul(other)
622 return self
623
624 cpdef void ifma(self, Float32 a1, Float32 a2):
625 self._c_float = cfloat.f32_mulAdd(a1._c_float, a2._c_float, self._c_float)
626
627 cpdef void idiv(self, Float32 other):
628 self._c_float = cfloat.f32_div(self._c_float, other._c_float)
629
630 def __itruediv__(self, Float32 other):
631 self.idiv(other)
632 return self
633
634 cpdef void irem(self, Float32 other):
635 self._c_float = cfloat.f32_rem(self._c_float, other._c_float)
636
637 cpdef void isqrt(self):
638 self._c_float = cfloat.f32_sqrt(self._c_float)
639
640 # comparison
641
642 cpdef bint eq(self, Float32 other):
643 return cfloat.f32_eq(self._c_float, other._c_float)
644
645 cpdef bint le(self, Float32 other):
646 return cfloat.f32_le(self._c_float, other._c_float)
647
648 cpdef bint lt(self, Float32 other):
649 return cfloat.f32_lt(self._c_float, other._c_float)
650
651 def __lt__(self, Float32 other):
652 return self.lt(other)
653
654 def __le__(self, Float32 other):
655 return self.le(other)
656
657 def __eq__(self, Float32 other):
658 return self.eq(other)
659
660 def __ne__(self, Float32 other):
661 return not self.eq(other)
662
663 def __ge__(self, Float32 other):
664 return other.le(self)
665
666 def __gt__(self, Float32 other):
667 return other.lt(self)
668
669 # conversion to other float types
670
671 cpdef Float16 to_f16(self):
672 cdef cfloat.float16_t f = cfloat.f32_to_f16(self._c_float)
673 return Float16.from_c_float(f)
674
675 cpdef Float64 to_f64(self):
676 cdef cfloat.float64_t f = cfloat.f32_to_f64(self._c_float)
677 return Float64.from_c_float(f)
678
679 ########
680 # integer conversions
681 ########
682
683 # u/i32 <-> f16
684
685 cpdef Float16 i32_to_f16(int32_t value):
686 cdef cfloat.float16_t f = cfloat.i32_to_f16(value)
687 return Float16.from_c_float(f)
688
689 cpdef Float16 ui32_to_f16(uint32_t value):
690 cdef cfloat.float16_t f = cfloat.ui32_to_f16(value)
691 return Float16.from_c_float(f)
692
693 cpdef uint32_t f16_to_ui32(Float16 a1):
694 cdef uint32_t i = cfloat.f16_to_ui32(a1._c_float,
695 cfloat.softfloat_roundingMode, True)
696 return i
697
698 cpdef int32_t f16_to_i32(Float16 a1):
699 cdef int32_t i = cfloat.f16_to_i32(a1._c_float,
700 cfloat.softfloat_roundingMode, True)
701 return i
702
703 # u/i32 <-> f32
704
705 cpdef Float32 i32_to_f32(int32_t value):
706 cdef cfloat.float32_t f = cfloat.i32_to_f32(value)
707 return Float32.from_c_float(f)
708
709 cpdef Float32 ui32_to_f32(uint32_t value):
710 cdef cfloat.float32_t f = cfloat.ui32_to_f32(value)
711 return Float32.from_c_float(f)
712
713 cpdef uint32_t f32_to_ui32(Float32 a1):
714 cdef uint32_t i = cfloat.f32_to_ui32(a1._c_float,
715 cfloat.softfloat_roundingMode, True)
716 return i
717
718 cpdef int32_t f32_to_i32(Float32 a1):
719 cdef int32_t i = cfloat.f32_to_i32(a1._c_float,
720 cfloat.softfloat_roundingMode, True)
721 return i
722
723 # u/i32 <-> f64
724
725 cpdef Float64 i32_to_f64(int32_t value):
726 cdef cfloat.float64_t f = cfloat.i32_to_f64(value)
727 return Float64.from_c_float(f)
728
729 cpdef Float64 ui32_to_f64(uint32_t value):
730 cdef cfloat.float64_t f = cfloat.ui32_to_f64(value)
731 return Float64.from_c_float(f)
732
733 cpdef uint32_t f64_to_ui32(Float64 a1):
734 cdef uint32_t i = cfloat.f64_to_ui32(a1._c_float,
735 cfloat.softfloat_roundingMode, True)
736 return i
737
738 cpdef int32_t f64_to_i32(Float64 a1):
739 cdef int32_t i = cfloat.f64_to_i32(a1._c_float,
740 cfloat.softfloat_roundingMode, True)
741 return i
742
743 # u/i64 <-> f16
744
745 cpdef Float16 i64_to_f16(int32_t value):
746 cdef cfloat.float16_t f = cfloat.i64_to_f16(value)
747 return Float16.from_c_float(f)
748
749 cpdef Float16 ui64_to_f16(uint32_t value):
750 cdef cfloat.float16_t f = cfloat.ui64_to_f16(value)
751 return Float16.from_c_float(f)
752
753 cpdef uint32_t f16_to_ui64(Float16 a1):
754 cdef uint32_t i = cfloat.f16_to_ui64(a1._c_float,
755 cfloat.softfloat_roundingMode, True)
756 return i
757
758 cpdef int32_t f16_to_i64(Float16 a1):
759 cdef int32_t i = cfloat.f16_to_i64(a1._c_float,
760 cfloat.softfloat_roundingMode, True)
761 return i
762
763 # u/i64 <-> f32
764
765 cpdef Float32 i64_to_f32(int32_t value):
766 cdef cfloat.float32_t f = cfloat.i64_to_f32(value)
767 return Float32.from_c_float(f)
768
769 cpdef Float32 ui64_to_f32(uint32_t value):
770 cdef cfloat.float32_t f = cfloat.ui64_to_f32(value)
771 return Float32.from_c_float(f)
772
773 cpdef uint32_t f32_to_ui64(Float32 a1):
774 cdef uint32_t i = cfloat.f32_to_ui64(a1._c_float,
775 cfloat.softfloat_roundingMode, True)
776 return i
777
778 cpdef int32_t f32_to_i64(Float32 a1):
779 cdef int32_t i = cfloat.f32_to_i64(a1._c_float,
780 cfloat.softfloat_roundingMode, True)
781 return i
782
783 # u/i64 <-> f64
784
785 cpdef Float64 i64_to_f64(int64_t value):
786 cdef cfloat.float64_t f = cfloat.i64_to_f64(value)
787 return Float64.from_c_float(f)
788
789 cpdef Float64 ui64_to_f64(uint64_t value):
790 cdef cfloat.float64_t f = cfloat.ui64_to_f64(value)
791 return Float64.from_c_float(f)
792
793 cpdef uint64_t f64_to_ui64(Float64 a1):
794 cdef uint64_t i = cfloat.f64_to_ui64(a1._c_float,
795 cfloat.softfloat_roundingMode, True)
796 return i
797
798 cpdef int64_t f64_to_i64(Float64 a1):
799 cdef int64_t i = cfloat.f64_to_i64(a1._c_float,
800 cfloat.softfloat_roundingMode, True)
801 return i
802
803 # external, non-method arithmetic
804
805 cpdef Float32 f32_neg(Float32 a1):
806 cdef cfloat.float32_t f = _f32_neg(a1._c_float)
807 return Float32.from_c_float(f)
808
809 cpdef Float32 f32_abs(Float32 a1):
810 cdef cfloat.float32_t f = _f32_abs(a1._c_float)
811 return Float32.from_c_float(f)
812
813 cpdef Float32 f32_round_to(Float32 a1, uint_fast8_t rm, bint exact):
814 cdef cfloat.float32_t f = cfloat.f32_roundToInt(a1._c_float, rm, exact)
815 return Float32.from_c_float(f)
816
817 cpdef Float32 f32_round(Float32 a1):
818 cdef cfloat.float32_t f = cfloat.f32_roundToInt(a1._c_float, cfloat.softfloat_roundingMode, True)
819 return Float32.from_c_float(f)
820
821 cpdef Float32 f32_add(Float32 a1, Float32 a2):
822 cdef cfloat.float32_t f = cfloat.f32_add(a1._c_float, a2._c_float)
823 return Float32.from_c_float(f)
824
825 cpdef Float32 f32_sub(Float32 a1, Float32 a2):
826 cdef cfloat.float32_t f = cfloat.f32_sub(a1._c_float, a2._c_float)
827 return Float32.from_c_float(f)
828
829 cpdef Float32 f32_mul(Float32 a1, Float32 a2):
830 cdef cfloat.float32_t f = cfloat.f32_mul(a1._c_float, a2._c_float)
831 return Float32.from_c_float(f)
832
833 cpdef Float32 f32_fma(Float32 acc, Float32 a1, Float32 a2):
834 cdef cfloat.float32_t f = cfloat.f32_mulAdd(a1._c_float, a2._c_float, acc._c_float)
835 return Float32.from_c_float(f)
836
837 cpdef Float32 f32_div(Float32 a1, Float32 a2):
838 cdef cfloat.float32_t f = cfloat.f32_div(a1._c_float, a2._c_float)
839 return Float32.from_c_float(f)
840
841 cpdef Float32 f32_rem(Float32 a1, Float32 a2):
842 cdef cfloat.float32_t f = cfloat.f32_rem(a1._c_float, a2._c_float)
843 return Float32.from_c_float(f)
844
845 cpdef Float32 f32_sqrt(Float32 a1):
846 cdef cfloat.float32_t f = cfloat.f32_sqrt(a1._c_float)
847 return Float32.from_c_float(f)
848
849 cpdef bint f32_eq(Float32 a1, Float32 a2):
850 return cfloat.f32_eq(a1._c_float, a2._c_float)
851
852 cpdef bint f32_le(Float32 a1, Float32 a2):
853 return cfloat.f32_le(a1._c_float, a2._c_float)
854
855 cpdef bint f32_lt(Float32 a1, Float32 a2):
856 return cfloat.f32_lt(a1._c_float, a2._c_float)
857
858 cpdef Float16 f32_to_f16(Float32 a1):
859 cdef cfloat.float16_t f = cfloat.f32_to_f16(a1._c_float)
860 return Float16.from_c_float(f)
861
862 cpdef Float64 f32_to_f64(Float32 a1):
863 cdef cfloat.float64_t f = cfloat.f32_to_f64(a1._c_float)
864 return Float64.from_c_float(f)
865
866
867 cdef class Float64:
868
869 # the wrapped float value
870 cdef cfloat.float64_t _c_float
871
872 # factory function constructors that bypass __init__
873
874 @staticmethod
875 cdef Float64 from_c_float(cfloat.float64_t f):
876 """Factory function to create a Float64 object directly from
877 a C float64_t.
878 """
879 cdef Float64 obj = Float64.__new__(Float64)
880 obj._c_float = f
881 return obj
882
883 @staticmethod
884 def from_bits(uint64_t value):
885 """Factory function to create a Float64 object from a bit pattern
886 represented as an integer.
887 """
888 cdef Float64 obj = Float64.__new__(Float64)
889 obj._c_float.v = value
890 return obj
891
892 @staticmethod
893 def from_double(double value):
894 """Factory function to create a Float64 object from a double.
895 """
896 cdef Float64 obj = Float64.__new__(Float64)
897 cdef cfloat.ui64_double ud
898 cdef cfloat.float64_t d
899
900 ud.d = value
901 obj._c_float.v = ud.u
902
903 return obj
904
905 # convenience interface for use inside Python
906
907 def __init__(self, value):
908 """Given an int, create a Float64 from the bitpattern represented by
909 that int. Otherwise, given some value, create a Float64 from
910 float(value).
911 """
912 cdef cfloat.ui64_double ud
913 cdef cfloat.float64_t d
914
915 if isinstance(value, int):
916 self._c_float.v = value
917 else:
918 ud.d = float(value)
919 self._c_float.v = ud.u
920
921 def __float__(self):
922 cdef cfloat.ui64_double ud
923 ud.u = self._c_float.v
924 return ud.d
925
926 def __int__(self):
927 cdef cfloat.ui64_double ud
928 ud.u = self._c_float.v
929 return int(ud.d)
930
931 def __str__(self):
932 cdef cfloat.ui64_double ud
933 ud.u = self._c_float.v
934 return repr(ud.d)
935
936 def __repr__(self):
937 cdef cfloat.ui64_double ud
938 ud.u = self._c_float.v
939 return 'Float64(' + repr(ud.d) + ')'
940
941 cpdef uint64_t get_bits(self):
942 return self._c_float.v
943 bits = property(get_bits)
944
945 # arithmetic
946
947 cpdef Float64 neg(self):
948 cdef cfloat.float64_t f = _f64_neg(self._c_float)
949 return Float64.from_c_float(f)
950
951 def __neg__(self):
952 return self.neg()
953
954 cpdef Float64 abs(self):
955 cdef cfloat.float64_t f = _f64_abs(self._c_float)
956 return Float64.from_c_float(f)
957
958 def __abs__(self):
959 return self.abs()
960
961 cpdef Float64 round_to(self, uint_fast8_t rm, bint exact):
962 cdef cfloat.float64_t f = cfloat.f64_roundToInt(self._c_float, rm, exact)
963 return Float64.from_c_float(f)
964
965 cpdef Float64 round(self):
966 cdef cfloat.float64_t f = cfloat.f64_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True)
967 return Float64.from_c_float(f)
968
969 def __round__(self):
970 return self.round()
971
972 cpdef Float64 add(self, Float64 other):
973 cdef cfloat.float64_t f = cfloat.f64_add(self._c_float, other._c_float)
974 return Float64.from_c_float(f)
975
976 def __add__(self, Float64 other):
977 return self.add(other)
978
979 cpdef Float64 sub(self, Float64 other):
980 cdef cfloat.float64_t f = cfloat.f64_sub(self._c_float, other._c_float)
981 return Float64.from_c_float(f)
982
983 def __sub__(self, Float64 other):
984 return self.sub(other)
985
986 cpdef Float64 mul(self, Float64 other):
987 cdef cfloat.float64_t f = cfloat.f64_mul(self._c_float, other._c_float)
988 return Float64.from_c_float(f)
989
990 def __mul__(self, Float64 other):
991 return self.mul(other)
992
993 cpdef Float64 fma(self, Float64 a1, Float64 a2):
994 cdef cfloat.float64_t f = cfloat.f64_mulAdd(a1._c_float, a2._c_float, self._c_float)
995 return Float64.from_c_float(f)
996
997 cpdef Float64 div(self, Float64 other):
998 cdef cfloat.float64_t f = cfloat.f64_div(self._c_float, other._c_float)
999 return Float64.from_c_float(f)
1000
1001 def __truediv__(self, Float64 other):
1002 return self.div(other)
1003
1004 cpdef Float64 rem(self, Float64 other):
1005 cdef cfloat.float64_t f = cfloat.f64_rem(self._c_float, other._c_float)
1006 return Float64.from_c_float(f)
1007
1008 cpdef Float64 sqrt(self):
1009 cdef cfloat.float64_t f = cfloat.f64_sqrt(self._c_float)
1010 return Float64.from_c_float(f)
1011
1012 # in-place arithmetic
1013
1014 cpdef void ineg(self):
1015 self._c_float = _f64_neg(self._c_float)
1016
1017 cpdef void iabs(self):
1018 self._c_float = _f64_abs(self._c_float)
1019
1020 cpdef void iround_to(self, uint_fast8_t rm, bint exact):
1021 self._c_float = cfloat.f64_roundToInt(self._c_float, rm, exact)
1022
1023 cpdef void iround(self):
1024 self._c_float = cfloat.f64_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True)
1025
1026 cpdef void iadd(self, Float64 other):
1027 self._c_float = cfloat.f64_add(self._c_float, other._c_float)
1028
1029 def __iadd__(self, Float64 other):
1030 self.iadd(other)
1031 return self
1032
1033 cpdef void isub(self, Float64 other):
1034 self._c_float = cfloat.f64_sub(self._c_float, other._c_float)
1035
1036 def __isub__(self, Float64 other):
1037 self.isub(other)
1038 return self
1039
1040 cpdef void imul(self, Float64 other):
1041 self._c_float = cfloat.f64_mul(self._c_float, other._c_float)
1042
1043 def __imul__(self, Float64 other):
1044 self.imul(other)
1045 return self
1046
1047 cpdef void ifma(self, Float64 a1, Float64 a2):
1048 self._c_float = cfloat.f64_mulAdd(a1._c_float, a2._c_float, self._c_float)
1049
1050 cpdef void idiv(self, Float64 other):
1051 self._c_float = cfloat.f64_div(self._c_float, other._c_float)
1052
1053 def __itruediv__(self, Float64 other):
1054 self.idiv(other)
1055 return self
1056
1057 cpdef void irem(self, Float64 other):
1058 self._c_float = cfloat.f64_rem(self._c_float, other._c_float)
1059
1060 cpdef void isqrt(self):
1061 self._c_float = cfloat.f64_sqrt(self._c_float)
1062
1063 # comparison
1064
1065 cpdef bint eq(self, Float64 other):
1066 return cfloat.f64_eq(self._c_float, other._c_float)
1067
1068 cpdef bint le(self, Float64 other):
1069 return cfloat.f64_le(self._c_float, other._c_float)
1070
1071 cpdef bint lt(self, Float64 other):
1072 return cfloat.f64_lt(self._c_float, other._c_float)
1073
1074 def __lt__(self, Float64 other):
1075 return self.lt(other)
1076
1077 def __le__(self, Float64 other):
1078 return self.le(other)
1079
1080 def __eq__(self, Float64 other):
1081 return self.eq(other)
1082
1083 def __ne__(self, Float64 other):
1084 return not self.eq(other)
1085
1086 def __ge__(self, Float64 other):
1087 return other.le(self)
1088
1089 def __gt__(self, Float64 other):
1090 return other.lt(self)
1091
1092 # conversion to other float types
1093
1094 cpdef Float16 to_f16(self):
1095 cdef cfloat.float16_t f = cfloat.f64_to_f16(self._c_float)
1096 return Float16.from_c_float(f)
1097
1098 cpdef Float32 to_f32(self):
1099 cdef cfloat.float32_t f = cfloat.f64_to_f32(self._c_float)
1100 return Float32.from_c_float(f)
1101
1102
1103 # external, non-method arithmetic
1104
1105 cpdef Float64 f64_neg(Float64 a1):
1106 cdef cfloat.float64_t f = _f64_neg(a1._c_float)
1107 return Float64.from_c_float(f)
1108
1109 cpdef Float64 f64_abs(Float64 a1):
1110 cdef cfloat.float64_t f = _f64_abs(a1._c_float)
1111 return Float64.from_c_float(f)
1112
1113 cpdef Float64 f64_round_to(Float64 a1, uint_fast8_t rm, bint exact):
1114 cdef cfloat.float64_t f = cfloat.f64_roundToInt(a1._c_float, rm, exact)
1115 return Float64.from_c_float(f)
1116
1117 cpdef Float64 f64_round(Float64 a1):
1118 cdef cfloat.float64_t f = cfloat.f64_roundToInt(a1._c_float, cfloat.softfloat_roundingMode, True)
1119 return Float64.from_c_float(f)
1120
1121 cpdef Float64 f64_add(Float64 a1, Float64 a2):
1122 cdef cfloat.float64_t f = cfloat.f64_add(a1._c_float, a2._c_float)
1123 return Float64.from_c_float(f)
1124
1125 cpdef Float64 f64_sub(Float64 a1, Float64 a2):
1126 cdef cfloat.float64_t f = cfloat.f64_sub(a1._c_float, a2._c_float)
1127 return Float64.from_c_float(f)
1128
1129 cpdef Float64 f64_mul(Float64 a1, Float64 a2):
1130 cdef cfloat.float64_t f = cfloat.f64_mul(a1._c_float, a2._c_float)
1131 return Float64.from_c_float(f)
1132
1133 cpdef Float64 f64_fma(Float64 acc, Float64 a1, Float64 a2):
1134 cdef cfloat.float64_t f = cfloat.f64_mulAdd(a1._c_float, a2._c_float, acc._c_float)
1135 return Float64.from_c_float(f)
1136
1137 cpdef Float64 f64_div(Float64 a1, Float64 a2):
1138 cdef cfloat.float64_t f = cfloat.f64_div(a1._c_float, a2._c_float)
1139 return Float64.from_c_float(f)
1140
1141 cpdef Float64 f64_rem(Float64 a1, Float64 a2):
1142 cdef cfloat.float64_t f = cfloat.f64_rem(a1._c_float, a2._c_float)
1143 return Float64.from_c_float(f)
1144
1145 cpdef Float64 f64_sqrt(Float64 a1):
1146 cdef cfloat.float64_t f = cfloat.f64_sqrt(a1._c_float)
1147 return Float64.from_c_float(f)
1148
1149 cpdef bint f64_eq(Float64 a1, Float64 a2):
1150 return cfloat.f64_eq(a1._c_float, a2._c_float)
1151
1152 cpdef bint f64_le(Float64 a1, Float64 a2):
1153 return cfloat.f64_le(a1._c_float, a2._c_float)
1154
1155 cpdef bint f64_lt(Float64 a1, Float64 a2):
1156 return cfloat.f64_lt(a1._c_float, a2._c_float)
1157
1158 cpdef Float16 f64_to_f16(Float64 a1):
1159 cdef cfloat.float16_t f = cfloat.f64_to_f16(a1._c_float)
1160 return Float16.from_c_float(f)
1161
1162 cpdef Float32 f64_to_f32(Float64 a1):
1163 cdef cfloat.float32_t f = cfloat.f64_to_f32(a1._c_float)
1164 return Float32.from_c_float(f)