From 613fd66860992ec270d1515a4cd92b4468bc6280 Mon Sep 17 00:00:00 2001 From: Bill Zorn Date: Thu, 2 Aug 2018 19:31:19 -0700 Subject: [PATCH] update posit interface --- sfpy/cposit.pxd | 100 +++++++---- sfpy/posit.pyx | 458 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 437 insertions(+), 121 deletions(-) diff --git a/sfpy/cposit.pxd b/sfpy/cposit.pxd index c7c4c3e..ad205d3 100644 --- a/sfpy/cposit.pxd +++ b/sfpy/cposit.pxd @@ -1,30 +1,60 @@ from libc.stdint cimport * +# As far as I can tell, this is never enabled when the library is comiled... +# The option will have to be synced manually, as by the time Cython's c is +# compiled the library will already be stored as a .a file and any compile-time +# options used to build it will be long gone. +DEF SOFTPOSIT_EXACT = 0 + cdef extern from '../SoftPosit/source/include/softposit.h': - ctypedef struct posit8_t: - pass + # Transparent types so we can have access to the raw bits. + + IF SOFTPOSIT_EXACT: + + ctypedef struct posit8_t: + uint8_t v; + bint exact; + + ctypedef struct quire8_t: + uint32_t v; + bint exact; + + ctypedef struct posit16_t: + uint16_t v; + bint exact; - ctypedef struct posit16_t: - pass + ctypedef struct quire16_t: + uint64_t v[2]; + bint exact; - ctypedef struct posit32_t: - pass + ctypedef struct posit32_t: + uint32_t v; + bint exact; - ctypedef struct posit64_t: - pass + ctypedef struct quire32_t: + uint64_t v[8]; + bint exact; - ctypedef struct posit128_t: - pass + ELSE: - ctypedef struct quire8_t: - pass + ctypedef struct posit8_t: + uint8_t v; - ctypedef struct quire16_t: - pass + ctypedef struct posit16_t: + uint16_t v; - ctypedef struct quire32_t: - pass + ctypedef struct posit32_t: + uint32_t v; + + ctypedef struct quire8_t: + uint32_t v; + + ctypedef struct quire16_t: + uint64_t v[2]; + + ctypedef struct quire32_t: + uint64_t v[8]; # /*---------------------------------------------------------------------------- # | Integer-to-posit conversion routines. @@ -32,23 +62,23 @@ cdef extern from '../SoftPosit/source/include/softposit.h': posit8_t ui32_to_p8( uint32_t ); posit16_t ui32_to_p16( uint32_t ); - posit32_t ui32_to_p32( uint32_t ); - posit64_t ui32_to_p64( uint32_t ); + # posit32_t ui32_to_p32( uint32_t ); + # posit64_t ui32_to_p64( uint32_t ); posit8_t ui64_to_p8( uint64_t ); posit16_t ui64_to_p16( uint64_t ); - posit32_t ui64_to_p32( uint64_t ); - posit64_t ui64_to_p64( uint64_t ); + # posit32_t ui64_to_p32( uint64_t ); + # posit64_t ui64_to_p64( uint64_t ); posit8_t i32_to_p8( int32_t ); posit16_t i32_to_p16( int32_t ); - posit32_t i32_to_p32( int32_t ); - posit64_t i32_to_p64( int32_t ); + # posit32_t i32_to_p32( int32_t ); + # posit64_t i32_to_p64( int32_t ); posit8_t i64_to_p8( int64_t ); posit16_t i64_to_p16( int64_t ); - posit32_t i64_to_p32( int64_t ); - posit64_t i64_to_p64( int64_t ); + # posit32_t i64_to_p32( int64_t ); + # posit64_t i64_to_p64( int64_t ); # /*---------------------------------------------------------------------------- # | 8-bit (quad-precision) posit operations. @@ -62,8 +92,8 @@ cdef extern from '../SoftPosit/source/include/softposit.h': int_fast64_t p8_to_i64( posit8_t ); posit16_t p8_to_p16( posit8_t ); - #posit32_t p8_to_p32( posit8_t ); - #posit64_t p8_to_p64( posit8_t ); + # posit32_t p8_to_p32( posit8_t ); + # posit64_t p8_to_p64( posit8_t ); posit8_t p8_roundToInt( posit8_t ); posit8_t p8_add( posit8_t, posit8_t ); @@ -98,14 +128,14 @@ cdef extern from '../SoftPosit/source/include/softposit.h': # *----------------------------------------------------------------------------*/ bint isNaRP16UI( uint16_t ); - + uint_fast32_t p16_to_ui32( posit16_t ); uint_fast64_t p16_to_ui64( posit16_t ); int_fast32_t p16_to_i32( posit16_t); int_fast64_t p16_to_i64( posit16_t ); posit8_t p16_to_p8( posit16_t ); - #posit32_t p16_to_p32( posit16_t ); - #posit64_t p16_to_p64( posit16_t ); + # posit32_t p16_to_p32( posit16_t ); + # posit64_t p16_to_p64( posit16_t ); posit16_t p16_roundToInt( posit16_t); posit16_t p16_add( posit16_t, posit16_t ); @@ -118,18 +148,18 @@ cdef extern from '../SoftPosit/source/include/softposit.h': bint p16_le( posit16_t, posit16_t ); bint p16_lt( posit16_t, posit16_t ); - #Quire 16 + # Quire 16 quire16_t q16_fdp_add( quire16_t, posit16_t, posit16_t ); quire16_t q16_fdp_sub( quire16_t, posit16_t, posit16_t ); - #posit16_t convertQ16ToP16( quire16_t ); + # posit16_t convertQ16ToP16( quire16_t ); posit16_t q16_to_p16( quire16_t ); bint isNaRQ16( quire16_t ); bint isQ16Zero( quire16_t ); - #quire16_t q16_TwosComplement( quire16_t ); + # quire16_t q16_TwosComplement( quire16_t ); - #void printBinary( uint64_t*, int ); - #void printHex( uint64_t ); + # void printBinary( uint64_t*, int ); + # void printHex( uint64_t ); quire16_t q16_clr( quire16_t ); quire16_t castQ16( uint16_t, uint16_t ); @@ -139,5 +169,5 @@ cdef extern from '../SoftPosit/source/include/softposit.h': # Helper double convertP16ToDouble( posit16_t ); - #posit16_t convertFloatToP16( float ); + # posit16_t convertFloatToP16( float ); posit16_t convertDoubleToP16( double ); diff --git a/sfpy/posit.pyx b/sfpy/posit.pyx index ce3888c..d09b603 100644 --- a/sfpy/posit.pyx +++ b/sfpy/posit.pyx @@ -1,5 +1,13 @@ +from libc.stdint cimport * cimport cposit + +# special values needed for some initializations + +cdef posit8_one = cposit.ui32_to_p8(1) +cdef posit16_one = cposit.ui32_to_p16(1) + + cdef class Posit8: # the wrapped posit value @@ -17,16 +25,16 @@ cdef class Posit8: return obj @staticmethod - def from_bits(int value): + def from_bits(uint8_t value): """Factory function to create a Posit8 object from a bit pattern represented as an integer. """ cdef Posit8 obj = Posit8.__new__(Posit8) - obj._c_posit = cposit.castP8(value) + obj._c_posit.v = value return obj @staticmethod - def from_double(float value): + def from_double(double value): """Factory function to create a Posit8 object from a double. """ cdef Posit8 obj = Posit8.__new__(Posit8) @@ -37,119 +45,128 @@ cdef class Posit8: def __init__(self, value): if isinstance(value, int): - self._c_posit = cposit.castP8(value) + self._c_posit.v = value else: f = float(value) self._c_posit = cposit.convertDoubleToP8(f) + def __float__(self): + return cposit.convertP8ToDouble(self._c_posit) + + def __int__(self): + return int(cposit.convertP8ToDouble(self._c_posit)) + def __str__(self): return repr(cposit.convertP8ToDouble(self._c_posit)) def __repr__(self): return 'Posit8(' + repr(cposit.convertP8ToDouble(self._c_posit)) + ')' - cpdef get_bits(self): - cdef int u = cposit.castUI8(self._c_posit) - return u + cpdef uint8_t get_bits(self): + return self._c_posit.v bits = property(get_bits) # arithmetic - cpdef round(self): + cpdef Posit8 round(self): cdef cposit.posit8_t f = cposit.p8_roundToInt(self._c_posit) return Posit8.from_c_posit(f) - def __round__(self, Posit8 other): - return self.roundToInt(other) + def __round__(self): + return self.roundToInt() - cpdef add(self, Posit8 other): + cpdef Posit8 add(self, Posit8 other): cdef cposit.posit8_t f = cposit.p8_add(self._c_posit, other._c_posit) return Posit8.from_c_posit(f) def __add__(self, Posit8 other): return self.add(other) - cpdef sub(self, Posit8 other): + cpdef Posit8 sub(self, Posit8 other): cdef cposit.posit8_t f = cposit.p8_sub(self._c_posit, other._c_posit) return Posit8.from_c_posit(f) def __sub__(self, Posit8 other): return self.sub(other) - cpdef mul(self, Posit8 other): + cpdef Posit8 mul(self, Posit8 other): cdef cposit.posit8_t f = cposit.p8_mul(self._c_posit, other._c_posit) return Posit8.from_c_posit(f) def __mul__(self, Posit8 other): return self.mul(other) - cpdef fma(self, Posit8 a2, Posit8 a3): - cdef cposit.posit8_t f = cposit.p8_mulAdd(self._c_posit, a2._c_posit, a3._c_posit) - return Posit8.from_c_posit(f) + cpdef Posit8 fma(self, Posit8 a2, Posit8 a3): + cdef cposit.posit8_t f = cposit.p8_mulAdd(self._c_posit, a2._c_posit, a3._c_posit) + return Posit8.from_c_posit(f) - cpdef div(self, Posit8 other): + cpdef Posit8 qma(self, Posit8 a1, Posit8 a2): + cdef cposit.posit8_t f = cposit.p8_mulAdd(a1._c_posit, a2._c_posit, self._c_posit) + return Posit8.from_c_posit(f) + + cpdef Posit8 div(self, Posit8 other): cdef cposit.posit8_t f = cposit.p8_div(self._c_posit, other._c_posit) return Posit8.from_c_posit(f) def __truediv__(self, Posit8 other): return self.div(other) - cpdef sqrt(self): + cpdef Posit8 sqrt(self): cdef cposit.posit8_t f = cposit.p8_sqrt(self._c_posit) return Posit8.from_c_posit(f) # in-place arithmetic - cpdef iround(self): + cpdef void iround(self): self._c_posit = cposit.p8_roundToInt(self._c_posit) - cpdef iadd(self, Posit8 other): + cpdef void iadd(self, Posit8 other): self._c_posit = cposit.p8_add(self._c_posit, other._c_posit) def __iadd__(self, Posit8 other): self.iadd(other) return self - cpdef isub(self, Posit8 other): + cpdef void isub(self, Posit8 other): self._c_posit = cposit.p8_sub(self._c_posit, other._c_posit) def __isub__(self, Posit8 other): self.isub(other) return self - cpdef imul(self, Posit8 other): + cpdef void imul(self, Posit8 other): self._c_posit = cposit.p8_mul(self._c_posit, other._c_posit) def __imul__(self, Posit8 other): self.imul(other) return self - cpdef ifma(self, Posit8 a2, Posit8 a3): + cpdef void ifma(self, Posit8 a2, Posit8 a3): self._c_posit = cposit.p8_mulAdd(self._c_posit, a2._c_posit, a3._c_posit) - cpdef idiv(self, Posit8 other): + cpdef void iqma(self, Posit8 a1, Posit8 a2): + self._c_posit = cposit.p8_mulAdd(a1._c_posit, a2._c_posit, self._c_posit) + + cpdef void idiv(self, Posit8 other): self._c_posit = cposit.p8_div(self._c_posit, other._c_posit) def __itruediv__(self, Posit8 other): self.idiv(other) return self - cpdef isqrt(self): + cpdef void isqrt(self): self._c_posit = cposit.p8_sqrt(self._c_posit) # comparison - cpdef eq(self, Posit8 other): - cdef bint b = cposit.p8_eq(self._c_posit, other._c_posit) - return b + cpdef bint eq(self, Posit8 other): + return cposit.p8_eq(self._c_posit, other._c_posit) - cpdef le(self, Posit8 other): - cdef bint b = cposit.p8_le(self._c_posit, other._c_posit) - return b + cpdef bint le(self, Posit8 other): + return cposit.p8_le(self._c_posit, other._c_posit) - cpdef lt(self, Posit8 other): - cdef bint b = cposit.p8_lt(self._c_posit, other._c_posit) - return b + cpdef bint lt(self, Posit8 other): + return cposit.p8_lt(self._c_posit, other._c_posit) def __lt__(self, Posit8 other): return self.lt(other) @@ -175,16 +192,53 @@ cdef class Posit8: cdef cposit.posit16_t f = cposit.p8_to_p16(self._c_posit) return Posit16.from_c_posit(f) + cpdef to_quire(self): + cdef cposit.quire8_t f + cposit.q8_clr(f) + f = cposit.q8_fdp_add(f, self._c_posit, posit8_one) + return Quire8.from_c_quire(f) + cdef class Quire8: # the wrapped quire value cdef cposit.quire8_t _c_quire - # limited interface for now + # factory function constructors that bypass init - def __cinit__(self): - cposit.q8_clr(self._c_quire) + @staticmethod + cdef Quire8 from_c_quire(cposit.quire8_t f): + """Factory function to create a Quire8 object directly from + a C quire8_t. + """ + cdef Quire8 obj = Quire8.__new__(Quire8) + obj._c_quire = f + return obj + + @staticmethod + def from_bits(uint32_t value): + """Factory function to create a Quire8 object from a bit pattern + represented as an integer. + """ + cdef Quire8 obj = Quire8.__new__(Quire8) + obj._c_quire.v = value + return obj + + # convenience interface for use inside Python + + def __init__(self, value): + if isinstance(value, int): + self._c_quire.v = value + else: + f = float(value) + cposit.q8_clr(self._c_quire) + self._c_quire = cposit.q8_fdp_add(self._c_quire, cposit.convertDoubleToP8(f), posit8_one) + + def __float__(self): + return cposit.convertP8ToDouble(cposit.q8_to_p8(self._c_quire)) + + def __int__(self): + return int(cposit.convertP8ToDouble(cposit.q8_to_p8(self._c_quire))) def __str__(self): return repr(cposit.convertP8ToDouble(cposit.q8_to_p8(self._c_quire))) @@ -192,16 +246,100 @@ cdef class Quire8: def __repr__(self): return 'Quire8(' + repr(cposit.convertP8ToDouble(cposit.q8_to_p8(self._c_quire))) + ')' - cpdef fdp_add(self, Posit8 a2, Posit8 a3): - self._c_quire = cposit.q8_fdp_add(self._c_quire, a2._c_posit, a3._c_posit) + cpdef uint32_t get_bits(self): + return self._c_quire.v + bits = property(get_bits) + + # arithmetic + + cpdef Quire8 qma(self, Posit8 a1, Posit8 a2): + cdef cposit.quire8_t f = cposit.q8_fdp_add(self._c_quire, a1._c_posit, a2._c_posit) + return Quire8.from_c_quire(f) + + cpdef Quire8 qms(self, Posit8 a1, Posit8 a2): + cdef cposit.quire8_t f = cposit.q8_fdp_sub(self._c_quire, a1._c_posit, a2._c_posit) + return Quire8.from_c_quire(f) + + cpdef void iqma(self, Posit8 a1, Posit8 a2): + self._c_quire = cposit.q8_fdp_add(self._c_quire, a1._c_posit, a2._c_posit) - cpdef fdp_sub(self, Posit8 a2, Posit8 a3): - self._c_quire = cposit.q8_fdp_sub(self._c_quire, a2._c_posit, a3._c_posit) + cpdef void iqms(self, Posit8 a1, Posit8 a2): + self._c_quire = cposit.q8_fdp_sub(self._c_quire, a1._c_posit, a2._c_posit) - cpdef get_p8(self): + cpdef void iclr(self): + cposit.q8_clr(self._c_quire) + + # conversion back to posit + + cpdef Posit8 to_posit(self): cpdef cposit.posit8_t f = cposit.q8_to_p8(self._c_quire) return Posit8.from_c_posit(f) - p8 = property(get_p8) + + +# external, non-method arithmetic + +cpdef Posit8 p8_round(Posit8 a1): + cdef cposit.posit8_t f = cposit.p8_roundToInt(a1._c_posit) + return Posit8.from_c_posit(f) + +cpdef Posit8 p8_add(Posit8 a1, Posit8 a2): + cdef cposit.posit8_t f = cposit.p8_add(a1._c_posit, a2._c_posit) + return Posit8.from_c_posit(f) + +cpdef Posit8 p8_sub(Posit8 a1, Posit8 a2): + cdef cposit.posit8_t f = cposit.p8_sub(a1._c_posit, a2._c_posit) + return Posit8.from_c_posit(f) + +cpdef Posit8 p8_mul(Posit8 a1, Posit8 a2): + cdef cposit.posit8_t f = cposit.p8_mul(a1._c_posit, a2._c_posit) + return Posit8.from_c_posit(f) + +cpdef Posit8 p8_fma(Posit8 a1, Posit8 a2, Posit8 a3): + cdef cposit.posit8_t f = cposit.p8_mulAdd(a1._c_posit, a2._c_posit, a3._c_posit) + return Posit8.from_c_posit(f) + +cpdef Posit8 p8_qma(Posit8 a3, Posit8 a1, Posit8 a2): + cdef cposit.posit8_t f = cposit.p8_mulAdd(a1._c_posit, a2._c_posit, a3._c_posit) + return Posit8.from_c_posit(f) + +cpdef Posit8 p8_div(Posit8 a1, Posit8 a2): + cdef cposit.posit8_t f = cposit.p8_div(a1._c_posit, a2._c_posit) + return Posit8.from_c_posit(f) + +cpdef Posit8 p8_sqrt(Posit8 a1): + cdef cposit.posit8_t f = cposit.p8_sqrt(a1._c_posit) + return Posit8.from_c_posit(f) + +cpdef bint p8_eq(Posit8 a1, Posit8 a2): + return cposit.p8_eq(a1._c_posit, a2._c_posit) + +cpdef bint p8_le(Posit8 a1, Posit8 a2): + return cposit.p8_le(a1._c_posit, a2._c_posit) + +cpdef bint p8_lt(Posit8 a1, Posit8 a2): + return cposit.p8_lt(a1._c_posit, a2._c_posit) + +cpdef Posit16 p8_to_p16(Posit8 a1): + cdef cposit.posit16_t f = cposit.p8_to_p16(a1._c_posit) + return Posit16.from_c_posit(f) + +cpdef Quire8 p8_to_q8(Posit8 a1): + cdef cposit.quire8_t f + cposit.q8_clr(f) + f = cposit.q8_fdp_add(f, a1._c_posit, posit8_one) + return Quire8.from_c_quire(f) + +cpdef Quire8 q8_qma(Quire8 a3, Posit8 a1, Posit8 a2): + cdef cposit.quire8_t f = cposit.q8_fdp_add(a3._c_quire, a1._c_posit, a2._c_posit) + return Quire8.from_c_quire(f) + +cpdef Quire8 q8_qms(Quire8 a3, Posit8 a1, Posit8 a2): + cdef cposit.quire8_t f = cposit.q8_fdp_sub(a3._c_quire, a1._c_posit, a2._c_posit) + return Quire8.from_c_quire(f) + +cpdef Posit8 q8_to_p8(Quire8 a1): + cpdef cposit.posit8_t f = cposit.q8_to_p8(a1._c_quire) + return Posit8.from_c_posit(f) cdef class Posit16: @@ -221,16 +359,16 @@ cdef class Posit16: return obj @staticmethod - def from_bits(int value): + def from_bits(uint16_t value): """Factory function to create a Posit16 object from a bit pattern represented as an integer. """ cdef Posit16 obj = Posit16.__new__(Posit16) - obj._c_posit = cposit.castP16(value) + obj._c_posit.v = value return obj @staticmethod - def from_double(float value): + def from_double(double value): """Factory function to create a Posit16 object from a double. """ cdef Posit16 obj = Posit16.__new__(Posit16) @@ -241,119 +379,128 @@ cdef class Posit16: def __init__(self, value): if isinstance(value, int): - self._c_posit = cposit.castP16(value) + self._c_posit.v = value else: f = float(value) self._c_posit = cposit.convertDoubleToP16(f) + def __float__(self): + return cposit.convertP16ToDouble(self._c_posit) + + def __int__(self): + return int(cposit.convertP16ToDouble(self._c_posit)) + def __str__(self): return repr(cposit.convertP16ToDouble(self._c_posit)) def __repr__(self): return 'Posit16(' + repr(cposit.convertP16ToDouble(self._c_posit)) + ')' - cpdef get_bits(self): - cdef int u = cposit.castUI16(self._c_posit) - return u + cpdef uint16_t get_bits(self): + return self._c_posit.v bits = property(get_bits) # arithmetic - cpdef round(self): + cpdef Posit16 round(self): cdef cposit.posit16_t f = cposit.p16_roundToInt(self._c_posit) return Posit16.from_c_posit(f) - def __round__(self, Posit16 other): - return self.roundToInt(other) + def __round__(self): + return self.roundToInt() - cpdef add(self, Posit16 other): + cpdef Posit16 add(self, Posit16 other): cdef cposit.posit16_t f = cposit.p16_add(self._c_posit, other._c_posit) return Posit16.from_c_posit(f) def __add__(self, Posit16 other): return self.add(other) - cpdef sub(self, Posit16 other): + cpdef Posit16 sub(self, Posit16 other): cdef cposit.posit16_t f = cposit.p16_sub(self._c_posit, other._c_posit) return Posit16.from_c_posit(f) def __sub__(self, Posit16 other): return self.sub(other) - cpdef mul(self, Posit16 other): + cpdef Posit16 mul(self, Posit16 other): cdef cposit.posit16_t f = cposit.p16_mul(self._c_posit, other._c_posit) return Posit16.from_c_posit(f) def __mul__(self, Posit16 other): return self.mul(other) - cpdef fma(self, Posit16 a2, Posit16 a3): - cdef cposit.posit16_t f = cposit.p16_mulAdd(self._c_posit, a2._c_posit, a3._c_posit) - return Posit16.from_c_posit(f) + cpdef Posit16 fma(self, Posit16 a2, Posit16 a3): + cdef cposit.posit16_t f = cposit.p16_mulAdd(self._c_posit, a2._c_posit, a3._c_posit) + return Posit16.from_c_posit(f) + + cpdef Posit16 qma(self, Posit16 a1, Posit16 a2): + cdef cposit.posit16_t f = cposit.p16_mulAdd(a1._c_posit, a2._c_posit, self._c_posit) + return Posit16.from_c_posit(f) - cpdef div(self, Posit16 other): + cpdef Posit16 div(self, Posit16 other): cdef cposit.posit16_t f = cposit.p16_div(self._c_posit, other._c_posit) return Posit16.from_c_posit(f) def __truediv__(self, Posit16 other): return self.div(other) - cpdef sqrt(self): + cpdef Posit16 sqrt(self): cdef cposit.posit16_t f = cposit.p16_sqrt(self._c_posit) return Posit16.from_c_posit(f) # in-place arithmetic - cpdef iround(self): + cpdef void iround(self): self._c_posit = cposit.p16_roundToInt(self._c_posit) - cpdef iadd(self, Posit16 other): + cpdef void iadd(self, Posit16 other): self._c_posit = cposit.p16_add(self._c_posit, other._c_posit) def __iadd__(self, Posit16 other): self.iadd(other) return self - cpdef isub(self, Posit16 other): + cpdef void isub(self, Posit16 other): self._c_posit = cposit.p16_sub(self._c_posit, other._c_posit) def __isub__(self, Posit16 other): self.isub(other) return self - cpdef imul(self, Posit16 other): + cpdef void imul(self, Posit16 other): self._c_posit = cposit.p16_mul(self._c_posit, other._c_posit) def __imul__(self, Posit16 other): self.imul(other) return self - cpdef ifma(self, Posit16 a2, Posit16 a3): + cpdef void ifma(self, Posit16 a2, Posit16 a3): self._c_posit = cposit.p16_mulAdd(self._c_posit, a2._c_posit, a3._c_posit) - cpdef idiv(self, Posit16 other): + cpdef void iqma(self, Posit16 a1, Posit16 a2): + self._c_posit = cposit.p16_mulAdd(a1._c_posit, a2._c_posit, self._c_posit) + + cpdef void idiv(self, Posit16 other): self._c_posit = cposit.p16_div(self._c_posit, other._c_posit) def __itruediv__(self, Posit16 other): self.idiv(other) return self - cpdef isqrt(self): + cpdef void isqrt(self): self._c_posit = cposit.p16_sqrt(self._c_posit) # comparison - cpdef eq(self, Posit16 other): - cdef bint b = cposit.p16_eq(self._c_posit, other._c_posit) - return b + cpdef bint eq(self, Posit16 other): + return cposit.p16_eq(self._c_posit, other._c_posit) - cpdef le(self, Posit16 other): - cdef bint b = cposit.p16_le(self._c_posit, other._c_posit) - return b + cpdef bint le(self, Posit16 other): + return cposit.p16_le(self._c_posit, other._c_posit) - cpdef lt(self, Posit16 other): - cdef bint b = cposit.p16_lt(self._c_posit, other._c_posit) - return b + cpdef bint lt(self, Posit16 other): + return cposit.p16_lt(self._c_posit, other._c_posit) def __lt__(self, Posit16 other): return self.lt(other) @@ -379,16 +526,67 @@ cdef class Posit16: cdef cposit.posit8_t f = cposit.p16_to_p8(self._c_posit) return Posit8.from_c_posit(f) + cpdef to_quire(self): + cdef cposit.quire16_t f + cposit.q16_clr(f) + f = cposit.q16_fdp_add(f, self._c_posit, posit16_one) + return Quire16.from_c_quire(f) + cdef class Quire16: # the wrapped quire value cdef cposit.quire16_t _c_quire - # limited interface for now + # factory function constructors that bypass init - def __cinit__(self): - cposit.q16_clr(self._c_quire) + @staticmethod + cdef Quire16 from_c_quire(cposit.quire16_t f): + """Factory function to create a Quire16 object directly from + a C quire16_t. + """ + cdef Quire16 obj = Quire16.__new__(Quire16) + obj._c_quire = f + return obj + + @staticmethod + def from_bits(value): + """Factory function to create a Quire16 object from a bit pattern + represented as an integer. + """ + cdef Quire16 obj = Quire16.__new__(Quire16) + + if not isinstance(value, int): + raise TypeError('expecting int, got {}'.format(repr(value))) + + for idx in range(1, -1, -1): + obj._c_quire.v[idx] = value & 0xffffffffffffffff + value >>= 64 + + if not (value == 0): + raise OverflowError('value too large to fit in uint64_t[2]') + + return obj + + # convenience interface for use inside Python + + def __init__(self, value): + if isinstance(value, int): + for idx in range(1, -1, -1): + self._c_quire.v[idx] = value & 0xffffffffffffffff + value >>= 64 + if not (value == 0): + raise OverflowError('value too large to fit in uint64_t[2]') + else: + f = float(value) + cposit.q16_clr(self._c_quire) + self._c_quire = cposit.q16_fdp_add(self._c_quire, cposit.convertDoubleToP16(f), posit16_one) + + def __float__(self): + return cposit.convertP16ToDouble(cposit.q16_to_p16(self._c_quire)) + + def __int__(self): + return int(cposit.convertP16ToDouble(cposit.q16_to_p16(self._c_quire))) def __str__(self): return repr(cposit.convertP16ToDouble(cposit.q16_to_p16(self._c_quire))) @@ -396,13 +594,101 @@ cdef class Quire16: def __repr__(self): return 'Quire16(' + repr(cposit.convertP16ToDouble(cposit.q16_to_p16(self._c_quire))) + ')' - cpdef fdp_add(self, Posit16 a2, Posit16 a3): - self._c_quire = cposit.q16_fdp_add(self._c_quire, a2._c_posit, a3._c_posit) + def get_bits(self): + b = 0 + for u in self._c_quire.v: + b <<= 64 + b |= u + return b + bits = property(get_bits) + + # arithmetic + + cpdef Quire16 qma(self, Posit16 a1, Posit16 a2): + cdef cposit.quire16_t f = cposit.q16_fdp_add(self._c_quire, a1._c_posit, a2._c_posit) + return Quire16.from_c_quire(f) + + cpdef Quire16 qms(self, Posit16 a1, Posit16 a2): + cdef cposit.quire16_t f = cposit.q16_fdp_sub(self._c_quire, a1._c_posit, a2._c_posit) + return Quire16.from_c_quire(f) + + cpdef void iqma(self, Posit16 a1, Posit16 a2): + self._c_quire = cposit.q16_fdp_add(self._c_quire, a1._c_posit, a2._c_posit) - cpdef fdp_sub(self, Posit16 a2, Posit16 a3): - self._c_quire = cposit.q16_fdp_sub(self._c_quire, a2._c_posit, a3._c_posit) + cpdef void iqms(self, Posit16 a1, Posit16 a2): + self._c_quire = cposit.q16_fdp_sub(self._c_quire, a1._c_posit, a2._c_posit) - cpdef get_p16(self): + cpdef void iclr(self): + cposit.q16_clr(self._c_quire) + + # conversion back to posit + + cpdef Posit16 to_posit(self): cpdef cposit.posit16_t f = cposit.q16_to_p16(self._c_quire) return Posit16.from_c_posit(f) - p16 = property(get_p16) + + +# external, non-method arithmetic + +cpdef Posit16 p16_round(Posit16 a1): + cdef cposit.posit16_t f = cposit.p16_roundToInt(a1._c_posit) + return Posit16.from_c_posit(f) + +cpdef Posit16 p16_add(Posit16 a1, Posit16 a2): + cdef cposit.posit16_t f = cposit.p16_add(a1._c_posit, a2._c_posit) + return Posit16.from_c_posit(f) + +cpdef Posit16 p16_sub(Posit16 a1, Posit16 a2): + cdef cposit.posit16_t f = cposit.p16_sub(a1._c_posit, a2._c_posit) + return Posit16.from_c_posit(f) + +cpdef Posit16 p16_mul(Posit16 a1, Posit16 a2): + cdef cposit.posit16_t f = cposit.p16_mul(a1._c_posit, a2._c_posit) + return Posit16.from_c_posit(f) + +cpdef Posit16 p16_fma(Posit16 a1, Posit16 a2, Posit16 a3): + cdef cposit.posit16_t f = cposit.p16_mulAdd(a1._c_posit, a2._c_posit, a3._c_posit) + return Posit16.from_c_posit(f) + +cpdef Posit16 p16_qma(Posit16 a3, Posit16 a1, Posit16 a2): + cdef cposit.posit16_t f = cposit.p16_mulAdd(a1._c_posit, a2._c_posit, a3._c_posit) + return Posit16.from_c_posit(f) + +cpdef Posit16 p16_div(Posit16 a1, Posit16 a2): + cdef cposit.posit16_t f = cposit.p16_div(a1._c_posit, a2._c_posit) + return Posit16.from_c_posit(f) + +cpdef Posit16 p16_sqrt(Posit16 a1): + cdef cposit.posit16_t f = cposit.p16_sqrt(a1._c_posit) + return Posit16.from_c_posit(f) + +cpdef bint p16_eq(Posit16 a1, Posit16 a2): + return cposit.p16_eq(a1._c_posit, a2._c_posit) + +cpdef bint p16_le(Posit16 a1, Posit16 a2): + return cposit.p16_le(a1._c_posit, a2._c_posit) + +cpdef bint p16_lt(Posit16 a1, Posit16 a2): + return cposit.p16_lt(a1._c_posit, a2._c_posit) + +cpdef Posit8 p16_to_p8(Posit16 a1): + cdef cposit.posit8_t f = cposit.p16_to_p8(a1._c_posit) + return Posit8.from_c_posit(f) + +cpdef Quire16 p16_to_q16(Posit16 a1): + cdef cposit.quire16_t f + cposit.q16_clr(f) + f = cposit.q16_fdp_add(f, a1._c_posit, posit16_one) + return Quire16.from_c_quire(f) + +cpdef Quire16 q16_qma(Quire16 a3, Posit16 a1, Posit16 a2): + cdef cposit.quire16_t f = cposit.q16_fdp_add(a3._c_quire, a1._c_posit, a2._c_posit) + return Quire16.from_c_quire(f) + +cpdef Quire16 q16_qms(Quire16 a3, Posit16 a1, Posit16 a2): + cdef cposit.quire16_t f = cposit.q16_fdp_sub(a3._c_quire, a1._c_posit, a2._c_posit) + return Quire16.from_c_quire(f) + +cpdef Posit16 q16_to_p16(Quire16 a1): + cpdef cposit.posit16_t f = cposit.q16_to_p16(a1._c_quire) + return Posit16.from_c_posit(f) -- 2.30.2