revise fma/qma interface to match SoftPosit
[sfpy.git] / sfpy / posit.pyx
1 from libc.stdint cimport *
2 cimport cposit
3
4
5 # special values and C helpers
6
7 cdef _p8_one = cposit.ui32_to_p8(1)
8 cdef _p16_one = cposit.ui32_to_p16(1)
9 cdef _p32_one = cposit.ui32_to_p32(1)
10
11 cdef inline cposit.posit8_t _p8_neg(cposit.posit8_t f):
12 f.v = -f.v
13 return f
14
15 cdef inline cposit.posit16_t _p16_neg(cposit.posit16_t f):
16 f.v = -f.v
17 return f
18
19 cdef inline cposit.posit32_t _p32_neg(cposit.posit32_t f):
20 f.v = -f.v
21 return f
22
23 cdef inline cposit.posit8_t _p8_abs(cposit.posit8_t f):
24 f.v = <uint8_t> abs(<int8_t> f.v)
25 return f
26
27 cdef inline cposit.posit16_t _p16_abs(cposit.posit16_t f):
28 f.v = <uint16_t> abs(<int16_t> f.v)
29 return f
30
31 cdef inline cposit.posit32_t _p32_abs(cposit.posit32_t f):
32 f.v = <uint32_t> abs(<int32_t> f.v)
33 return f
34
35
36 cdef class Posit8:
37
38 # the wrapped posit value
39 cdef cposit.posit8_t _c_posit
40
41 # factory function constructors that bypass __init__
42
43 @staticmethod
44 cdef Posit8 from_c_posit(cposit.posit8_t f):
45 """Factory function to create a Posit8 object directly from
46 a C posit8_t.
47 """
48 cdef Posit8 obj = Posit8.__new__(Posit8)
49 obj._c_posit = f
50 return obj
51
52 @staticmethod
53 def from_bits(uint8_t value):
54 """Factory function to create a Posit8 object from a bit pattern
55 represented as an integer.
56 """
57 cdef Posit8 obj = Posit8.__new__(Posit8)
58 obj._c_posit.v = value
59 return obj
60
61 @staticmethod
62 def from_double(double value):
63 """Factory function to create a Posit8 object from a double.
64 """
65 cdef Posit8 obj = Posit8.__new__(Posit8)
66 obj._c_posit = cposit.convertDoubleToP8(value)
67 return obj
68
69 # convenience interface for use inside Python
70
71 def __init__(self, value):
72 if isinstance(value, int):
73 self._c_posit.v = value
74 else:
75 f = float(value)
76 self._c_posit = cposit.convertDoubleToP8(f)
77
78 def __float__(self):
79 return cposit.convertP8ToDouble(self._c_posit)
80
81 def __int__(self):
82 return int(cposit.convertP8ToDouble(self._c_posit))
83
84 def __str__(self):
85 return repr(cposit.convertP8ToDouble(self._c_posit))
86
87 def __repr__(self):
88 return 'Posit8(' + repr(cposit.convertP8ToDouble(self._c_posit)) + ')'
89
90 cpdef uint8_t get_bits(self):
91 return self._c_posit.v
92 bits = property(get_bits)
93
94 # arithmetic
95
96 cpdef Posit8 neg(self):
97 cdef cposit.posit8_t f = _p8_neg(self._c_posit)
98 return Posit8.from_c_posit(f)
99
100 def __neg__(self):
101 return self.neg()
102
103 cpdef Posit8 abs(self):
104 cdef cposit.posit8_t f = _p8_abs(self._c_posit)
105 return Posit8.from_c_posit(f)
106
107 def __abs__(self):
108 return self.abs()
109
110 cpdef Posit8 round(self):
111 cdef cposit.posit8_t f = cposit.p8_roundToInt(self._c_posit)
112 return Posit8.from_c_posit(f)
113
114 def __round__(self):
115 return self.round()
116
117 cpdef Posit8 add(self, Posit8 other):
118 cdef cposit.posit8_t f = cposit.p8_add(self._c_posit, other._c_posit)
119 return Posit8.from_c_posit(f)
120
121 def __add__(self, Posit8 other):
122 return self.add(other)
123
124 cpdef Posit8 sub(self, Posit8 other):
125 cdef cposit.posit8_t f = cposit.p8_sub(self._c_posit, other._c_posit)
126 return Posit8.from_c_posit(f)
127
128 def __sub__(self, Posit8 other):
129 return self.sub(other)
130
131 cpdef Posit8 mul(self, Posit8 other):
132 cdef cposit.posit8_t f = cposit.p8_mul(self._c_posit, other._c_posit)
133 return Posit8.from_c_posit(f)
134
135 def __mul__(self, Posit8 other):
136 return self.mul(other)
137
138 cpdef Posit8 fma(self, Posit8 a1, Posit8 a2):
139 cdef cposit.posit8_t f = cposit.p8_mulAdd(a1._c_posit, a2._c_posit, self._c_posit)
140 return Posit8.from_c_posit(f)
141
142 cpdef Posit8 div(self, Posit8 other):
143 cdef cposit.posit8_t f = cposit.p8_div(self._c_posit, other._c_posit)
144 return Posit8.from_c_posit(f)
145
146 def __truediv__(self, Posit8 other):
147 return self.div(other)
148
149 cpdef Posit8 sqrt(self):
150 cdef cposit.posit8_t f = cposit.p8_sqrt(self._c_posit)
151 return Posit8.from_c_posit(f)
152
153 # in-place arithmetic
154
155 cpdef void ineg(self):
156 self._c_posit = _p8_neg(self._c_posit)
157
158 cpdef void iabs(self):
159 self._c_posit = _p8_abs(self._c_posit)
160
161 cpdef void iround(self):
162 self._c_posit = cposit.p8_roundToInt(self._c_posit)
163
164 cpdef void iadd(self, Posit8 other):
165 self._c_posit = cposit.p8_add(self._c_posit, other._c_posit)
166
167 def __iadd__(self, Posit8 other):
168 self.iadd(other)
169 return self
170
171 cpdef void isub(self, Posit8 other):
172 self._c_posit = cposit.p8_sub(self._c_posit, other._c_posit)
173
174 def __isub__(self, Posit8 other):
175 self.isub(other)
176 return self
177
178 cpdef void imul(self, Posit8 other):
179 self._c_posit = cposit.p8_mul(self._c_posit, other._c_posit)
180
181 def __imul__(self, Posit8 other):
182 self.imul(other)
183 return self
184
185 cpdef void ifma(self, Posit8 a1, Posit8 a2):
186 self._c_posit = cposit.p8_mulAdd(a1._c_posit, a2._c_posit, self._c_posit)
187
188 cpdef void idiv(self, Posit8 other):
189 self._c_posit = cposit.p8_div(self._c_posit, other._c_posit)
190
191 def __itruediv__(self, Posit8 other):
192 self.idiv(other)
193 return self
194
195 cpdef void isqrt(self):
196 self._c_posit = cposit.p8_sqrt(self._c_posit)
197
198 # comparison
199
200 cpdef bint eq(self, Posit8 other):
201 return cposit.p8_eq(self._c_posit, other._c_posit)
202
203 cpdef bint le(self, Posit8 other):
204 return cposit.p8_le(self._c_posit, other._c_posit)
205
206 cpdef bint lt(self, Posit8 other):
207 return cposit.p8_lt(self._c_posit, other._c_posit)
208
209 def __lt__(self, Posit8 other):
210 return self.lt(other)
211
212 def __le__(self, Posit8 other):
213 return self.le(other)
214
215 def __eq__(self, Posit8 other):
216 return self.eq(other)
217
218 def __ne__(self, Posit8 other):
219 return not self.eq(other)
220
221 def __ge__(self, Posit8 other):
222 return other.le(self)
223
224 def __gt__(self, Posit8 other):
225 return other.lt(self)
226
227 # conversion to other posit types
228
229 cpdef to_p16(self):
230 cdef cposit.posit16_t f = cposit.p8_to_p16(self._c_posit)
231 return Posit16.from_c_posit(f)
232
233 cpdef to_p32(self):
234 cdef cposit.posit32_t f = cposit.p8_to_p32(self._c_posit)
235 return Posit32.from_c_posit(f)
236
237 cpdef to_quire(self):
238 cdef cposit.quire8_t f
239 f = cposit.q8_clr(f)
240 f = cposit.q8_fdp_add(f, self._c_posit, _p8_one)
241 return Quire8.from_c_quire(f)
242
243
244 cdef class Quire8:
245
246 # the wrapped quire value
247 cdef cposit.quire8_t _c_quire
248
249 # factory function constructors that bypass init
250
251 @staticmethod
252 cdef Quire8 from_c_quire(cposit.quire8_t f):
253 """Factory function to create a Quire8 object directly from
254 a C quire8_t.
255 """
256 cdef Quire8 obj = Quire8.__new__(Quire8)
257 obj._c_quire = f
258 return obj
259
260 @staticmethod
261 def from_bits(uint32_t value):
262 """Factory function to create a Quire8 object from a bit pattern
263 represented as an integer.
264 """
265 cdef Quire8 obj = Quire8.__new__(Quire8)
266 obj._c_quire.v = value
267 return obj
268
269 # convenience interface for use inside Python
270
271 def __init__(self, value):
272 if isinstance(value, int):
273 self._c_quire.v = value
274 else:
275 f = float(value)
276 self._c_quire = cposit.q8_clr(self._c_quire)
277 self._c_quire = cposit.q8_fdp_add(self._c_quire, cposit.convertDoubleToP8(f), _p8_one)
278
279 def __float__(self):
280 return cposit.convertP8ToDouble(cposit.q8_to_p8(self._c_quire))
281
282 def __int__(self):
283 return int(cposit.convertP8ToDouble(cposit.q8_to_p8(self._c_quire)))
284
285 def __str__(self):
286 return repr(cposit.convertP8ToDouble(cposit.q8_to_p8(self._c_quire)))
287
288 def __repr__(self):
289 return 'Quire8(' + repr(cposit.convertP8ToDouble(cposit.q8_to_p8(self._c_quire))) + ')'
290
291 cpdef uint32_t get_bits(self):
292 return self._c_quire.v
293 bits = property(get_bits)
294
295 # arithmetic
296
297 cpdef Quire8 qma(self, Posit8 a1, Posit8 a2):
298 cdef cposit.quire8_t f = cposit.q8_fdp_add(self._c_quire, a1._c_posit, a2._c_posit)
299 return Quire8.from_c_quire(f)
300
301 cpdef Quire8 qms(self, Posit8 a1, Posit8 a2):
302 cdef cposit.quire8_t f = cposit.q8_fdp_sub(self._c_quire, a1._c_posit, a2._c_posit)
303 return Quire8.from_c_quire(f)
304
305 cpdef void iqma(self, Posit8 a1, Posit8 a2):
306 self._c_quire = cposit.q8_fdp_add(self._c_quire, a1._c_posit, a2._c_posit)
307
308 cpdef void iqms(self, Posit8 a1, Posit8 a2):
309 self._c_quire = cposit.q8_fdp_sub(self._c_quire, a1._c_posit, a2._c_posit)
310
311 cpdef void iclr(self):
312 self._c_quire = cposit.q8_clr(self._c_quire)
313
314 # conversion back to posit
315
316 cpdef Posit8 to_posit(self):
317 cpdef cposit.posit8_t f = cposit.q8_to_p8(self._c_quire)
318 return Posit8.from_c_posit(f)
319
320
321 # external, non-method arithmetic
322
323 cpdef Posit8 p8_neg(Posit8 a1):
324 cdef cposit.posit8_t f = _p8_neg(a1._c_posit)
325 return Posit8.from_c_posit(f)
326
327 cpdef Posit8 p8_abs(Posit8 a1):
328 cdef cposit.posit8_t f = _p8_abs(a1._c_posit)
329 return Posit8.from_c_posit(f)
330
331 cpdef Posit8 p8_round(Posit8 a1):
332 cdef cposit.posit8_t f = cposit.p8_roundToInt(a1._c_posit)
333 return Posit8.from_c_posit(f)
334
335 cpdef Posit8 p8_add(Posit8 a1, Posit8 a2):
336 cdef cposit.posit8_t f = cposit.p8_add(a1._c_posit, a2._c_posit)
337 return Posit8.from_c_posit(f)
338
339 cpdef Posit8 p8_sub(Posit8 a1, Posit8 a2):
340 cdef cposit.posit8_t f = cposit.p8_sub(a1._c_posit, a2._c_posit)
341 return Posit8.from_c_posit(f)
342
343 cpdef Posit8 p8_mul(Posit8 a1, Posit8 a2):
344 cdef cposit.posit8_t f = cposit.p8_mul(a1._c_posit, a2._c_posit)
345 return Posit8.from_c_posit(f)
346
347 cpdef Posit8 p8_fma(Posit8 acc, Posit8 a1, Posit8 a2):
348 cdef cposit.posit8_t f = cposit.p8_mulAdd(a1._c_posit, a2._c_posit, acc._c_posit)
349 return Posit8.from_c_posit(f)
350
351 cpdef Posit8 p8_div(Posit8 a1, Posit8 a2):
352 cdef cposit.posit8_t f = cposit.p8_div(a1._c_posit, a2._c_posit)
353 return Posit8.from_c_posit(f)
354
355 cpdef Posit8 p8_sqrt(Posit8 a1):
356 cdef cposit.posit8_t f = cposit.p8_sqrt(a1._c_posit)
357 return Posit8.from_c_posit(f)
358
359 cpdef bint p8_eq(Posit8 a1, Posit8 a2):
360 return cposit.p8_eq(a1._c_posit, a2._c_posit)
361
362 cpdef bint p8_le(Posit8 a1, Posit8 a2):
363 return cposit.p8_le(a1._c_posit, a2._c_posit)
364
365 cpdef bint p8_lt(Posit8 a1, Posit8 a2):
366 return cposit.p8_lt(a1._c_posit, a2._c_posit)
367
368 cpdef Posit16 p8_to_p16(Posit8 a1):
369 cdef cposit.posit16_t f = cposit.p8_to_p16(a1._c_posit)
370 return Posit16.from_c_posit(f)
371
372 cpdef Posit32 p8_to_p32(Posit8 a1):
373 cdef cposit.posit32_t f = cposit.p8_to_p32(a1._c_posit)
374 return Posit32.from_c_posit(f)
375
376 cpdef Quire8 p8_to_q8(Posit8 a1):
377 cdef cposit.quire8_t f
378 f = cposit.q8_clr(f)
379 f = cposit.q8_fdp_add(f, a1._c_posit, _p8_one)
380 return Quire8.from_c_quire(f)
381
382 cpdef Quire8 q8_qma(Quire8 acc, Posit8 a1, Posit8 a2):
383 cdef cposit.quire8_t f = cposit.q8_fdp_add(acc._c_quire, a1._c_posit, a2._c_posit)
384 return Quire8.from_c_quire(f)
385
386 cpdef Quire8 q8_qms(Quire8 acc, Posit8 a1, Posit8 a2):
387 cdef cposit.quire8_t f = cposit.q8_fdp_sub(acc._c_quire, a1._c_posit, a2._c_posit)
388 return Quire8.from_c_quire(f)
389
390 cpdef Posit8 q8_to_p8(Quire8 a1):
391 cpdef cposit.posit8_t f = cposit.q8_to_p8(a1._c_quire)
392 return Posit8.from_c_posit(f)
393
394
395 cdef class Posit16:
396
397 # the wrapped posit value
398 cdef cposit.posit16_t _c_posit
399
400 # factory function constructors that bypass __init__
401
402 @staticmethod
403 cdef Posit16 from_c_posit(cposit.posit16_t f):
404 """Factory function to create a Posit16 object directly from
405 a C posit16_t.
406 """
407 cdef Posit16 obj = Posit16.__new__(Posit16)
408 obj._c_posit = f
409 return obj
410
411 @staticmethod
412 def from_bits(uint16_t value):
413 """Factory function to create a Posit16 object from a bit pattern
414 represented as an integer.
415 """
416 cdef Posit16 obj = Posit16.__new__(Posit16)
417 obj._c_posit.v = value
418 return obj
419
420 @staticmethod
421 def from_double(double value):
422 """Factory function to create a Posit16 object from a double.
423 """
424 cdef Posit16 obj = Posit16.__new__(Posit16)
425 obj._c_posit = cposit.convertDoubleToP16(value)
426 return obj
427
428 # convenience interface for use inside Python
429
430 def __init__(self, value):
431 if isinstance(value, int):
432 self._c_posit.v = value
433 else:
434 f = float(value)
435 self._c_posit = cposit.convertDoubleToP16(f)
436
437 def __float__(self):
438 return cposit.convertP16ToDouble(self._c_posit)
439
440 def __int__(self):
441 return int(cposit.convertP16ToDouble(self._c_posit))
442
443 def __str__(self):
444 return repr(cposit.convertP16ToDouble(self._c_posit))
445
446 def __repr__(self):
447 return 'Posit16(' + repr(cposit.convertP16ToDouble(self._c_posit)) + ')'
448
449 cpdef uint16_t get_bits(self):
450 return self._c_posit.v
451 bits = property(get_bits)
452
453 # arithmetic
454
455 cpdef Posit16 neg(self):
456 cdef cposit.posit16_t f = _p16_neg(self._c_posit)
457 return Posit16.from_c_posit(f)
458
459 def __neg__(self):
460 return self.neg()
461
462 cpdef Posit16 abs(self):
463 cdef cposit.posit16_t f = _p16_abs(self._c_posit)
464 return Posit16.from_c_posit(f)
465
466 def __abs__(self):
467 return self.abs()
468
469 cpdef Posit16 round(self):
470 cdef cposit.posit16_t f = cposit.p16_roundToInt(self._c_posit)
471 return Posit16.from_c_posit(f)
472
473 def __round__(self):
474 return self.round()
475
476 cpdef Posit16 add(self, Posit16 other):
477 cdef cposit.posit16_t f = cposit.p16_add(self._c_posit, other._c_posit)
478 return Posit16.from_c_posit(f)
479
480 def __add__(self, Posit16 other):
481 return self.add(other)
482
483 cpdef Posit16 sub(self, Posit16 other):
484 cdef cposit.posit16_t f = cposit.p16_sub(self._c_posit, other._c_posit)
485 return Posit16.from_c_posit(f)
486
487 def __sub__(self, Posit16 other):
488 return self.sub(other)
489
490 cpdef Posit16 mul(self, Posit16 other):
491 cdef cposit.posit16_t f = cposit.p16_mul(self._c_posit, other._c_posit)
492 return Posit16.from_c_posit(f)
493
494 def __mul__(self, Posit16 other):
495 return self.mul(other)
496
497 cpdef Posit16 fma(self, Posit16 a1, Posit16 a2):
498 cdef cposit.posit16_t f = cposit.p16_mulAdd(a1._c_posit, a2._c_posit, self._c_posit)
499 return Posit16.from_c_posit(f)
500
501 cpdef Posit16 div(self, Posit16 other):
502 cdef cposit.posit16_t f = cposit.p16_div(self._c_posit, other._c_posit)
503 return Posit16.from_c_posit(f)
504
505 def __truediv__(self, Posit16 other):
506 return self.div(other)
507
508 cpdef Posit16 sqrt(self):
509 cdef cposit.posit16_t f = cposit.p16_sqrt(self._c_posit)
510 return Posit16.from_c_posit(f)
511
512 # in-place arithmetic
513
514 cpdef void ineg(self):
515 self._c_posit = _p16_neg(self._c_posit)
516
517 cpdef void iabs(self):
518 self._c_posit = _p16_abs(self._c_posit)
519
520 cpdef void iround(self):
521 self._c_posit = cposit.p16_roundToInt(self._c_posit)
522
523 cpdef void iadd(self, Posit16 other):
524 self._c_posit = cposit.p16_add(self._c_posit, other._c_posit)
525
526 def __iadd__(self, Posit16 other):
527 self.iadd(other)
528 return self
529
530 cpdef void isub(self, Posit16 other):
531 self._c_posit = cposit.p16_sub(self._c_posit, other._c_posit)
532
533 def __isub__(self, Posit16 other):
534 self.isub(other)
535 return self
536
537 cpdef void imul(self, Posit16 other):
538 self._c_posit = cposit.p16_mul(self._c_posit, other._c_posit)
539
540 def __imul__(self, Posit16 other):
541 self.imul(other)
542 return self
543
544 cpdef void ifma(self, Posit16 a1, Posit16 a2):
545 self._c_posit = cposit.p16_mulAdd(a1._c_posit, a2._c_posit, self._c_posit)
546
547 cpdef void idiv(self, Posit16 other):
548 self._c_posit = cposit.p16_div(self._c_posit, other._c_posit)
549
550 def __itruediv__(self, Posit16 other):
551 self.idiv(other)
552 return self
553
554 cpdef void isqrt(self):
555 self._c_posit = cposit.p16_sqrt(self._c_posit)
556
557 # comparison
558
559 cpdef bint eq(self, Posit16 other):
560 return cposit.p16_eq(self._c_posit, other._c_posit)
561
562 cpdef bint le(self, Posit16 other):
563 return cposit.p16_le(self._c_posit, other._c_posit)
564
565 cpdef bint lt(self, Posit16 other):
566 return cposit.p16_lt(self._c_posit, other._c_posit)
567
568 def __lt__(self, Posit16 other):
569 return self.lt(other)
570
571 def __le__(self, Posit16 other):
572 return self.le(other)
573
574 def __eq__(self, Posit16 other):
575 return self.eq(other)
576
577 def __ne__(self, Posit16 other):
578 return not self.eq(other)
579
580 def __ge__(self, Posit16 other):
581 return other.le(self)
582
583 def __gt__(self, Posit16 other):
584 return other.lt(self)
585
586 # conversion to other posit types
587
588 cpdef to_p8(self):
589 cdef cposit.posit8_t f = cposit.p16_to_p8(self._c_posit)
590 return Posit8.from_c_posit(f)
591
592 cpdef to_p32(self):
593 cdef cposit.posit32_t f = cposit.p16_to_p32(self._c_posit)
594 return Posit32.from_c_posit(f)
595
596 cpdef to_quire(self):
597 cdef cposit.quire16_t f
598 f = cposit.q16_clr(f)
599 f = cposit.q16_fdp_add(f, self._c_posit, _p16_one)
600 return Quire16.from_c_quire(f)
601
602
603 cdef class Quire16:
604
605 # the wrapped quire value
606 cdef cposit.quire16_t _c_quire
607
608 # factory function constructors that bypass init
609
610 @staticmethod
611 cdef Quire16 from_c_quire(cposit.quire16_t f):
612 """Factory function to create a Quire16 object directly from
613 a C quire16_t.
614 """
615 cdef Quire16 obj = Quire16.__new__(Quire16)
616 obj._c_quire = f
617 return obj
618
619 @staticmethod
620 def from_bits(value):
621 """Factory function to create a Quire16 object from a bit pattern
622 represented as an integer.
623 """
624 cdef Quire16 obj = Quire16.__new__(Quire16)
625
626 if not isinstance(value, int):
627 raise TypeError('expecting int, got {}'.format(repr(value)))
628
629 for idx in range(1, -1, -1):
630 obj._c_quire.v[idx] = value & 0xffffffffffffffff
631 value >>= 64
632
633 if not (value == 0):
634 raise OverflowError('value too large to fit in uint64_t[2]')
635
636 return obj
637
638 # convenience interface for use inside Python
639
640 def __init__(self, value):
641 if isinstance(value, int):
642 for idx in range(1, -1, -1):
643 self._c_quire.v[idx] = value & 0xffffffffffffffff
644 value >>= 64
645 if not (value == 0):
646 raise OverflowError('value too large to fit in uint64_t[2]')
647 else:
648 f = float(value)
649 self._c_quire = cposit.q16_clr(self._c_quire)
650 self._c_quire = cposit.q16_fdp_add(self._c_quire, cposit.convertDoubleToP16(f), _p16_one)
651
652 def __float__(self):
653 return cposit.convertP16ToDouble(cposit.q16_to_p16(self._c_quire))
654
655 def __int__(self):
656 return int(cposit.convertP16ToDouble(cposit.q16_to_p16(self._c_quire)))
657
658 def __str__(self):
659 return repr(cposit.convertP16ToDouble(cposit.q16_to_p16(self._c_quire)))
660
661 def __repr__(self):
662 return 'Quire16(' + repr(cposit.convertP16ToDouble(cposit.q16_to_p16(self._c_quire))) + ')'
663
664 def get_bits(self):
665 b = 0
666 for u in self._c_quire.v:
667 b <<= 64
668 b |= u
669 return b
670 bits = property(get_bits)
671
672 # arithmetic
673
674 cpdef Quire16 qma(self, Posit16 a1, Posit16 a2):
675 cdef cposit.quire16_t f = cposit.q16_fdp_add(self._c_quire, a1._c_posit, a2._c_posit)
676 return Quire16.from_c_quire(f)
677
678 cpdef Quire16 qms(self, Posit16 a1, Posit16 a2):
679 cdef cposit.quire16_t f = cposit.q16_fdp_sub(self._c_quire, a1._c_posit, a2._c_posit)
680 return Quire16.from_c_quire(f)
681
682 cpdef void iqma(self, Posit16 a1, Posit16 a2):
683 self._c_quire = cposit.q16_fdp_add(self._c_quire, a1._c_posit, a2._c_posit)
684
685 cpdef void iqms(self, Posit16 a1, Posit16 a2):
686 self._c_quire = cposit.q16_fdp_sub(self._c_quire, a1._c_posit, a2._c_posit)
687
688 cpdef void iclr(self):
689 self._c_quire = cposit.q16_clr(self._c_quire)
690
691 # conversion back to posit
692
693 cpdef Posit16 to_posit(self):
694 cpdef cposit.posit16_t f = cposit.q16_to_p16(self._c_quire)
695 return Posit16.from_c_posit(f)
696
697
698 # external, non-method arithmetic
699
700 cpdef Posit16 p16_neg(Posit16 a1):
701 cdef cposit.posit16_t f = _p16_neg(a1._c_posit)
702 return Posit16.from_c_posit(f)
703
704 cpdef Posit16 p16_abs(Posit16 a1):
705 cdef cposit.posit16_t f = _p16_abs(a1._c_posit)
706 return Posit16.from_c_posit(f)
707
708 cpdef Posit16 p16_round(Posit16 a1):
709 cdef cposit.posit16_t f = cposit.p16_roundToInt(a1._c_posit)
710 return Posit16.from_c_posit(f)
711
712 cpdef Posit16 p16_add(Posit16 a1, Posit16 a2):
713 cdef cposit.posit16_t f = cposit.p16_add(a1._c_posit, a2._c_posit)
714 return Posit16.from_c_posit(f)
715
716 cpdef Posit16 p16_sub(Posit16 a1, Posit16 a2):
717 cdef cposit.posit16_t f = cposit.p16_sub(a1._c_posit, a2._c_posit)
718 return Posit16.from_c_posit(f)
719
720 cpdef Posit16 p16_mul(Posit16 a1, Posit16 a2):
721 cdef cposit.posit16_t f = cposit.p16_mul(a1._c_posit, a2._c_posit)
722 return Posit16.from_c_posit(f)
723
724 cpdef Posit16 p16_fma(Posit16 acc, Posit16 a1, Posit16 a2):
725 cdef cposit.posit16_t f = cposit.p16_mulAdd(a1._c_posit, a2._c_posit, acc._c_posit)
726 return Posit16.from_c_posit(f)
727
728 cpdef Posit16 p16_div(Posit16 a1, Posit16 a2):
729 cdef cposit.posit16_t f = cposit.p16_div(a1._c_posit, a2._c_posit)
730 return Posit16.from_c_posit(f)
731
732 cpdef Posit16 p16_sqrt(Posit16 a1):
733 cdef cposit.posit16_t f = cposit.p16_sqrt(a1._c_posit)
734 return Posit16.from_c_posit(f)
735
736 cpdef bint p16_eq(Posit16 a1, Posit16 a2):
737 return cposit.p16_eq(a1._c_posit, a2._c_posit)
738
739 cpdef bint p16_le(Posit16 a1, Posit16 a2):
740 return cposit.p16_le(a1._c_posit, a2._c_posit)
741
742 cpdef bint p16_lt(Posit16 a1, Posit16 a2):
743 return cposit.p16_lt(a1._c_posit, a2._c_posit)
744
745 cpdef Posit8 p16_to_p8(Posit16 a1):
746 cdef cposit.posit8_t f = cposit.p16_to_p8(a1._c_posit)
747 return Posit8.from_c_posit(f)
748
749 cpdef Posit32 p16_to_p32(Posit16 a1):
750 cdef cposit.posit32_t f = cposit.p16_to_p32(a1._c_posit)
751 return Posit32.from_c_posit(f)
752
753 cpdef Quire16 p16_to_q16(Posit16 a1):
754 cdef cposit.quire16_t f
755 f = cposit.q16_clr(f)
756 f = cposit.q16_fdp_add(f, a1._c_posit, _p16_one)
757 return Quire16.from_c_quire(f)
758
759 cpdef Quire16 q16_qma(Quire16 acc, Posit16 a1, Posit16 a2):
760 cdef cposit.quire16_t f = cposit.q16_fdp_add(acc._c_quire, a1._c_posit, a2._c_posit)
761 return Quire16.from_c_quire(f)
762
763 cpdef Quire16 q16_qms(Quire16 acc, Posit16 a1, Posit16 a2):
764 cdef cposit.quire16_t f = cposit.q16_fdp_sub(acc._c_quire, a1._c_posit, a2._c_posit)
765 return Quire16.from_c_quire(f)
766
767 cpdef Posit16 q16_to_p16(Quire16 a1):
768 cpdef cposit.posit16_t f = cposit.q16_to_p16(a1._c_quire)
769 return Posit16.from_c_posit(f)
770
771
772 cdef class Posit32:
773
774 # the wrapped posit value
775 cdef cposit.posit32_t _c_posit
776
777 # factory function constructors that bypass __init__
778
779 @staticmethod
780 cdef Posit32 from_c_posit(cposit.posit32_t f):
781 """Factory function to create a Posit32 object directly from
782 a C posit32_t.
783 """
784 cdef Posit32 obj = Posit32.__new__(Posit32)
785 obj._c_posit = f
786 return obj
787
788 @staticmethod
789 def from_bits(uint32_t value):
790 """Factory function to create a Posit32 object from a bit pattern
791 represented as an integer.
792 """
793 cdef Posit32 obj = Posit32.__new__(Posit32)
794 obj._c_posit.v = value
795 return obj
796
797 @staticmethod
798 def from_double(double value):
799 """Factory function to create a Posit32 object from a double.
800 """
801 cdef Posit32 obj = Posit32.__new__(Posit32)
802 obj._c_posit = cposit.convertDoubleToP32(value)
803 return obj
804
805 # convenience interface for use inside Python
806
807 def __init__(self, value):
808 if isinstance(value, int):
809 self._c_posit.v = value
810 else:
811 f = float(value)
812 self._c_posit = cposit.convertDoubleToP32(f)
813
814 def __float__(self):
815 return cposit.convertP32ToDouble(self._c_posit)
816
817 def __int__(self):
818 return int(cposit.convertP32ToDouble(self._c_posit))
819
820 def __str__(self):
821 return repr(cposit.convertP32ToDouble(self._c_posit))
822
823 def __repr__(self):
824 return 'Posit32(' + repr(cposit.convertP32ToDouble(self._c_posit)) + ')'
825
826 cpdef uint32_t get_bits(self):
827 return self._c_posit.v
828 bits = property(get_bits)
829
830 # arithmetic
831
832 cpdef Posit32 neg(self):
833 cdef cposit.posit32_t f = _p32_neg(self._c_posit)
834 return Posit32.from_c_posit(f)
835
836 def __neg__(self):
837 return self.neg()
838
839 cpdef Posit32 abs(self):
840 cdef cposit.posit32_t f = _p32_abs(self._c_posit)
841 return Posit32.from_c_posit(f)
842
843 def __abs__(self):
844 return self.abs()
845
846 cpdef Posit32 round(self):
847 cdef cposit.posit32_t f = cposit.p32_roundToInt(self._c_posit)
848 return Posit32.from_c_posit(f)
849
850 def __round__(self):
851 return self.round()
852
853 cpdef Posit32 add(self, Posit32 other):
854 cdef cposit.posit32_t f = cposit.p32_add(self._c_posit, other._c_posit)
855 return Posit32.from_c_posit(f)
856
857 def __add__(self, Posit32 other):
858 return self.add(other)
859
860 cpdef Posit32 sub(self, Posit32 other):
861 cdef cposit.posit32_t f = cposit.p32_sub(self._c_posit, other._c_posit)
862 return Posit32.from_c_posit(f)
863
864 def __sub__(self, Posit32 other):
865 return self.sub(other)
866
867 cpdef Posit32 mul(self, Posit32 other):
868 cdef cposit.posit32_t f = cposit.p32_mul(self._c_posit, other._c_posit)
869 return Posit32.from_c_posit(f)
870
871 def __mul__(self, Posit32 other):
872 return self.mul(other)
873
874 cpdef Posit32 fma(self, Posit32 a1, Posit32 a2):
875 cdef cposit.posit32_t f = cposit.p32_mulAdd(a1._c_posit, a2._c_posit, self._c_posit)
876 return Posit32.from_c_posit(f)
877
878 cpdef Posit32 div(self, Posit32 other):
879 cdef cposit.posit32_t f = cposit.p32_div(self._c_posit, other._c_posit)
880 return Posit32.from_c_posit(f)
881
882 def __truediv__(self, Posit32 other):
883 return self.div(other)
884
885 cpdef Posit32 sqrt(self):
886 cdef cposit.posit32_t f = cposit.p32_sqrt(self._c_posit)
887 return Posit32.from_c_posit(f)
888
889 # in-place arithmetic
890
891 cpdef void ineg(self):
892 self._c_posit = _p32_neg(self._c_posit)
893
894 cpdef void iabs(self):
895 self._c_posit = _p32_abs(self._c_posit)
896
897 cpdef void iround(self):
898 self._c_posit = cposit.p32_roundToInt(self._c_posit)
899
900 cpdef void iadd(self, Posit32 other):
901 self._c_posit = cposit.p32_add(self._c_posit, other._c_posit)
902
903 def __iadd__(self, Posit32 other):
904 self.iadd(other)
905 return self
906
907 cpdef void isub(self, Posit32 other):
908 self._c_posit = cposit.p32_sub(self._c_posit, other._c_posit)
909
910 def __isub__(self, Posit32 other):
911 self.isub(other)
912 return self
913
914 cpdef void imul(self, Posit32 other):
915 self._c_posit = cposit.p32_mul(self._c_posit, other._c_posit)
916
917 def __imul__(self, Posit32 other):
918 self.imul(other)
919 return self
920
921 cpdef void ifma(self, Posit32 a1, Posit32 a2):
922 self._c_posit = cposit.p32_mulAdd(a1._c_posit, a2._c_posit, self._c_posit)
923
924 cpdef void idiv(self, Posit32 other):
925 self._c_posit = cposit.p32_div(self._c_posit, other._c_posit)
926
927 def __itruediv__(self, Posit32 other):
928 self.idiv(other)
929 return self
930
931 cpdef void isqrt(self):
932 self._c_posit = cposit.p32_sqrt(self._c_posit)
933
934 # comparison
935
936 cpdef bint eq(self, Posit32 other):
937 return cposit.p32_eq(self._c_posit, other._c_posit)
938
939 cpdef bint le(self, Posit32 other):
940 return cposit.p32_le(self._c_posit, other._c_posit)
941
942 cpdef bint lt(self, Posit32 other):
943 return cposit.p32_lt(self._c_posit, other._c_posit)
944
945 def __lt__(self, Posit32 other):
946 return self.lt(other)
947
948 def __le__(self, Posit32 other):
949 return self.le(other)
950
951 def __eq__(self, Posit32 other):
952 return self.eq(other)
953
954 def __ne__(self, Posit32 other):
955 return not self.eq(other)
956
957 def __ge__(self, Posit32 other):
958 return other.le(self)
959
960 def __gt__(self, Posit32 other):
961 return other.lt(self)
962
963 # conversion to other posit types
964
965 cpdef to_p8(self):
966 cdef cposit.posit8_t f = cposit.p32_to_p8(self._c_posit)
967 return Posit8.from_c_posit(f)
968
969 cpdef to_p16(self):
970 cdef cposit.posit16_t f = cposit.p32_to_p16(self._c_posit)
971 return Posit16.from_c_posit(f)
972
973 cpdef to_quire(self):
974 cdef cposit.quire32_t f
975 f = cposit.q32_clr(f)
976 f = cposit.q32_fdp_add(f, self._c_posit, _p32_one)
977 return Quire32.from_c_quire(f)
978
979
980 cdef class Quire32:
981
982 # the wrapped quire value
983 cdef cposit.quire32_t _c_quire
984
985 # factory function constructors that bypass init
986
987 @staticmethod
988 cdef Quire32 from_c_quire(cposit.quire32_t f):
989 """Factory function to create a Quire32 object directly from
990 a C quire32_t.
991 """
992 cdef Quire32 obj = Quire32.__new__(Quire32)
993 obj._c_quire = f
994 return obj
995
996 @staticmethod
997 def from_bits(value):
998 """Factory function to create a Quire32 object from a bit pattern
999 represented as an integer.
1000 """
1001 cdef Quire32 obj = Quire32.__new__(Quire32)
1002
1003 if not isinstance(value, int):
1004 raise TypeError('expecting int, got {}'.format(repr(value)))
1005
1006 for idx in range(7, -1, -1):
1007 obj._c_quire.v[idx] = value & 0xffffffffffffffff
1008 value >>= 64
1009
1010 if not (value == 0):
1011 raise OverflowError('value too large to fit in uint64_t[8]')
1012
1013 return obj
1014
1015 # convenience interface for use inside Python
1016
1017 def __init__(self, value):
1018 if isinstance(value, int):
1019 for idx in range(7, -1, -1):
1020 self._c_quire.v[idx] = value & 0xffffffffffffffff
1021 value >>= 64
1022 if not (value == 0):
1023 raise OverflowError('value too large to fit in uint64_t[8]')
1024 else:
1025 f = float(value)
1026 self._c_quire = cposit.q32_clr(self._c_quire)
1027 self._c_quire = cposit.q32_fdp_add(self._c_quire, cposit.convertDoubleToP32(f), _p32_one)
1028
1029 def __float__(self):
1030 return cposit.convertP32ToDouble(cposit.q32_to_p32(self._c_quire))
1031
1032 def __int__(self):
1033 return int(cposit.convertP32ToDouble(cposit.q32_to_p32(self._c_quire)))
1034
1035 def __str__(self):
1036 return repr(cposit.convertP32ToDouble(cposit.q32_to_p32(self._c_quire)))
1037
1038 def __repr__(self):
1039 return 'Quire32(' + repr(cposit.convertP32ToDouble(cposit.q32_to_p32(self._c_quire))) + ')'
1040
1041 def get_bits(self):
1042 b = 0
1043 for u in self._c_quire.v:
1044 b <<= 64
1045 b |= u
1046 return b
1047 bits = property(get_bits)
1048
1049 # arithmetic
1050
1051 cpdef Quire32 qma(self, Posit32 a1, Posit32 a2):
1052 cdef cposit.quire32_t f = cposit.q32_fdp_add(self._c_quire, a1._c_posit, a2._c_posit)
1053 return Quire32.from_c_quire(f)
1054
1055 cpdef Quire32 qms(self, Posit32 a1, Posit32 a2):
1056 cdef cposit.quire32_t f = cposit.q32_fdp_sub(self._c_quire, a1._c_posit, a2._c_posit)
1057 return Quire32.from_c_quire(f)
1058
1059 cpdef void iqma(self, Posit32 a1, Posit32 a2):
1060 self._c_quire = cposit.q32_fdp_add(self._c_quire, a1._c_posit, a2._c_posit)
1061
1062 cpdef void iqms(self, Posit32 a1, Posit32 a2):
1063 self._c_quire = cposit.q32_fdp_sub(self._c_quire, a1._c_posit, a2._c_posit)
1064
1065 cpdef void iclr(self):
1066 self._c_quire = cposit.q32_clr(self._c_quire)
1067
1068 # conversion back to posit
1069
1070 cpdef Posit32 to_posit(self):
1071 cpdef cposit.posit32_t f = cposit.q32_to_p32(self._c_quire)
1072 return Posit32.from_c_posit(f)
1073
1074
1075 # external, non-method arithmetic
1076
1077 cpdef Posit32 p32_neg(Posit32 a1):
1078 cdef cposit.posit32_t f = _p32_neg(a1._c_posit)
1079 return Posit32.from_c_posit(f)
1080
1081 cpdef Posit32 p32_abs(Posit32 a1):
1082 cdef cposit.posit32_t f = _p32_abs(a1._c_posit)
1083 return Posit32.from_c_posit(f)
1084
1085 cpdef Posit32 p32_round(Posit32 a1):
1086 cdef cposit.posit32_t f = cposit.p32_roundToInt(a1._c_posit)
1087 return Posit32.from_c_posit(f)
1088
1089 cpdef Posit32 p32_add(Posit32 a1, Posit32 a2):
1090 cdef cposit.posit32_t f = cposit.p32_add(a1._c_posit, a2._c_posit)
1091 return Posit32.from_c_posit(f)
1092
1093 cpdef Posit32 p32_sub(Posit32 a1, Posit32 a2):
1094 cdef cposit.posit32_t f = cposit.p32_sub(a1._c_posit, a2._c_posit)
1095 return Posit32.from_c_posit(f)
1096
1097 cpdef Posit32 p32_mul(Posit32 a1, Posit32 a2):
1098 cdef cposit.posit32_t f = cposit.p32_mul(a1._c_posit, a2._c_posit)
1099 return Posit32.from_c_posit(f)
1100
1101 cpdef Posit32 p32_fma(Posit32 acc, Posit32 a1, Posit32 a2):
1102 cdef cposit.posit32_t f = cposit.p32_mulAdd(a1._c_posit, a2._c_posit, acc._c_posit)
1103 return Posit32.from_c_posit(f)
1104
1105 cpdef Posit32 p32_div(Posit32 a1, Posit32 a2):
1106 cdef cposit.posit32_t f = cposit.p32_div(a1._c_posit, a2._c_posit)
1107 return Posit32.from_c_posit(f)
1108
1109 cpdef Posit32 p32_sqrt(Posit32 a1):
1110 cdef cposit.posit32_t f = cposit.p32_sqrt(a1._c_posit)
1111 return Posit32.from_c_posit(f)
1112
1113 cpdef bint p32_eq(Posit32 a1, Posit32 a2):
1114 return cposit.p32_eq(a1._c_posit, a2._c_posit)
1115
1116 cpdef bint p32_le(Posit32 a1, Posit32 a2):
1117 return cposit.p32_le(a1._c_posit, a2._c_posit)
1118
1119 cpdef bint p32_lt(Posit32 a1, Posit32 a2):
1120 return cposit.p32_lt(a1._c_posit, a2._c_posit)
1121
1122 cpdef Posit8 p32_to_p8(Posit32 a1):
1123 cdef cposit.posit8_t f = cposit.p32_to_p8(a1._c_posit)
1124 return Posit8.from_c_posit(f)
1125
1126 cpdef Posit16 p32_to_p16(Posit32 a1):
1127 cdef cposit.posit16_t f = cposit.p32_to_p16(a1._c_posit)
1128 return Posit16.from_c_posit(f)
1129
1130 cpdef Quire32 p32_to_q32(Posit32 a1):
1131 cdef cposit.quire32_t f
1132 f = cposit.q32_clr(f)
1133 f = cposit.q32_fdp_add(f, a1._c_posit, _p32_one)
1134 return Quire32.from_c_quire(f)
1135
1136 cpdef Quire32 q32_qma(Quire32 acc, Posit32 a1, Posit32 a2):
1137 cdef cposit.quire32_t f = cposit.q32_fdp_add(acc._c_quire, a1._c_posit, a2._c_posit)
1138 return Quire32.from_c_quire(f)
1139
1140 cpdef Quire32 q32_qms(Quire32 acc, Posit32 a1, Posit32 a2):
1141 cdef cposit.quire32_t f = cposit.q32_fdp_sub(acc._c_quire, a1._c_posit, a2._c_posit)
1142 return Quire32.from_c_quire(f)
1143
1144 cpdef Posit32 q32_to_p32(Quire32 a1):
1145 cpdef cposit.posit32_t f = cposit.q32_to_p32(a1._c_quire)
1146 return Posit32.from_c_posit(f)