From: Bill Zorn Date: Wed, 25 Jul 2018 20:59:34 +0000 (-0700) Subject: Merge branch 'master' of github.com:billzorn/sfpy X-Git-Url: https://git.libre-soc.org/?p=sfpy.git;a=commitdiff_plain;h=bbabe0a19c2e72452a33f64f1126b91e20075df8;hp=16ef44383f258cb0dfb8d88b5aac6f56773ae3f1 Merge branch 'master' of github.com:billzorn/sfpy oops forgot to rebase --- diff --git a/cposit.pxd b/cposit.pxd deleted file mode 100644 index 913a96b..0000000 --- a/cposit.pxd +++ /dev/null @@ -1,143 +0,0 @@ -from libc.stdint cimport * - -cdef extern from 'SoftPosit/source/include/softposit.h': - - ctypedef struct posit8_t: - pass - - ctypedef struct posit16_t: - pass - - ctypedef struct posit32_t: - pass - - ctypedef struct posit64_t: - pass - - ctypedef struct posit128_t: - pass - - ctypedef struct quire8_t: - pass - - ctypedef struct quire16_t: - pass - - ctypedef struct quire32_t: - pass - - # /*---------------------------------------------------------------------------- - # | Integer-to-posit conversion routines. - # *----------------------------------------------------------------------------*/ - - 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 ); - - 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 ); - - 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 ); - - 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 ); - - # /*---------------------------------------------------------------------------- - # | 8-bit (quad-precision) posit operations. - # *----------------------------------------------------------------------------*/ - - bint isNaRP8UI( uint8_t ); - - uint_fast32_t p8_to_ui32( posit8_t ); - uint_fast64_t p8_to_ui64( posit8_t ); - int_fast32_t p8_to_i32( posit8_t ); - 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 ); - - posit8_t p8_roundToInt( posit8_t ); - posit8_t p8_add( posit8_t, posit8_t ); - posit8_t p8_sub( posit8_t, posit8_t ); - posit8_t p8_mul( posit8_t, posit8_t ); - posit8_t p8_mulAdd( posit8_t, posit8_t, posit8_t ); - posit8_t p8_div( posit8_t, posit8_t ); - posit8_t p8_sqrt( posit8_t ); - bint p8_eq( posit8_t, posit8_t ); - bint p8_le( posit8_t, posit8_t ); - bint p8_lt( posit8_t, posit8_t ); - - # Quire 8 - quire8_t q8_fdp_add( quire8_t, posit8_t, posit8_t ); - quire8_t q8_fdp_sub( quire8_t, posit8_t, posit8_t ); - posit8_t q8_to_p8( quire8_t ); - - bint isNaRQ8( quire8_t ); - bint isQ8Zero( quire8_t ); - quire8_t q8_clr( quire8_t ); - quire8_t castQ8( uint32_t ); - posit8_t castP8( uint8_t ); - uint8_t castUI8( posit8_t ); - posit8_t negP8( posit8_t ); - - # Helper - double convertP8ToDouble( posit8_t ); - posit8_t convertDoubleToP8( double ); - - # /*---------------------------------------------------------------------------- - # | 16-bit (half-precision) posit operations. - # *----------------------------------------------------------------------------*/ - - 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 ); - - posit16_t p16_roundToInt( posit16_t); - posit16_t p16_add( posit16_t, posit16_t ); - posit16_t p16_sub( posit16_t, posit16_t ); - posit16_t p16_mul( posit16_t, posit16_t ); - posit16_t p16_mulAdd( posit16_t, posit16_t, posit16_t ); - posit16_t p16_div( posit16_t, posit16_t ); - posit16_t p16_sqrt( posit16_t ); - bint p16_eq( posit16_t, posit16_t ); - bint p16_le( posit16_t, posit16_t ); - bint p16_lt( posit16_t, posit16_t ); - - #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 q16_to_p16( quire16_t ); - - bint isNaRQ16( quire16_t ); - bint isQ16Zero( quire16_t ); - #quire16_t q16_TwosComplement( quire16_t ); - - #void printBinary( uint64_t*, int ); - #void printHex( uint64_t ); - - quire16_t q16_clr( quire16_t ); - quire16_t castQ16( uint16_t, uint16_t ); - posit16_t castP16( uint16_t ); - uint16_t castUI16( posit16_t ); - posit16_t negP16( posit16_t ); - - # Helper - double convertP16ToDouble( posit16_t ); - #posit16_t convertFloatToP16( float ); - posit16_t convertDoubleToP16( double ); diff --git a/posit.pyx b/posit.pyx deleted file mode 100644 index ce3888c..0000000 --- a/posit.pyx +++ /dev/null @@ -1,408 +0,0 @@ -cimport cposit - -cdef class Posit8: - - # the wrapped posit value - cdef cposit.posit8_t _c_posit - - # factory function constructors that bypass __init__ - - @staticmethod - cdef Posit8 from_c_posit(cposit.posit8_t f): - """Factory function to create a Posit8 object directly from - a C posit8_t. - """ - cdef Posit8 obj = Posit8.__new__(Posit8) - obj._c_posit = f - return obj - - @staticmethod - def from_bits(int 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) - return obj - - @staticmethod - def from_double(float value): - """Factory function to create a Posit8 object from a double. - """ - cdef Posit8 obj = Posit8.__new__(Posit8) - obj._c_posit = cposit.convertDoubleToP8(value) - return obj - - # convenience interface for use inside Python - - def __init__(self, value): - if isinstance(value, int): - self._c_posit = cposit.castP8(value) - else: - f = float(value) - self._c_posit = cposit.convertDoubleToP8(f) - - 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 - bits = property(get_bits) - - # arithmetic - - cpdef 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) - - cpdef 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): - 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): - 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 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): - cdef cposit.posit8_t f = cposit.p8_sqrt(self._c_posit) - return Posit8.from_c_posit(f) - - # in-place arithmetic - - cpdef iround(self): - self._c_posit = cposit.p8_roundToInt(self._c_posit) - - cpdef 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): - 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): - 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): - self._c_posit = cposit.p8_mulAdd(self._c_posit, a2._c_posit, a3._c_posit) - - cpdef 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): - 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 le(self, Posit8 other): - cdef bint b = cposit.p8_le(self._c_posit, other._c_posit) - return b - - cpdef lt(self, Posit8 other): - cdef bint b = cposit.p8_lt(self._c_posit, other._c_posit) - return b - - def __lt__(self, Posit8 other): - return self.lt(other) - - def __le__(self, Posit8 other): - return self.le(other) - - def __eq__(self, Posit8 other): - return self.eq(other) - - def __ne__(self, Posit8 other): - return not self.eq(other) - - def __ge__(self, Posit8 other): - return other.le(self) - - def __gt__(self, Posit8 other): - return other.lt(self) - - # conversion to other posit types - - cpdef to_p16(self): - cdef cposit.posit16_t f = cposit.p8_to_p16(self._c_posit) - return Posit16.from_c_posit(f) - - -cdef class Quire8: - - # the wrapped quire value - cdef cposit.quire8_t _c_quire - - # limited interface for now - - def __cinit__(self): - cposit.q8_clr(self._c_quire) - - def __str__(self): - return repr(cposit.convertP8ToDouble(cposit.q8_to_p8(self._c_quire))) - - 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 fdp_sub(self, Posit8 a2, Posit8 a3): - self._c_quire = cposit.q8_fdp_sub(self._c_quire, a2._c_posit, a3._c_posit) - - cpdef get_p8(self): - cpdef cposit.posit8_t f = cposit.q8_to_p8(self._c_quire) - return Posit8.from_c_posit(f) - p8 = property(get_p8) - - -cdef class Posit16: - - # the wrapped posit value - cdef cposit.posit16_t _c_posit - - # factory function constructors that bypass __init__ - - @staticmethod - cdef Posit16 from_c_posit(cposit.posit16_t f): - """Factory function to create a Posit16 object directly from - a C posit16_t. - """ - cdef Posit16 obj = Posit16.__new__(Posit16) - obj._c_posit = f - return obj - - @staticmethod - def from_bits(int 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) - return obj - - @staticmethod - def from_double(float value): - """Factory function to create a Posit16 object from a double. - """ - cdef Posit16 obj = Posit16.__new__(Posit16) - obj._c_posit = cposit.convertDoubleToP16(value) - return obj - - # convenience interface for use inside Python - - def __init__(self, value): - if isinstance(value, int): - self._c_posit = cposit.castP16(value) - else: - f = float(value) - self._c_posit = cposit.convertDoubleToP16(f) - - 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 - bits = property(get_bits) - - # arithmetic - - cpdef 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) - - cpdef 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): - 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): - 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 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): - cdef cposit.posit16_t f = cposit.p16_sqrt(self._c_posit) - return Posit16.from_c_posit(f) - - # in-place arithmetic - - cpdef iround(self): - self._c_posit = cposit.p16_roundToInt(self._c_posit) - - cpdef 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): - 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): - 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): - self._c_posit = cposit.p16_mulAdd(self._c_posit, a2._c_posit, a3._c_posit) - - cpdef 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): - 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 le(self, Posit16 other): - cdef bint b = cposit.p16_le(self._c_posit, other._c_posit) - return b - - cpdef lt(self, Posit16 other): - cdef bint b = cposit.p16_lt(self._c_posit, other._c_posit) - return b - - def __lt__(self, Posit16 other): - return self.lt(other) - - def __le__(self, Posit16 other): - return self.le(other) - - def __eq__(self, Posit16 other): - return self.eq(other) - - def __ne__(self, Posit16 other): - return not self.eq(other) - - def __ge__(self, Posit16 other): - return other.le(self) - - def __gt__(self, Posit16 other): - return other.lt(self) - - # conversion to other posit types - - cpdef to_p8(self): - cdef cposit.posit8_t f = cposit.p16_to_p8(self._c_posit) - return Posit8.from_c_posit(f) - - -cdef class Quire16: - - # the wrapped quire value - cdef cposit.quire16_t _c_quire - - # limited interface for now - - def __cinit__(self): - cposit.q16_clr(self._c_quire) - - def __str__(self): - return repr(cposit.convertP16ToDouble(cposit.q16_to_p16(self._c_quire))) - - 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) - - 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 get_p16(self): - cpdef cposit.posit16_t f = cposit.q16_to_p16(self._c_quire) - return Posit16.from_c_posit(f) - p16 = property(get_p16) diff --git a/setup.py b/setup.py index 82b066d..2aa76e2 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,8 @@ from distutils.core import setup from distutils.extension import Extension from Cython.Build import cythonize -ext = Extension('posit', ['posit.pyx'], +posit_ext = Extension( + 'sfpy.posit', ['sfpy/posit.pyx'], include_dirs=['SoftPosit/source/include/'], extra_objects=['./SoftPosit/build/Linux-x86_64-GCC/softposit.a'], libraries=['m'], @@ -10,5 +11,11 @@ ext = Extension('posit', ['posit.pyx'], setup( name='sfpy', - ext_modules=cythonize([ext]), + version='0.1.0', + description='softfloat and softposit in python', + author='Bill Zorn', + author_email='bill.zorn@gmail.com', + url='https://github.com/billzorn/sfpy', + packages=['sfpy'], + ext_modules=cythonize([posit_ext]), ) diff --git a/sfpy/__init__.py b/sfpy/__init__.py new file mode 100644 index 0000000..d213f2b --- /dev/null +++ b/sfpy/__init__.py @@ -0,0 +1,6 @@ +import os +mypath = os.path.abspath(os.path.dirname(__file__)) + +print('hi from module sfpy @ {:s}'.format(mypath)) + +from .posit import Posit8, Quire8, Posit16, Quire16 diff --git a/sfpy/cposit.pxd b/sfpy/cposit.pxd new file mode 100644 index 0000000..c7c4c3e --- /dev/null +++ b/sfpy/cposit.pxd @@ -0,0 +1,143 @@ +from libc.stdint cimport * + +cdef extern from '../SoftPosit/source/include/softposit.h': + + ctypedef struct posit8_t: + pass + + ctypedef struct posit16_t: + pass + + ctypedef struct posit32_t: + pass + + ctypedef struct posit64_t: + pass + + ctypedef struct posit128_t: + pass + + ctypedef struct quire8_t: + pass + + ctypedef struct quire16_t: + pass + + ctypedef struct quire32_t: + pass + + # /*---------------------------------------------------------------------------- + # | Integer-to-posit conversion routines. + # *----------------------------------------------------------------------------*/ + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + # /*---------------------------------------------------------------------------- + # | 8-bit (quad-precision) posit operations. + # *----------------------------------------------------------------------------*/ + + bint isNaRP8UI( uint8_t ); + + uint_fast32_t p8_to_ui32( posit8_t ); + uint_fast64_t p8_to_ui64( posit8_t ); + int_fast32_t p8_to_i32( posit8_t ); + 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 ); + + posit8_t p8_roundToInt( posit8_t ); + posit8_t p8_add( posit8_t, posit8_t ); + posit8_t p8_sub( posit8_t, posit8_t ); + posit8_t p8_mul( posit8_t, posit8_t ); + posit8_t p8_mulAdd( posit8_t, posit8_t, posit8_t ); + posit8_t p8_div( posit8_t, posit8_t ); + posit8_t p8_sqrt( posit8_t ); + bint p8_eq( posit8_t, posit8_t ); + bint p8_le( posit8_t, posit8_t ); + bint p8_lt( posit8_t, posit8_t ); + + # Quire 8 + quire8_t q8_fdp_add( quire8_t, posit8_t, posit8_t ); + quire8_t q8_fdp_sub( quire8_t, posit8_t, posit8_t ); + posit8_t q8_to_p8( quire8_t ); + + bint isNaRQ8( quire8_t ); + bint isQ8Zero( quire8_t ); + quire8_t q8_clr( quire8_t ); + quire8_t castQ8( uint32_t ); + posit8_t castP8( uint8_t ); + uint8_t castUI8( posit8_t ); + posit8_t negP8( posit8_t ); + + # Helper + double convertP8ToDouble( posit8_t ); + posit8_t convertDoubleToP8( double ); + + # /*---------------------------------------------------------------------------- + # | 16-bit (half-precision) posit operations. + # *----------------------------------------------------------------------------*/ + + 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 ); + + posit16_t p16_roundToInt( posit16_t); + posit16_t p16_add( posit16_t, posit16_t ); + posit16_t p16_sub( posit16_t, posit16_t ); + posit16_t p16_mul( posit16_t, posit16_t ); + posit16_t p16_mulAdd( posit16_t, posit16_t, posit16_t ); + posit16_t p16_div( posit16_t, posit16_t ); + posit16_t p16_sqrt( posit16_t ); + bint p16_eq( posit16_t, posit16_t ); + bint p16_le( posit16_t, posit16_t ); + bint p16_lt( posit16_t, posit16_t ); + + #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 q16_to_p16( quire16_t ); + + bint isNaRQ16( quire16_t ); + bint isQ16Zero( quire16_t ); + #quire16_t q16_TwosComplement( quire16_t ); + + #void printBinary( uint64_t*, int ); + #void printHex( uint64_t ); + + quire16_t q16_clr( quire16_t ); + quire16_t castQ16( uint16_t, uint16_t ); + posit16_t castP16( uint16_t ); + uint16_t castUI16( posit16_t ); + posit16_t negP16( posit16_t ); + + # Helper + double convertP16ToDouble( posit16_t ); + #posit16_t convertFloatToP16( float ); + posit16_t convertDoubleToP16( double ); diff --git a/sfpy/posit.pyx b/sfpy/posit.pyx new file mode 100644 index 0000000..ce3888c --- /dev/null +++ b/sfpy/posit.pyx @@ -0,0 +1,408 @@ +cimport cposit + +cdef class Posit8: + + # the wrapped posit value + cdef cposit.posit8_t _c_posit + + # factory function constructors that bypass __init__ + + @staticmethod + cdef Posit8 from_c_posit(cposit.posit8_t f): + """Factory function to create a Posit8 object directly from + a C posit8_t. + """ + cdef Posit8 obj = Posit8.__new__(Posit8) + obj._c_posit = f + return obj + + @staticmethod + def from_bits(int 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) + return obj + + @staticmethod + def from_double(float value): + """Factory function to create a Posit8 object from a double. + """ + cdef Posit8 obj = Posit8.__new__(Posit8) + obj._c_posit = cposit.convertDoubleToP8(value) + return obj + + # convenience interface for use inside Python + + def __init__(self, value): + if isinstance(value, int): + self._c_posit = cposit.castP8(value) + else: + f = float(value) + self._c_posit = cposit.convertDoubleToP8(f) + + 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 + bits = property(get_bits) + + # arithmetic + + cpdef 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) + + cpdef 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): + 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): + 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 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): + cdef cposit.posit8_t f = cposit.p8_sqrt(self._c_posit) + return Posit8.from_c_posit(f) + + # in-place arithmetic + + cpdef iround(self): + self._c_posit = cposit.p8_roundToInt(self._c_posit) + + cpdef 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): + 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): + 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): + self._c_posit = cposit.p8_mulAdd(self._c_posit, a2._c_posit, a3._c_posit) + + cpdef 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): + 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 le(self, Posit8 other): + cdef bint b = cposit.p8_le(self._c_posit, other._c_posit) + return b + + cpdef lt(self, Posit8 other): + cdef bint b = cposit.p8_lt(self._c_posit, other._c_posit) + return b + + def __lt__(self, Posit8 other): + return self.lt(other) + + def __le__(self, Posit8 other): + return self.le(other) + + def __eq__(self, Posit8 other): + return self.eq(other) + + def __ne__(self, Posit8 other): + return not self.eq(other) + + def __ge__(self, Posit8 other): + return other.le(self) + + def __gt__(self, Posit8 other): + return other.lt(self) + + # conversion to other posit types + + cpdef to_p16(self): + cdef cposit.posit16_t f = cposit.p8_to_p16(self._c_posit) + return Posit16.from_c_posit(f) + + +cdef class Quire8: + + # the wrapped quire value + cdef cposit.quire8_t _c_quire + + # limited interface for now + + def __cinit__(self): + cposit.q8_clr(self._c_quire) + + def __str__(self): + return repr(cposit.convertP8ToDouble(cposit.q8_to_p8(self._c_quire))) + + 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 fdp_sub(self, Posit8 a2, Posit8 a3): + self._c_quire = cposit.q8_fdp_sub(self._c_quire, a2._c_posit, a3._c_posit) + + cpdef get_p8(self): + cpdef cposit.posit8_t f = cposit.q8_to_p8(self._c_quire) + return Posit8.from_c_posit(f) + p8 = property(get_p8) + + +cdef class Posit16: + + # the wrapped posit value + cdef cposit.posit16_t _c_posit + + # factory function constructors that bypass __init__ + + @staticmethod + cdef Posit16 from_c_posit(cposit.posit16_t f): + """Factory function to create a Posit16 object directly from + a C posit16_t. + """ + cdef Posit16 obj = Posit16.__new__(Posit16) + obj._c_posit = f + return obj + + @staticmethod + def from_bits(int 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) + return obj + + @staticmethod + def from_double(float value): + """Factory function to create a Posit16 object from a double. + """ + cdef Posit16 obj = Posit16.__new__(Posit16) + obj._c_posit = cposit.convertDoubleToP16(value) + return obj + + # convenience interface for use inside Python + + def __init__(self, value): + if isinstance(value, int): + self._c_posit = cposit.castP16(value) + else: + f = float(value) + self._c_posit = cposit.convertDoubleToP16(f) + + 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 + bits = property(get_bits) + + # arithmetic + + cpdef 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) + + cpdef 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): + 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): + 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 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): + cdef cposit.posit16_t f = cposit.p16_sqrt(self._c_posit) + return Posit16.from_c_posit(f) + + # in-place arithmetic + + cpdef iround(self): + self._c_posit = cposit.p16_roundToInt(self._c_posit) + + cpdef 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): + 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): + 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): + self._c_posit = cposit.p16_mulAdd(self._c_posit, a2._c_posit, a3._c_posit) + + cpdef 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): + 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 le(self, Posit16 other): + cdef bint b = cposit.p16_le(self._c_posit, other._c_posit) + return b + + cpdef lt(self, Posit16 other): + cdef bint b = cposit.p16_lt(self._c_posit, other._c_posit) + return b + + def __lt__(self, Posit16 other): + return self.lt(other) + + def __le__(self, Posit16 other): + return self.le(other) + + def __eq__(self, Posit16 other): + return self.eq(other) + + def __ne__(self, Posit16 other): + return not self.eq(other) + + def __ge__(self, Posit16 other): + return other.le(self) + + def __gt__(self, Posit16 other): + return other.lt(self) + + # conversion to other posit types + + cpdef to_p8(self): + cdef cposit.posit8_t f = cposit.p16_to_p8(self._c_posit) + return Posit8.from_c_posit(f) + + +cdef class Quire16: + + # the wrapped quire value + cdef cposit.quire16_t _c_quire + + # limited interface for now + + def __cinit__(self): + cposit.q16_clr(self._c_quire) + + def __str__(self): + return repr(cposit.convertP16ToDouble(cposit.q16_to_p16(self._c_quire))) + + 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) + + 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 get_p16(self): + cpdef cposit.posit16_t f = cposit.q16_to_p16(self._c_quire) + return Posit16.from_c_posit(f) + p16 = property(get_p16) diff --git a/timing.py b/timing.py new file mode 100644 index 0000000..ff13387 --- /dev/null +++ b/timing.py @@ -0,0 +1,55 @@ +"""Some basic performance tests for the wrapper class""" + +import timeit + + +def ops_sec(stmt, setup): + # print('----') + # print(setup) + print('-- timing: --') + print(stmt) + print('----') + + timer = timeit.Timer(stmt, setup) + iters, time = timer.autorange() + + rate = iters/time + if rate > 1000000000: + erate = rate / 1000000000 + unit = 'Gops' + elif rate > 1000000: + erate = rate / 1000000 + unit = 'Mops' + elif rate > 1000: + erate = rate / 1000 + unit = 'kops' + else: + erate = rate + unit = 'ops' + + print('{} ops, {} s, {} {}/s\n'.format(iters, time, erate, unit)) + + +setup = """import sfpy +P8 = sfpy.Posit8 +Q8 = sfpy.Quire8 +a = P8(1.3) +b = P8(-0.5) +c = P8(15.0) +q = Q8() +zero = 0.0 +""" + +ops_sec('pass', setup) +ops_sec('P8(0)', setup) +ops_sec('P8("0")', setup) +ops_sec('P8.from_bits(0)', setup) + +ops_sec('1.1 + 2', setup) +ops_sec('a + b', setup) +ops_sec('a.add(b)', setup) +ops_sec('zero += 1', setup) +ops_sec('a += b', setup) +ops_sec('a.iadd(b)', setup) + +ops_sec('q.fdp_add(b, c)', setup)