updating some package info
[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 # external, non-method arithmetic
681
682 cpdef Float32 f32_neg(Float32 a1):
683 cdef cfloat.float32_t f = _f32_neg(a1._c_float)
684 return Float32.from_c_float(f)
685
686 cpdef Float32 f32_abs(Float32 a1):
687 cdef cfloat.float32_t f = _f32_abs(a1._c_float)
688 return Float32.from_c_float(f)
689
690 cpdef Float32 f32_round_to(Float32 a1, uint_fast8_t rm, bint exact):
691 cdef cfloat.float32_t f = cfloat.f32_roundToInt(a1._c_float, rm, exact)
692 return Float32.from_c_float(f)
693
694 cpdef Float32 f32_round(Float32 a1):
695 cdef cfloat.float32_t f = cfloat.f32_roundToInt(a1._c_float, cfloat.softfloat_roundingMode, True)
696 return Float32.from_c_float(f)
697
698 cpdef Float32 f32_add(Float32 a1, Float32 a2):
699 cdef cfloat.float32_t f = cfloat.f32_add(a1._c_float, a2._c_float)
700 return Float32.from_c_float(f)
701
702 cpdef Float32 f32_sub(Float32 a1, Float32 a2):
703 cdef cfloat.float32_t f = cfloat.f32_sub(a1._c_float, a2._c_float)
704 return Float32.from_c_float(f)
705
706 cpdef Float32 f32_mul(Float32 a1, Float32 a2):
707 cdef cfloat.float32_t f = cfloat.f32_mul(a1._c_float, a2._c_float)
708 return Float32.from_c_float(f)
709
710 cpdef Float32 f32_fma(Float32 acc, Float32 a1, Float32 a2):
711 cdef cfloat.float32_t f = cfloat.f32_mulAdd(a1._c_float, a2._c_float, acc._c_float)
712 return Float32.from_c_float(f)
713
714 cpdef Float32 f32_div(Float32 a1, Float32 a2):
715 cdef cfloat.float32_t f = cfloat.f32_div(a1._c_float, a2._c_float)
716 return Float32.from_c_float(f)
717
718 cpdef Float32 f32_rem(Float32 a1, Float32 a2):
719 cdef cfloat.float32_t f = cfloat.f32_rem(a1._c_float, a2._c_float)
720 return Float32.from_c_float(f)
721
722 cpdef Float32 f32_sqrt(Float32 a1):
723 cdef cfloat.float32_t f = cfloat.f32_sqrt(a1._c_float)
724 return Float32.from_c_float(f)
725
726 cpdef bint f32_eq(Float32 a1, Float32 a2):
727 return cfloat.f32_eq(a1._c_float, a2._c_float)
728
729 cpdef bint f32_le(Float32 a1, Float32 a2):
730 return cfloat.f32_le(a1._c_float, a2._c_float)
731
732 cpdef bint f32_lt(Float32 a1, Float32 a2):
733 return cfloat.f32_lt(a1._c_float, a2._c_float)
734
735 cpdef Float16 f32_to_f16(Float32 a1):
736 cdef cfloat.float16_t f = cfloat.f32_to_f16(a1._c_float)
737 return Float16.from_c_float(f)
738
739 cpdef Float64 f32_to_f64(Float32 a1):
740 cdef cfloat.float64_t f = cfloat.f32_to_f64(a1._c_float)
741 return Float64.from_c_float(f)
742
743
744 cdef class Float64:
745
746 # the wrapped float value
747 cdef cfloat.float64_t _c_float
748
749 # factory function constructors that bypass __init__
750
751 @staticmethod
752 cdef Float64 from_c_float(cfloat.float64_t f):
753 """Factory function to create a Float64 object directly from
754 a C float64_t.
755 """
756 cdef Float64 obj = Float64.__new__(Float64)
757 obj._c_float = f
758 return obj
759
760 @staticmethod
761 def from_bits(uint64_t value):
762 """Factory function to create a Float64 object from a bit pattern
763 represented as an integer.
764 """
765 cdef Float64 obj = Float64.__new__(Float64)
766 obj._c_float.v = value
767 return obj
768
769 @staticmethod
770 def from_double(double value):
771 """Factory function to create a Float64 object from a double.
772 """
773 cdef Float64 obj = Float64.__new__(Float64)
774 cdef cfloat.ui64_double ud
775 cdef cfloat.float64_t d
776
777 ud.d = value
778 obj._c_float.v = ud.u
779
780 return obj
781
782 # convenience interface for use inside Python
783
784 def __init__(self, value):
785 """Given an int, create a Float64 from the bitpattern represented by
786 that int. Otherwise, given some value, create a Float64 from
787 float(value).
788 """
789 cdef cfloat.ui64_double ud
790 cdef cfloat.float64_t d
791
792 if isinstance(value, int):
793 self._c_float.v = value
794 else:
795 ud.d = float(value)
796 self._c_float.v = ud.u
797
798 def __float__(self):
799 cdef cfloat.ui64_double ud
800 ud.u = self._c_float.v
801 return ud.d
802
803 def __int__(self):
804 cdef cfloat.ui64_double ud
805 ud.u = self._c_float.v
806 return int(ud.d)
807
808 def __str__(self):
809 cdef cfloat.ui64_double ud
810 ud.u = self._c_float.v
811 return repr(ud.d)
812
813 def __repr__(self):
814 cdef cfloat.ui64_double ud
815 ud.u = self._c_float.v
816 return 'Float64(' + repr(ud.d) + ')'
817
818 cpdef uint64_t get_bits(self):
819 return self._c_float.v
820 bits = property(get_bits)
821
822 # arithmetic
823
824 cpdef Float64 neg(self):
825 cdef cfloat.float64_t f = _f64_neg(self._c_float)
826 return Float64.from_c_float(f)
827
828 def __neg__(self):
829 return self.neg()
830
831 cpdef Float64 abs(self):
832 cdef cfloat.float64_t f = _f64_abs(self._c_float)
833 return Float64.from_c_float(f)
834
835 def __abs__(self):
836 return self.abs()
837
838 cpdef Float64 round_to(self, uint_fast8_t rm, bint exact):
839 cdef cfloat.float64_t f = cfloat.f64_roundToInt(self._c_float, rm, exact)
840 return Float64.from_c_float(f)
841
842 cpdef Float64 round(self):
843 cdef cfloat.float64_t f = cfloat.f64_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True)
844 return Float64.from_c_float(f)
845
846 def __round__(self):
847 return self.round()
848
849 cpdef Float64 add(self, Float64 other):
850 cdef cfloat.float64_t f = cfloat.f64_add(self._c_float, other._c_float)
851 return Float64.from_c_float(f)
852
853 def __add__(self, Float64 other):
854 return self.add(other)
855
856 cpdef Float64 sub(self, Float64 other):
857 cdef cfloat.float64_t f = cfloat.f64_sub(self._c_float, other._c_float)
858 return Float64.from_c_float(f)
859
860 def __sub__(self, Float64 other):
861 return self.sub(other)
862
863 cpdef Float64 mul(self, Float64 other):
864 cdef cfloat.float64_t f = cfloat.f64_mul(self._c_float, other._c_float)
865 return Float64.from_c_float(f)
866
867 def __mul__(self, Float64 other):
868 return self.mul(other)
869
870 cpdef Float64 fma(self, Float64 a1, Float64 a2):
871 cdef cfloat.float64_t f = cfloat.f64_mulAdd(a1._c_float, a2._c_float, self._c_float)
872 return Float64.from_c_float(f)
873
874 cpdef Float64 div(self, Float64 other):
875 cdef cfloat.float64_t f = cfloat.f64_div(self._c_float, other._c_float)
876 return Float64.from_c_float(f)
877
878 def __truediv__(self, Float64 other):
879 return self.div(other)
880
881 cpdef Float64 rem(self, Float64 other):
882 cdef cfloat.float64_t f = cfloat.f64_rem(self._c_float, other._c_float)
883 return Float64.from_c_float(f)
884
885 cpdef Float64 sqrt(self):
886 cdef cfloat.float64_t f = cfloat.f64_sqrt(self._c_float)
887 return Float64.from_c_float(f)
888
889 # in-place arithmetic
890
891 cpdef void ineg(self):
892 self._c_float = _f64_neg(self._c_float)
893
894 cpdef void iabs(self):
895 self._c_float = _f64_abs(self._c_float)
896
897 cpdef void iround_to(self, uint_fast8_t rm, bint exact):
898 self._c_float = cfloat.f64_roundToInt(self._c_float, rm, exact)
899
900 cpdef void iround(self):
901 self._c_float = cfloat.f64_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True)
902
903 cpdef void iadd(self, Float64 other):
904 self._c_float = cfloat.f64_add(self._c_float, other._c_float)
905
906 def __iadd__(self, Float64 other):
907 self.iadd(other)
908 return self
909
910 cpdef void isub(self, Float64 other):
911 self._c_float = cfloat.f64_sub(self._c_float, other._c_float)
912
913 def __isub__(self, Float64 other):
914 self.isub(other)
915 return self
916
917 cpdef void imul(self, Float64 other):
918 self._c_float = cfloat.f64_mul(self._c_float, other._c_float)
919
920 def __imul__(self, Float64 other):
921 self.imul(other)
922 return self
923
924 cpdef void ifma(self, Float64 a1, Float64 a2):
925 self._c_float = cfloat.f64_mulAdd(a1._c_float, a2._c_float, self._c_float)
926
927 cpdef void idiv(self, Float64 other):
928 self._c_float = cfloat.f64_div(self._c_float, other._c_float)
929
930 def __itruediv__(self, Float64 other):
931 self.idiv(other)
932 return self
933
934 cpdef void irem(self, Float64 other):
935 self._c_float = cfloat.f64_rem(self._c_float, other._c_float)
936
937 cpdef void isqrt(self):
938 self._c_float = cfloat.f64_sqrt(self._c_float)
939
940 # comparison
941
942 cpdef bint eq(self, Float64 other):
943 return cfloat.f64_eq(self._c_float, other._c_float)
944
945 cpdef bint le(self, Float64 other):
946 return cfloat.f64_le(self._c_float, other._c_float)
947
948 cpdef bint lt(self, Float64 other):
949 return cfloat.f64_lt(self._c_float, other._c_float)
950
951 def __lt__(self, Float64 other):
952 return self.lt(other)
953
954 def __le__(self, Float64 other):
955 return self.le(other)
956
957 def __eq__(self, Float64 other):
958 return self.eq(other)
959
960 def __ne__(self, Float64 other):
961 return not self.eq(other)
962
963 def __ge__(self, Float64 other):
964 return other.le(self)
965
966 def __gt__(self, Float64 other):
967 return other.lt(self)
968
969 # conversion to other float types
970
971 cpdef Float16 to_f16(self):
972 cdef cfloat.float16_t f = cfloat.f64_to_f16(self._c_float)
973 return Float16.from_c_float(f)
974
975 cpdef Float32 to_f32(self):
976 cdef cfloat.float32_t f = cfloat.f64_to_f32(self._c_float)
977 return Float32.from_c_float(f)
978
979
980 # external, non-method arithmetic
981
982 cpdef Float64 f64_neg(Float64 a1):
983 cdef cfloat.float64_t f = _f64_neg(a1._c_float)
984 return Float64.from_c_float(f)
985
986 cpdef Float64 f64_abs(Float64 a1):
987 cdef cfloat.float64_t f = _f64_abs(a1._c_float)
988 return Float64.from_c_float(f)
989
990 cpdef Float64 f64_round_to(Float64 a1, uint_fast8_t rm, bint exact):
991 cdef cfloat.float64_t f = cfloat.f64_roundToInt(a1._c_float, rm, exact)
992 return Float64.from_c_float(f)
993
994 cpdef Float64 f64_round(Float64 a1):
995 cdef cfloat.float64_t f = cfloat.f64_roundToInt(a1._c_float, cfloat.softfloat_roundingMode, True)
996 return Float64.from_c_float(f)
997
998 cpdef Float64 f64_add(Float64 a1, Float64 a2):
999 cdef cfloat.float64_t f = cfloat.f64_add(a1._c_float, a2._c_float)
1000 return Float64.from_c_float(f)
1001
1002 cpdef Float64 f64_sub(Float64 a1, Float64 a2):
1003 cdef cfloat.float64_t f = cfloat.f64_sub(a1._c_float, a2._c_float)
1004 return Float64.from_c_float(f)
1005
1006 cpdef Float64 f64_mul(Float64 a1, Float64 a2):
1007 cdef cfloat.float64_t f = cfloat.f64_mul(a1._c_float, a2._c_float)
1008 return Float64.from_c_float(f)
1009
1010 cpdef Float64 f64_fma(Float64 acc, Float64 a1, Float64 a2):
1011 cdef cfloat.float64_t f = cfloat.f64_mulAdd(a1._c_float, a2._c_float, acc._c_float)
1012 return Float64.from_c_float(f)
1013
1014 cpdef Float64 f64_div(Float64 a1, Float64 a2):
1015 cdef cfloat.float64_t f = cfloat.f64_div(a1._c_float, a2._c_float)
1016 return Float64.from_c_float(f)
1017
1018 cpdef Float64 f64_rem(Float64 a1, Float64 a2):
1019 cdef cfloat.float64_t f = cfloat.f64_rem(a1._c_float, a2._c_float)
1020 return Float64.from_c_float(f)
1021
1022 cpdef Float64 f64_sqrt(Float64 a1):
1023 cdef cfloat.float64_t f = cfloat.f64_sqrt(a1._c_float)
1024 return Float64.from_c_float(f)
1025
1026 cpdef bint f64_eq(Float64 a1, Float64 a2):
1027 return cfloat.f64_eq(a1._c_float, a2._c_float)
1028
1029 cpdef bint f64_le(Float64 a1, Float64 a2):
1030 return cfloat.f64_le(a1._c_float, a2._c_float)
1031
1032 cpdef bint f64_lt(Float64 a1, Float64 a2):
1033 return cfloat.f64_lt(a1._c_float, a2._c_float)
1034
1035 cpdef Float16 f64_to_f16(Float64 a1):
1036 cdef cfloat.float16_t f = cfloat.f64_to_f16(a1._c_float)
1037 return Float16.from_c_float(f)
1038
1039 cpdef Float32 f64_to_f32(Float64 a1):
1040 cdef cfloat.float32_t f = cfloat.f64_to_f32(a1._c_float)
1041 return Float32.from_c_float(f)