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