From f35c6aec3052d7fa5afd08de9f7621847239ad31 Mon Sep 17 00:00:00 2001 From: Bill Zorn Date: Thu, 2 Aug 2018 15:55:28 -0700 Subject: [PATCH] added support for berkeley softfloat 3 --- setup.py | 8 +- sfpy/__init__.py | 2 + sfpy/cfloat.pxd | 334 +++++++++++++++++ sfpy/float.pyx | 951 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1294 insertions(+), 1 deletion(-) create mode 100644 sfpy/cfloat.pxd create mode 100644 sfpy/float.pyx diff --git a/setup.py b/setup.py index 2aa76e2..7948964 100644 --- a/setup.py +++ b/setup.py @@ -9,6 +9,12 @@ posit_ext = Extension( libraries=['m'], ) +float_ext = Extension( + 'sfpy.float', ['sfpy/float.pyx'], + include_dirs=['berkeley-softfloat-3/source/include/'], + extra_objects=['./berkeley-softfloat-3/build/Linux-x86_64-GCC/softfloat.a'], +) + setup( name='sfpy', version='0.1.0', @@ -17,5 +23,5 @@ setup( author_email='bill.zorn@gmail.com', url='https://github.com/billzorn/sfpy', packages=['sfpy'], - ext_modules=cythonize([posit_ext]), + ext_modules=cythonize([posit_ext, float_ext]), ) diff --git a/sfpy/__init__.py b/sfpy/__init__.py index d213f2b..77dba97 100644 --- a/sfpy/__init__.py +++ b/sfpy/__init__.py @@ -4,3 +4,5 @@ mypath = os.path.abspath(os.path.dirname(__file__)) print('hi from module sfpy @ {:s}'.format(mypath)) from .posit import Posit8, Quire8, Posit16, Quire16 + +from .float import Float16, Float32, Float64 diff --git a/sfpy/cfloat.pxd b/sfpy/cfloat.pxd new file mode 100644 index 0000000..dc00f24 --- /dev/null +++ b/sfpy/cfloat.pxd @@ -0,0 +1,334 @@ +from libc.stdint cimport * + +# For bitwise conversion between Python floats and the uint containers +# needed to construct softfloat representations. +ctypedef union ui64_double: + uint64_t u; + double d; + +cdef extern from '../berkeley-softfloat-3/source/include/softfloat.h': + + # Transparent types so we can have access to the raw bits. + + ctypedef struct float16_t: + uint16_t v; + + ctypedef struct float32_t: + uint32_t v; + + ctypedef struct float64_t: + uint64_t v; + + ctypedef struct float128_t: + uint64_t v[2]; + + # /*---------------------------------------------------------------------------- + # | Software floating-point underflow tininess-detection mode. + # *----------------------------------------------------------------------------*/ + # extern uint_fast8_t softfloat_detectTininess; # THREAD_LOCAL + # cdef enum: + # softfloat_tininess_beforeRounding = 0 + # softfloat_tininess_afterRounding = 1 + + # /*---------------------------------------------------------------------------- + # | Software floating-point rounding mode. (Mode "odd" is supported only if + # | SoftFloat is compiled with macro 'SOFTFLOAT_ROUND_ODD' defined.) + # *----------------------------------------------------------------------------*/ + extern uint_fast8_t softfloat_roundingMode; # THREAD_LOCAL + cdef enum: + softfloat_round_near_even = 0 + softfloat_round_minMag = 1 + softfloat_round_min = 2 + softfloat_round_max = 3 + softfloat_round_near_maxMag = 4 + # softfloat_round_odd = 6 + + # /*---------------------------------------------------------------------------- + # | Software floating-point exception flags. + # *----------------------------------------------------------------------------*/ + extern uint_fast8_t softfloat_exceptionFlags; # THREAD_LOCAL + cdef enum: + softfloat_flag_inexact = 1 + softfloat_flag_underflow = 2 + softfloat_flag_overflow = 4 + softfloat_flag_infinite = 8 + softfloat_flag_invalid = 16 + + # /*---------------------------------------------------------------------------- + # | Routine to raise any or all of the software floating-point exception flags. + # *----------------------------------------------------------------------------*/ + void softfloat_raiseFlags( uint_fast8_t ); + + # /*---------------------------------------------------------------------------- + # | Integer-to-floating-point conversion routines. + # *----------------------------------------------------------------------------*/ + float16_t ui32_to_f16( uint32_t ); + float32_t ui32_to_f32( uint32_t ); + float64_t ui32_to_f64( uint32_t ); + # #ifdef SOFTFLOAT_FAST_INT64 + # extFloat80_t ui32_to_extF80( uint32_t ); + # float128_t ui32_to_f128( uint32_t ); + # #endif + # void ui32_to_extF80M( uint32_t, extFloat80_t * ); + # void ui32_to_f128M( uint32_t, float128_t * ); + float16_t ui64_to_f16( uint64_t ); + float32_t ui64_to_f32( uint64_t ); + float64_t ui64_to_f64( uint64_t ); + # #ifdef SOFTFLOAT_FAST_INT64 + # extFloat80_t ui64_to_extF80( uint64_t ); + # float128_t ui64_to_f128( uint64_t ); + # #endif + # void ui64_to_extF80M( uint64_t, extFloat80_t * ); + # void ui64_to_f128M( uint64_t, float128_t * ); + float16_t i32_to_f16( int32_t ); + float32_t i32_to_f32( int32_t ); + float64_t i32_to_f64( int32_t ); + # #ifdef SOFTFLOAT_FAST_INT64 + # extFloat80_t i32_to_extF80( int32_t ); + # float128_t i32_to_f128( int32_t ); + # #endif + # void i32_to_extF80M( int32_t, extFloat80_t * ); + # void i32_to_f128M( int32_t, float128_t * ); + float16_t i64_to_f16( int64_t ); + float32_t i64_to_f32( int64_t ); + float64_t i64_to_f64( int64_t ); + # #ifdef SOFTFLOAT_FAST_INT64 + # extFloat80_t i64_to_extF80( int64_t ); + # float128_t i64_to_f128( int64_t ); + # #endif + # void i64_to_extF80M( int64_t, extFloat80_t * ); + # void i64_to_f128M( int64_t, float128_t * ); + + # /*---------------------------------------------------------------------------- + # | 16-bit (half-precision) floating-point operations. + # *----------------------------------------------------------------------------*/ + uint_fast32_t f16_to_ui32( float16_t, uint_fast8_t, bint ); + uint_fast64_t f16_to_ui64( float16_t, uint_fast8_t, bint ); + int_fast32_t f16_to_i32( float16_t, uint_fast8_t, bint ); + int_fast64_t f16_to_i64( float16_t, uint_fast8_t, bint ); + uint_fast32_t f16_to_ui32_r_minMag( float16_t, bint ); + uint_fast64_t f16_to_ui64_r_minMag( float16_t, bint ); + int_fast32_t f16_to_i32_r_minMag( float16_t, bint ); + int_fast64_t f16_to_i64_r_minMag( float16_t, bint ); + float32_t f16_to_f32( float16_t ); + float64_t f16_to_f64( float16_t ); + # #ifdef SOFTFLOAT_FAST_INT64 + # extFloat80_t f16_to_extF80( float16_t ); + # float128_t f16_to_f128( float16_t ); + # #endif + # void f16_to_extF80M( float16_t, extFloat80_t * ); + # void f16_to_f128M( float16_t, float128_t * ); + float16_t f16_roundToInt( float16_t, uint_fast8_t, bint ); + float16_t f16_add( float16_t, float16_t ); + float16_t f16_sub( float16_t, float16_t ); + float16_t f16_mul( float16_t, float16_t ); + float16_t f16_mulAdd( float16_t, float16_t, float16_t ); + float16_t f16_div( float16_t, float16_t ); + float16_t f16_rem( float16_t, float16_t ); + float16_t f16_sqrt( float16_t ); + bint f16_eq( float16_t, float16_t ); + bint f16_le( float16_t, float16_t ); + bint f16_lt( float16_t, float16_t ); + bint f16_eq_signaling( float16_t, float16_t ); + bint f16_le_quiet( float16_t, float16_t ); + bint f16_lt_quiet( float16_t, float16_t ); + bint f16_isSignalingNaN( float16_t ); + + # /*---------------------------------------------------------------------------- + # | 32-bit (single-precision) floating-point operations. + # *----------------------------------------------------------------------------*/ + uint_fast32_t f32_to_ui32( float32_t, uint_fast8_t, bint ); + uint_fast64_t f32_to_ui64( float32_t, uint_fast8_t, bint ); + int_fast32_t f32_to_i32( float32_t, uint_fast8_t, bint ); + int_fast64_t f32_to_i64( float32_t, uint_fast8_t, bint ); + uint_fast32_t f32_to_ui32_r_minMag( float32_t, bint ); + uint_fast64_t f32_to_ui64_r_minMag( float32_t, bint ); + int_fast32_t f32_to_i32_r_minMag( float32_t, bint ); + int_fast64_t f32_to_i64_r_minMag( float32_t, bint ); + float16_t f32_to_f16( float32_t ); + float64_t f32_to_f64( float32_t ); + # #ifdef SOFTFLOAT_FAST_INT64 + # extFloat80_t f32_to_extF80( float32_t ); + # float128_t f32_to_f128( float32_t ); + # #endif + # void f32_to_extF80M( float32_t, extFloat80_t * ); + # void f32_to_f128M( float32_t, float128_t * ); + float32_t f32_roundToInt( float32_t, uint_fast8_t, bint ); + float32_t f32_add( float32_t, float32_t ); + float32_t f32_sub( float32_t, float32_t ); + float32_t f32_mul( float32_t, float32_t ); + float32_t f32_mulAdd( float32_t, float32_t, float32_t ); + float32_t f32_div( float32_t, float32_t ); + float32_t f32_rem( float32_t, float32_t ); + float32_t f32_sqrt( float32_t ); + bint f32_eq( float32_t, float32_t ); + bint f32_le( float32_t, float32_t ); + bint f32_lt( float32_t, float32_t ); + bint f32_eq_signaling( float32_t, float32_t ); + bint f32_le_quiet( float32_t, float32_t ); + bint f32_lt_quiet( float32_t, float32_t ); + bint f32_isSignalingNaN( float32_t ); + + # /*---------------------------------------------------------------------------- + # | 64-bit (double-precision) floating-point operations. + # *----------------------------------------------------------------------------*/ + uint_fast32_t f64_to_ui32( float64_t, uint_fast8_t, bint ); + uint_fast64_t f64_to_ui64( float64_t, uint_fast8_t, bint ); + int_fast32_t f64_to_i32( float64_t, uint_fast8_t, bint ); + int_fast64_t f64_to_i64( float64_t, uint_fast8_t, bint ); + uint_fast32_t f64_to_ui32_r_minMag( float64_t, bint ); + uint_fast64_t f64_to_ui64_r_minMag( float64_t, bint ); + int_fast32_t f64_to_i32_r_minMag( float64_t, bint ); + int_fast64_t f64_to_i64_r_minMag( float64_t, bint ); + float16_t f64_to_f16( float64_t ); + float32_t f64_to_f32( float64_t ); + # #ifdef SOFTFLOAT_FAST_INT64 + # extFloat80_t f64_to_extF80( float64_t ); + # float128_t f64_to_f128( float64_t ); + # #endif + # void f64_to_extF80M( float64_t, extFloat80_t * ); + # void f64_to_f128M( float64_t, float128_t * ); + float64_t f64_roundToInt( float64_t, uint_fast8_t, bint ); + float64_t f64_add( float64_t, float64_t ); + float64_t f64_sub( float64_t, float64_t ); + float64_t f64_mul( float64_t, float64_t ); + float64_t f64_mulAdd( float64_t, float64_t, float64_t ); + float64_t f64_div( float64_t, float64_t ); + float64_t f64_rem( float64_t, float64_t ); + float64_t f64_sqrt( float64_t ); + bint f64_eq( float64_t, float64_t ); + bint f64_le( float64_t, float64_t ); + bint f64_lt( float64_t, float64_t ); + bint f64_eq_signaling( float64_t, float64_t ); + bint f64_le_quiet( float64_t, float64_t ); + bint f64_lt_quiet( float64_t, float64_t ); + bint f64_isSignalingNaN( float64_t ); + + # /*---------------------------------------------------------------------------- + # | Rounding precision for 80-bit extended double-precision floating-point. + # | Valid values are 32, 64, and 80. + # *----------------------------------------------------------------------------*/ + # extern THREAD_LOCAL uint_fast8_t extF80_roundingPrecision; + + # /*---------------------------------------------------------------------------- + # | 80-bit extended double-precision floating-point operations. + # *----------------------------------------------------------------------------*/ + # #ifdef SOFTFLOAT_FAST_INT64 + # uint_fast32_t extF80_to_ui32( extFloat80_t, uint_fast8_t, bint ); + # uint_fast64_t extF80_to_ui64( extFloat80_t, uint_fast8_t, bint ); + # int_fast32_t extF80_to_i32( extFloat80_t, uint_fast8_t, bint ); + # int_fast64_t extF80_to_i64( extFloat80_t, uint_fast8_t, bint ); + # uint_fast32_t extF80_to_ui32_r_minMag( extFloat80_t, bint ); + # uint_fast64_t extF80_to_ui64_r_minMag( extFloat80_t, bint ); + # int_fast32_t extF80_to_i32_r_minMag( extFloat80_t, bint ); + # int_fast64_t extF80_to_i64_r_minMag( extFloat80_t, bint ); + # float16_t extF80_to_f16( extFloat80_t ); + # float32_t extF80_to_f32( extFloat80_t ); + # float64_t extF80_to_f64( extFloat80_t ); + # float128_t extF80_to_f128( extFloat80_t ); + # extFloat80_t extF80_roundToInt( extFloat80_t, uint_fast8_t, bint ); + # extFloat80_t extF80_add( extFloat80_t, extFloat80_t ); + # extFloat80_t extF80_sub( extFloat80_t, extFloat80_t ); + # extFloat80_t extF80_mul( extFloat80_t, extFloat80_t ); + # extFloat80_t extF80_div( extFloat80_t, extFloat80_t ); + # extFloat80_t extF80_rem( extFloat80_t, extFloat80_t ); + # extFloat80_t extF80_sqrt( extFloat80_t ); + # bint extF80_eq( extFloat80_t, extFloat80_t ); + # bint extF80_le( extFloat80_t, extFloat80_t ); + # bint extF80_lt( extFloat80_t, extFloat80_t ); + # bint extF80_eq_signaling( extFloat80_t, extFloat80_t ); + # bint extF80_le_quiet( extFloat80_t, extFloat80_t ); + # bint extF80_lt_quiet( extFloat80_t, extFloat80_t ); + # bint extF80_isSignalingNaN( extFloat80_t ); + # #endif + # uint_fast32_t extF80M_to_ui32( const extFloat80_t *, uint_fast8_t, bint ); + # uint_fast64_t extF80M_to_ui64( const extFloat80_t *, uint_fast8_t, bint ); + # int_fast32_t extF80M_to_i32( const extFloat80_t *, uint_fast8_t, bint ); + # int_fast64_t extF80M_to_i64( const extFloat80_t *, uint_fast8_t, bint ); + # uint_fast32_t extF80M_to_ui32_r_minMag( const extFloat80_t *, bint ); + # uint_fast64_t extF80M_to_ui64_r_minMag( const extFloat80_t *, bint ); + # int_fast32_t extF80M_to_i32_r_minMag( const extFloat80_t *, bint ); + # int_fast64_t extF80M_to_i64_r_minMag( const extFloat80_t *, bint ); + # float16_t extF80M_to_f16( const extFloat80_t * ); + # float32_t extF80M_to_f32( const extFloat80_t * ); + # float64_t extF80M_to_f64( const extFloat80_t * ); + # void extF80M_to_f128M( const extFloat80_t *, float128_t * ); + # void + # extF80M_roundToInt( + # const extFloat80_t *, uint_fast8_t, bint, extFloat80_t * ); + # void extF80M_add( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); + # void extF80M_sub( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); + # void extF80M_mul( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); + # void extF80M_div( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); + # void extF80M_rem( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); + # void extF80M_sqrt( const extFloat80_t *, extFloat80_t * ); + # bint extF80M_eq( const extFloat80_t *, const extFloat80_t * ); + # bint extF80M_le( const extFloat80_t *, const extFloat80_t * ); + # bint extF80M_lt( const extFloat80_t *, const extFloat80_t * ); + # bint extF80M_eq_signaling( const extFloat80_t *, const extFloat80_t * ); + # bint extF80M_le_quiet( const extFloat80_t *, const extFloat80_t * ); + # bint extF80M_lt_quiet( const extFloat80_t *, const extFloat80_t * ); + # bint extF80M_isSignalingNaN( const extFloat80_t * ); + + # /*---------------------------------------------------------------------------- + # | 128-bit (quadruple-precision) floating-point operations. + # *----------------------------------------------------------------------------*/ + # #ifdef SOFTFLOAT_FAST_INT64 + # uint_fast32_t f128_to_ui32( float128_t, uint_fast8_t, bint ); + # uint_fast64_t f128_to_ui64( float128_t, uint_fast8_t, bint ); + # int_fast32_t f128_to_i32( float128_t, uint_fast8_t, bint ); + # int_fast64_t f128_to_i64( float128_t, uint_fast8_t, bint ); + # uint_fast32_t f128_to_ui32_r_minMag( float128_t, bint ); + # uint_fast64_t f128_to_ui64_r_minMag( float128_t, bint ); + # int_fast32_t f128_to_i32_r_minMag( float128_t, bint ); + # int_fast64_t f128_to_i64_r_minMag( float128_t, bint ); + # float16_t f128_to_f16( float128_t ); + # float32_t f128_to_f32( float128_t ); + # float64_t f128_to_f64( float128_t ); + # extFloat80_t f128_to_extF80( float128_t ); + # float128_t f128_roundToInt( float128_t, uint_fast8_t, bint ); + # float128_t f128_add( float128_t, float128_t ); + # float128_t f128_sub( float128_t, float128_t ); + # float128_t f128_mul( float128_t, float128_t ); + # float128_t f128_mulAdd( float128_t, float128_t, float128_t ); + # float128_t f128_div( float128_t, float128_t ); + # float128_t f128_rem( float128_t, float128_t ); + # float128_t f128_sqrt( float128_t ); + # bint f128_eq( float128_t, float128_t ); + # bint f128_le( float128_t, float128_t ); + # bint f128_lt( float128_t, float128_t ); + # bint f128_eq_signaling( float128_t, float128_t ); + # bint f128_le_quiet( float128_t, float128_t ); + # bint f128_lt_quiet( float128_t, float128_t ); + # bint f128_isSignalingNaN( float128_t ); + # #endif + # uint_fast32_t f128M_to_ui32( const float128_t *, uint_fast8_t, bint ); + # uint_fast64_t f128M_to_ui64( const float128_t *, uint_fast8_t, bint ); + # int_fast32_t f128M_to_i32( const float128_t *, uint_fast8_t, bint ); + # int_fast64_t f128M_to_i64( const float128_t *, uint_fast8_t, bint ); + # uint_fast32_t f128M_to_ui32_r_minMag( const float128_t *, bint ); + # uint_fast64_t f128M_to_ui64_r_minMag( const float128_t *, bint ); + # int_fast32_t f128M_to_i32_r_minMag( const float128_t *, bint ); + # int_fast64_t f128M_to_i64_r_minMag( const float128_t *, bint ); + # float16_t f128M_to_f16( const float128_t * ); + # float32_t f128M_to_f32( const float128_t * ); + # float64_t f128M_to_f64( const float128_t * ); + # void f128M_to_extF80M( const float128_t *, extFloat80_t * ); + # void f128M_roundToInt( const float128_t *, uint_fast8_t, bint, float128_t * ); + # void f128M_add( const float128_t *, const float128_t *, float128_t * ); + # void f128M_sub( const float128_t *, const float128_t *, float128_t * ); + # void f128M_mul( const float128_t *, const float128_t *, float128_t * ); + # void + # f128M_mulAdd( + # const float128_t *, const float128_t *, const float128_t *, float128_t * + # ); + # void f128M_div( const float128_t *, const float128_t *, float128_t * ); + # void f128M_rem( const float128_t *, const float128_t *, float128_t * ); + # void f128M_sqrt( const float128_t *, float128_t * ); + # bint f128M_eq( const float128_t *, const float128_t * ); + # bint f128M_le( const float128_t *, const float128_t * ); + # bint f128M_lt( const float128_t *, const float128_t * ); + # bint f128M_eq_signaling( const float128_t *, const float128_t * ); + # bint f128M_le_quiet( const float128_t *, const float128_t * ); + # bint f128M_lt_quiet( const float128_t *, const float128_t * ); + # bint f128M_isSignalingNaN( const float128_t * ); diff --git a/sfpy/float.pyx b/sfpy/float.pyx new file mode 100644 index 0000000..261226c --- /dev/null +++ b/sfpy/float.pyx @@ -0,0 +1,951 @@ +from libc.stdint cimport * +cimport cfloat + + +# low-level access to rounding modes + +ROUND_NEAREST_EVEN = cfloat.softfloat_round_near_even +ROUND_TO_ZERO = cfloat.softfloat_round_minMag +ROUND_DOWN = cfloat.softfloat_round_min +ROUND_UP = cfloat.softfloat_round_max +ROUND_NEAREST_AWAY = cfloat.softfloat_round_near_maxMag + +cpdef uint_fast8_t round_get_mode(): + return cfloat.softfloat_roundingMode + +cpdef void round_set_mode(uint_fast8_t mode): + cfloat.softfloat_roundingMode = mode + +cpdef bint round_is_nearest_even(): + return cfloat.softfloat_roundingMode == cfloat.softfloat_round_near_even + +cpdef void round_set_nearest_even(): + cfloat.softfloat_roundingMode = cfloat.softfloat_round_near_even + +cpdef bint round_is_to_zero(): + return cfloat.softfloat_roundingMode == cfloat.softfloat_round_minMag + +cpdef void round_set_to_zero(): + cfloat.softfloat_roundingMode = cfloat.softfloat_round_minMag + +cpdef bint round_is_down(): + return cfloat.softfloat_roundingMode == cfloat.softfloat_round_min + +cpdef void round_set_down(): + cfloat.softfloat_roundingMode = cfloat.softfloat_round_min + +cpdef bint round_is_up(): + return cfloat.softfloat_roundingMode == cfloat.softfloat_round_max + +cpdef void round_set_up(): + cfloat.softfloat_roundingMode = cfloat.softfloat_round_max + +cpdef bint round_is_nearest_away(): + return cfloat.softfloat_roundingMode == cfloat.softfloat_round_near_maxMag + +cpdef void round_set_nearest_away(): + cfloat.softfloat_roundingMode = cfloat.softfloat_round_near_maxMag + + +# low-level access to exception flags + +FLAG_INEXACT = cfloat.softfloat_flag_inexact +FLAG_UNDERFLOW = cfloat.softfloat_flag_underflow +FLAG_OVERFLOW = cfloat.softfloat_flag_overflow +FLAG_INFINITE = cfloat.softfloat_flag_infinite +FLAG_INVALID = cfloat.softfloat_flag_invalid + +cpdef uint_fast8_t flag_get(): + return cfloat.softfloat_exceptionFlags + +cpdef void flag_set(uint_fast8_t flags): + cfloat.softfloat_exceptionFlags = flags + +cpdef void flag_reset(): + cfloat.softfloat_exceptionFlags = 0 + +cpdef bint flag_get_inexact(): + return (cfloat.softfloat_exceptionFlags & cfloat.softfloat_flag_inexact) != 0 + +cpdef void flag_raise_inexact(): + cfloat.softfloat_raiseFlags(cfloat.softfloat_flag_inexact) + +cpdef void flag_clear_inexact(): + cfloat.softfloat_exceptionFlags &= ~cfloat.softfloat_flag_inexact + +cpdef bint flag_get_underflow(): + return (cfloat.softfloat_exceptionFlags & cfloat.softfloat_flag_underflow) != 0 + +cpdef void flag_raise_underflow(): + cfloat.softfloat_raiseFlags(cfloat.softfloat_flag_underflow) + +cpdef void flag_clear_underflow(): + cfloat.softfloat_exceptionFlags &= ~cfloat.softfloat_flag_underflow + +cpdef bint flag_get_overflow(): + return (cfloat.softfloat_exceptionFlags & cfloat.softfloat_flag_overflow) != 0 + +cpdef void flag_raise_overflow(): + cfloat.softfloat_raiseFlags(cfloat.softfloat_flag_overflow) + +cpdef void flag_clear_overflow(): + cfloat.softfloat_exceptionFlags &= ~cfloat.softfloat_flag_overflow + +cpdef bint flag_get_infinite(): + return (cfloat.softfloat_exceptionFlags & cfloat.softfloat_flag_infinite) != 0 + +cpdef void flag_raise_infinite(): + cfloat.softfloat_raiseFlags(cfloat.softfloat_flag_infinite) + +cpdef void flag_clear_infinite(): + cfloat.softfloat_exceptionFlags &= ~cfloat.softfloat_flag_infinite + +cpdef bint flag_get_invalid(): + return (cfloat.softfloat_exceptionFlags & cfloat.softfloat_flag_invalid) != 0 + +cpdef void flag_raise_invalid(): + cfloat.softfloat_raiseFlags(cfloat.softfloat_flag_invalid) + +cpdef void flag_clear_invalid(): + cfloat.softfloat_exceptionFlags &= ~cfloat.softfloat_flag_invalid + + +cdef class Float16: + + # the wrapped float value + cdef cfloat.float16_t _c_float + + # factory function constructors that bypass __init__ + + @staticmethod + cdef Float16 from_c_float(cfloat.float16_t f): + """Factory function to create a Float16 object directly from + a C float16_t. + """ + cdef Float16 obj = Float16.__new__(Float16) + obj._c_float = f + return obj + + @staticmethod + def from_bits(uint16_t value): + """Factory function to create a Float16 object from a bit pattern + represented as an integer. + """ + cdef Float16 obj = Float16.__new__(Float16) + obj._c_float.v = value + return obj + + @staticmethod + def from_double(double value): + """Factory function to create a Float16 object from a double. + """ + cdef Float16 obj = Float16.__new__(Float16) + cdef cfloat.ui64_double ud + cdef cfloat.float64_t d + + ud.d = value + d.v = ud.u + obj._c_float = cfloat.f64_to_f16(d) + + return obj + + # convenience interface for use inside Python + + def __init__(self, value): + cdef cfloat.ui64_double ud + cdef cfloat.float64_t d + + if isinstance(value, int): + self._c_float.v = value + else: + ud.d = float(value) + d.v = ud.u + self._c_float = cfloat.f64_to_f16(d) + + def __float__(self): + cdef cfloat.ui64_double ud + ud.u = cfloat.f16_to_f64(self._c_float).v + return ud.d + + def __int__(self): + cdef cfloat.ui64_double ud + ud.u = cfloat.f16_to_f64(self._c_float).v + return int(ud.d) + + def __str__(self): + cdef cfloat.ui64_double ud + ud.u = cfloat.f16_to_f64(self._c_float).v + return repr(ud.d) + + def __repr__(self): + cdef cfloat.ui64_double ud + ud.u = cfloat.f16_to_f64(self._c_float).v + return 'Float16(' + repr(ud.d) + ')' + + cpdef uint16_t get_bits(self): + return self._c_float.v + bits = property(get_bits) + + # arithmetic + + cpdef Float16 round_to(self, uint_fast8_t rm, bint exact): + cdef cfloat.float16_t f = cfloat.f16_roundToInt(self._c_float, rm, exact) + return Float16.from_c_float(f) + + cpdef Float16 round(self): + cdef cfloat.float16_t f = cfloat.f16_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True) + return Float16.from_c_float(f) + + def __round__(self): + return self.round() + + cpdef Float16 add(self, Float16 other): + cdef cfloat.float16_t f = cfloat.f16_add(self._c_float, other._c_float) + return Float16.from_c_float(f) + + def __add__(self, Float16 other): + return self.add(other) + + cpdef Float16 sub(self, Float16 other): + cdef cfloat.float16_t f = cfloat.f16_sub(self._c_float, other._c_float) + return Float16.from_c_float(f) + + def __sub__(self, Float16 other): + return self.sub(other) + + cpdef Float16 mul(self, Float16 other): + cdef cfloat.float16_t f = cfloat.f16_mul(self._c_float, other._c_float) + return Float16.from_c_float(f) + + def __mul__(self, Float16 other): + return self.mul(other) + + cpdef Float16 fma(self, Float16 a2, Float16 a3): + cdef cfloat.float16_t f = cfloat.f16_mulAdd(self._c_float, a2._c_float, a3._c_float) + return Float16.from_c_float(f) + + cpdef Float16 qma(self, Float16 a1, Float16 a2): + cdef cfloat.float16_t f = cfloat.f16_mulAdd(a1._c_float, a2._c_float, self._c_float) + return Float16.from_c_float(f) + + cpdef Float16 div(self, Float16 other): + cdef cfloat.float16_t f = cfloat.f16_div(self._c_float, other._c_float) + return Float16.from_c_float(f) + + def __truediv__(self, Float16 other): + return self.div(other) + + cpdef Float16 rem(self, Float16 other): + cdef cfloat.float16_t f = cfloat.f16_rem(self._c_float, other._c_float) + return Float16.from_c_float(f) + + cpdef Float16 sqrt(self): + cdef cfloat.float16_t f = cfloat.f16_sqrt(self._c_float) + return Float16.from_c_float(f) + + # in-place arithmetic + + cpdef void iround_to(self, uint_fast8_t rm, bint exact): + self._c_float = cfloat.f16_roundToInt(self._c_float, rm, exact) + + cpdef void iround(self): + self._c_float = cfloat.f16_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True) + + cpdef void iadd(self, Float16 other): + self._c_float = cfloat.f16_add(self._c_float, other._c_float) + + def __iadd__(self, Float16 other): + self.iadd(other) + return self + + cpdef void isub(self, Float16 other): + self._c_float = cfloat.f16_sub(self._c_float, other._c_float) + + def __isub__(self, Float16 other): + self.isub(other) + return self + + cpdef void imul(self, Float16 other): + self._c_float = cfloat.f16_mul(self._c_float, other._c_float) + + def __imul__(self, Float16 other): + self.imul(other) + return self + + cpdef void ifma(self, Float16 a2, Float16 a3): + self._c_float = cfloat.f16_mulAdd(self._c_float, a2._c_float, a3._c_float) + + cpdef void iqma(self, Float16 a1, Float16 a2): + self._c_float = cfloat.f16_mulAdd(a1._c_float, a2._c_float, self._c_float) + + cpdef void idiv(self, Float16 other): + self._c_float = cfloat.f16_div(self._c_float, other._c_float) + + def __itruediv__(self, Float16 other): + self.idiv(other) + return self + + cpdef void irem(self, Float16 other): + self._c_float = cfloat.f16_rem(self._c_float, other._c_float) + + cpdef void isqrt(self): + self._c_float = cfloat.f16_sqrt(self._c_float) + + # comparison + + cpdef bint eq(self, Float16 other): + return cfloat.f16_eq(self._c_float, other._c_float) + + cpdef bint le(self, Float16 other): + return cfloat.f16_le(self._c_float, other._c_float) + + cpdef bint lt(self, Float16 other): + return cfloat.f16_lt(self._c_float, other._c_float) + + def __lt__(self, Float16 other): + return self.lt(other) + + def __le__(self, Float16 other): + return self.le(other) + + def __eq__(self, Float16 other): + return self.eq(other) + + def __ne__(self, Float16 other): + return not self.eq(other) + + def __ge__(self, Float16 other): + return other.le(self) + + def __gt__(self, Float16 other): + return other.lt(self) + + # conversion to other float types + + cpdef Float32 to_f32(self): + cdef cfloat.float32_t f = cfloat.f16_to_f32(self._c_float) + return Float32.from_c_float(f) + + cpdef Float64 to_f64(self): + cdef cfloat.float64_t f = cfloat.f16_to_f64(self._c_float) + return Float64.from_c_float(f) + + +# external, non-method arithmetic + +cpdef Float16 f16_round_to(Float16 a1, uint_fast8_t rm, bint exact): + cdef cfloat.float16_t f = cfloat.f16_roundToInt(a1._c_float, rm, exact) + return Float16.from_c_float(f) + +cpdef Float16 f16_round(Float16 a1): + cdef cfloat.float16_t f = cfloat.f16_roundToInt(a1._c_float, cfloat.softfloat_roundingMode, True) + return Float16.from_c_float(f) + +cpdef Float16 f16_add(Float16 a1, Float16 a2): + cdef cfloat.float16_t f = cfloat.f16_add(a1._c_float, a2._c_float) + return Float16.from_c_float(f) + +cpdef Float16 f16_sub(Float16 a1, Float16 a2): + cdef cfloat.float16_t f = cfloat.f16_sub(a1._c_float, a2._c_float) + return Float16.from_c_float(f) + +cpdef Float16 f16_mul(Float16 a1, Float16 a2): + cdef cfloat.float16_t f = cfloat.f16_mul(a1._c_float, a2._c_float) + return Float16.from_c_float(f) + +cpdef Float16 f16_fma(Float16 a1, Float16 a2, Float16 a3): + cdef cfloat.float16_t f = cfloat.f16_mulAdd(a1._c_float, a2._c_float, a3._c_float) + return Float16.from_c_float(f) + +cpdef Float16 f16_qma(Float16 a3, Float16 a1, Float16 a2): + cdef cfloat.float16_t f = cfloat.f16_mulAdd(a1._c_float, a2._c_float, a3._c_float) + return Float16.from_c_float(f) + +cpdef Float16 f16_div(Float16 a1, Float16 a2): + cdef cfloat.float16_t f = cfloat.f16_div(a1._c_float, a2._c_float) + return Float16.from_c_float(f) + +cpdef Float16 f16_rem(Float16 a1, Float16 a2): + cdef cfloat.float16_t f = cfloat.f16_rem(a1._c_float, a2._c_float) + return Float16.from_c_float(f) + +cpdef Float16 f16_sqrt(Float16 a1): + cdef cfloat.float16_t f = cfloat.f16_sqrt(a1._c_float) + return Float16.from_c_float(f) + +cpdef bint f16_eq(Float16 a1, Float16 a2): + return cfloat.f16_eq(a1._c_float, a2._c_float) + +cpdef bint f16_le(Float16 a1, Float16 a2): + return cfloat.f16_le(a1._c_float, a2._c_float) + +cpdef bint f16_lt(Float16 a1, Float16 a2): + return cfloat.f16_lt(a1._c_float, a2._c_float) + +cpdef Float32 f16_to_f32(Float16 a1): + cdef cfloat.float32_t f = cfloat.f16_to_f32(a1._c_float) + return Float32.from_c_float(f) + +cpdef Float64 f16_to_f64(Float16 a1): + cdef cfloat.float64_t f = cfloat.f16_to_f64(a1._c_float) + return Float64.from_c_float(f) + + +cdef class Float32: + + # the wrapped float value + cdef cfloat.float32_t _c_float + + # factory function constructors that bypass __init__ + + @staticmethod + cdef Float32 from_c_float(cfloat.float32_t f): + """Factory function to create a Float32 object directly from + a C float32_t. + """ + cdef Float32 obj = Float32.__new__(Float32) + obj._c_float = f + return obj + + @staticmethod + def from_bits(uint32_t value): + """Factory function to create a Float32 object from a bit pattern + represented as an integer. + """ + cdef Float32 obj = Float32.__new__(Float32) + obj._c_float.v = value + return obj + + @staticmethod + def from_double(double value): + """Factory function to create a Float32 object from a double. + """ + cdef Float32 obj = Float32.__new__(Float32) + cdef cfloat.ui64_double ud + cdef cfloat.float64_t d + + ud.d = value + d.v = ud.u + obj._c_float = cfloat.f64_to_f32(d) + + return obj + + # convenience interface for use inside Python + + def __init__(self, value): + cdef cfloat.ui64_double ud + cdef cfloat.float64_t d + + if isinstance(value, int): + self._c_float.v = value + else: + ud.d = float(value) + d.v = ud.u + self._c_float = cfloat.f64_to_f32(d) + + def __float__(self): + cdef cfloat.ui64_double ud + ud.u = cfloat.f32_to_f64(self._c_float).v + return ud.d + + def __int__(self): + cdef cfloat.ui64_double ud + ud.u = cfloat.f32_to_f64(self._c_float).v + return int(ud.d) + + def __str__(self): + cdef cfloat.ui64_double ud + ud.u = cfloat.f32_to_f64(self._c_float).v + return repr(ud.d) + + def __repr__(self): + cdef cfloat.ui64_double ud + ud.u = cfloat.f32_to_f64(self._c_float).v + return 'Float32(' + repr(ud.d) + ')' + + cpdef uint32_t get_bits(self): + return self._c_float.v + bits = property(get_bits) + + # arithmetic + + cpdef Float32 round_to(self, uint_fast8_t rm, bint exact): + cdef cfloat.float32_t f = cfloat.f32_roundToInt(self._c_float, rm, exact) + return Float32.from_c_float(f) + + cpdef Float32 round(self): + cdef cfloat.float32_t f = cfloat.f32_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True) + return Float32.from_c_float(f) + + def __round__(self): + return self.round() + + cpdef Float32 add(self, Float32 other): + cdef cfloat.float32_t f = cfloat.f32_add(self._c_float, other._c_float) + return Float32.from_c_float(f) + + def __add__(self, Float32 other): + return self.add(other) + + cpdef Float32 sub(self, Float32 other): + cdef cfloat.float32_t f = cfloat.f32_sub(self._c_float, other._c_float) + return Float32.from_c_float(f) + + def __sub__(self, Float32 other): + return self.sub(other) + + cpdef Float32 mul(self, Float32 other): + cdef cfloat.float32_t f = cfloat.f32_mul(self._c_float, other._c_float) + return Float32.from_c_float(f) + + def __mul__(self, Float32 other): + return self.mul(other) + + cpdef Float32 fma(self, Float32 a2, Float32 a3): + cdef cfloat.float32_t f = cfloat.f32_mulAdd(self._c_float, a2._c_float, a3._c_float) + return Float32.from_c_float(f) + + cpdef Float32 qma(self, Float32 a1, Float32 a2): + cdef cfloat.float32_t f = cfloat.f32_mulAdd(a1._c_float, a2._c_float, self._c_float) + return Float32.from_c_float(f) + + cpdef Float32 div(self, Float32 other): + cdef cfloat.float32_t f = cfloat.f32_div(self._c_float, other._c_float) + return Float32.from_c_float(f) + + def __truediv__(self, Float32 other): + return self.div(other) + + cpdef Float32 rem(self, Float32 other): + cdef cfloat.float32_t f = cfloat.f32_rem(self._c_float, other._c_float) + return Float32.from_c_float(f) + + cpdef Float32 sqrt(self): + cdef cfloat.float32_t f = cfloat.f32_sqrt(self._c_float) + return Float32.from_c_float(f) + + # in-place arithmetic + + cpdef void iround_to(self, uint_fast8_t rm, bint exact): + self._c_float = cfloat.f32_roundToInt(self._c_float, rm, exact) + + cpdef void iround(self): + self._c_float = cfloat.f32_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True) + + cpdef void iadd(self, Float32 other): + self._c_float = cfloat.f32_add(self._c_float, other._c_float) + + def __iadd__(self, Float32 other): + self.iadd(other) + return self + + cpdef void isub(self, Float32 other): + self._c_float = cfloat.f32_sub(self._c_float, other._c_float) + + def __isub__(self, Float32 other): + self.isub(other) + return self + + cpdef void imul(self, Float32 other): + self._c_float = cfloat.f32_mul(self._c_float, other._c_float) + + def __imul__(self, Float32 other): + self.imul(other) + return self + + cpdef void ifma(self, Float32 a2, Float32 a3): + self._c_float = cfloat.f32_mulAdd(self._c_float, a2._c_float, a3._c_float) + + cpdef void iqma(self, Float32 a1, Float32 a2): + self._c_float = cfloat.f32_mulAdd(a1._c_float, a2._c_float, self._c_float) + + cpdef void idiv(self, Float32 other): + self._c_float = cfloat.f32_div(self._c_float, other._c_float) + + def __itruediv__(self, Float32 other): + self.idiv(other) + return self + + cpdef void irem(self, Float32 other): + self._c_float = cfloat.f32_rem(self._c_float, other._c_float) + + cpdef void isqrt(self): + self._c_float = cfloat.f32_sqrt(self._c_float) + + # comparison + + cpdef bint eq(self, Float32 other): + return cfloat.f32_eq(self._c_float, other._c_float) + + cpdef bint le(self, Float32 other): + return cfloat.f32_le(self._c_float, other._c_float) + + cpdef bint lt(self, Float32 other): + return cfloat.f32_lt(self._c_float, other._c_float) + + def __lt__(self, Float32 other): + return self.lt(other) + + def __le__(self, Float32 other): + return self.le(other) + + def __eq__(self, Float32 other): + return self.eq(other) + + def __ne__(self, Float32 other): + return not self.eq(other) + + def __ge__(self, Float32 other): + return other.le(self) + + def __gt__(self, Float32 other): + return other.lt(self) + + # conversion to other float types + + cpdef Float16 to_f16(self): + cdef cfloat.float16_t f = cfloat.f32_to_f16(self._c_float) + return Float16.from_c_float(f) + + cpdef Float64 to_f64(self): + cdef cfloat.float64_t f = cfloat.f32_to_f64(self._c_float) + return Float64.from_c_float(f) + + +# external, non-method arithmetic + +cpdef Float32 f32_round_to(Float32 a1, uint_fast8_t rm, bint exact): + cdef cfloat.float32_t f = cfloat.f32_roundToInt(a1._c_float, rm, exact) + return Float32.from_c_float(f) + +cpdef Float32 f32_round(Float32 a1): + cdef cfloat.float32_t f = cfloat.f32_roundToInt(a1._c_float, cfloat.softfloat_roundingMode, True) + return Float32.from_c_float(f) + +cpdef Float32 f32_add(Float32 a1, Float32 a2): + cdef cfloat.float32_t f = cfloat.f32_add(a1._c_float, a2._c_float) + return Float32.from_c_float(f) + +cpdef Float32 f32_sub(Float32 a1, Float32 a2): + cdef cfloat.float32_t f = cfloat.f32_sub(a1._c_float, a2._c_float) + return Float32.from_c_float(f) + +cpdef Float32 f32_mul(Float32 a1, Float32 a2): + cdef cfloat.float32_t f = cfloat.f32_mul(a1._c_float, a2._c_float) + return Float32.from_c_float(f) + +cpdef Float32 f32_fma(Float32 a1, Float32 a2, Float32 a3): + cdef cfloat.float32_t f = cfloat.f32_mulAdd(a1._c_float, a2._c_float, a3._c_float) + return Float32.from_c_float(f) + +cpdef Float32 f32_qma(Float32 a3, Float32 a1, Float32 a2): + cdef cfloat.float32_t f = cfloat.f32_mulAdd(a1._c_float, a2._c_float, a3._c_float) + return Float32.from_c_float(f) + +cpdef Float32 f32_div(Float32 a1, Float32 a2): + cdef cfloat.float32_t f = cfloat.f32_div(a1._c_float, a2._c_float) + return Float32.from_c_float(f) + +cpdef Float32 f32_rem(Float32 a1, Float32 a2): + cdef cfloat.float32_t f = cfloat.f32_rem(a1._c_float, a2._c_float) + return Float32.from_c_float(f) + +cpdef Float32 f32_sqrt(Float32 a1): + cdef cfloat.float32_t f = cfloat.f32_sqrt(a1._c_float) + return Float32.from_c_float(f) + +cpdef bint f32_eq(Float32 a1, Float32 a2): + return cfloat.f32_eq(a1._c_float, a2._c_float) + +cpdef bint f32_le(Float32 a1, Float32 a2): + return cfloat.f32_le(a1._c_float, a2._c_float) + +cpdef bint f32_lt(Float32 a1, Float32 a2): + return cfloat.f32_lt(a1._c_float, a2._c_float) + +cpdef Float16 f32_to_f16(Float32 a1): + cdef cfloat.float16_t f = cfloat.f32_to_f16(a1._c_float) + return Float16.from_c_float(f) + +cpdef Float64 f32_to_f64(Float32 a1): + cdef cfloat.float64_t f = cfloat.f32_to_f64(a1._c_float) + return Float64.from_c_float(f) + + +cdef class Float64: + + # the wrapped float value + cdef cfloat.float64_t _c_float + + # factory function constructors that bypass __init__ + + @staticmethod + cdef Float64 from_c_float(cfloat.float64_t f): + """Factory function to create a Float64 object directly from + a C float64_t. + """ + cdef Float64 obj = Float64.__new__(Float64) + obj._c_float = f + return obj + + @staticmethod + def from_bits(uint64_t value): + """Factory function to create a Float64 object from a bit pattern + represented as an integer. + """ + cdef Float64 obj = Float64.__new__(Float64) + obj._c_float.v = value + return obj + + @staticmethod + def from_double(double value): + """Factory function to create a Float64 object from a double. + """ + cdef Float64 obj = Float64.__new__(Float64) + cdef cfloat.ui64_double ud + cdef cfloat.float64_t d + + ud.d = value + obj._c_float.v = ud.u + + return obj + + # convenience interface for use inside Python + + def __init__(self, value): + cdef cfloat.ui64_double ud + cdef cfloat.float64_t d + + if isinstance(value, int): + self._c_float.v = value + else: + ud.d = float(value) + self._c_float.v = ud.u + + def __float__(self): + cdef cfloat.ui64_double ud + ud.u = self._c_float.v + return ud.d + + def __int__(self): + cdef cfloat.ui64_double ud + ud.u = self._c_float.v + return int(ud.d) + + def __str__(self): + cdef cfloat.ui64_double ud + ud.u = self._c_float.v + return repr(ud.d) + + def __repr__(self): + cdef cfloat.ui64_double ud + ud.u = self._c_float.v + return 'Float64(' + repr(ud.d) + ')' + + cpdef uint64_t get_bits(self): + return self._c_float.v + bits = property(get_bits) + + # arithmetic + + cpdef Float64 round_to(self, uint_fast8_t rm, bint exact): + cdef cfloat.float64_t f = cfloat.f64_roundToInt(self._c_float, rm, exact) + return Float64.from_c_float(f) + + cpdef Float64 round(self): + cdef cfloat.float64_t f = cfloat.f64_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True) + return Float64.from_c_float(f) + + def __round__(self): + return self.round() + + cpdef Float64 add(self, Float64 other): + cdef cfloat.float64_t f = cfloat.f64_add(self._c_float, other._c_float) + return Float64.from_c_float(f) + + def __add__(self, Float64 other): + return self.add(other) + + cpdef Float64 sub(self, Float64 other): + cdef cfloat.float64_t f = cfloat.f64_sub(self._c_float, other._c_float) + return Float64.from_c_float(f) + + def __sub__(self, Float64 other): + return self.sub(other) + + cpdef Float64 mul(self, Float64 other): + cdef cfloat.float64_t f = cfloat.f64_mul(self._c_float, other._c_float) + return Float64.from_c_float(f) + + def __mul__(self, Float64 other): + return self.mul(other) + + cpdef Float64 fma(self, Float64 a2, Float64 a3): + cdef cfloat.float64_t f = cfloat.f64_mulAdd(self._c_float, a2._c_float, a3._c_float) + return Float64.from_c_float(f) + + cpdef Float64 qma(self, Float64 a1, Float64 a2): + cdef cfloat.float64_t f = cfloat.f64_mulAdd(a1._c_float, a2._c_float, self._c_float) + return Float64.from_c_float(f) + + cpdef Float64 div(self, Float64 other): + cdef cfloat.float64_t f = cfloat.f64_div(self._c_float, other._c_float) + return Float64.from_c_float(f) + + def __truediv__(self, Float64 other): + return self.div(other) + + cpdef Float64 rem(self, Float64 other): + cdef cfloat.float64_t f = cfloat.f64_rem(self._c_float, other._c_float) + return Float64.from_c_float(f) + + cpdef Float64 sqrt(self): + cdef cfloat.float64_t f = cfloat.f64_sqrt(self._c_float) + return Float64.from_c_float(f) + + # in-place arithmetic + + cpdef void iround_to(self, uint_fast8_t rm, bint exact): + self._c_float = cfloat.f64_roundToInt(self._c_float, rm, exact) + + cpdef void iround(self): + self._c_float = cfloat.f64_roundToInt(self._c_float, cfloat.softfloat_roundingMode, True) + + cpdef void iadd(self, Float64 other): + self._c_float = cfloat.f64_add(self._c_float, other._c_float) + + def __iadd__(self, Float64 other): + self.iadd(other) + return self + + cpdef void isub(self, Float64 other): + self._c_float = cfloat.f64_sub(self._c_float, other._c_float) + + def __isub__(self, Float64 other): + self.isub(other) + return self + + cpdef void imul(self, Float64 other): + self._c_float = cfloat.f64_mul(self._c_float, other._c_float) + + def __imul__(self, Float64 other): + self.imul(other) + return self + + cpdef void ifma(self, Float64 a2, Float64 a3): + self._c_float = cfloat.f64_mulAdd(self._c_float, a2._c_float, a3._c_float) + + cpdef void iqma(self, Float64 a1, Float64 a2): + self._c_float = cfloat.f64_mulAdd(a1._c_float, a2._c_float, self._c_float) + + cpdef void idiv(self, Float64 other): + self._c_float = cfloat.f64_div(self._c_float, other._c_float) + + def __itruediv__(self, Float64 other): + self.idiv(other) + return self + + cpdef void irem(self, Float64 other): + self._c_float = cfloat.f64_rem(self._c_float, other._c_float) + + cpdef void isqrt(self): + self._c_float = cfloat.f64_sqrt(self._c_float) + + # comparison + + cpdef bint eq(self, Float64 other): + return cfloat.f64_eq(self._c_float, other._c_float) + + cpdef bint le(self, Float64 other): + return cfloat.f64_le(self._c_float, other._c_float) + + cpdef bint lt(self, Float64 other): + return cfloat.f64_lt(self._c_float, other._c_float) + + def __lt__(self, Float64 other): + return self.lt(other) + + def __le__(self, Float64 other): + return self.le(other) + + def __eq__(self, Float64 other): + return self.eq(other) + + def __ne__(self, Float64 other): + return not self.eq(other) + + def __ge__(self, Float64 other): + return other.le(self) + + def __gt__(self, Float64 other): + return other.lt(self) + + # conversion to other float types + + cpdef Float16 to_f16(self): + cdef cfloat.float16_t f = cfloat.f64_to_f16(self._c_float) + return Float16.from_c_float(f) + + cpdef Float32 to_f32(self): + cdef cfloat.float32_t f = cfloat.f64_to_f32(self._c_float) + return Float32.from_c_float(f) + + +# external, non-method arithmetic + +cpdef Float64 f64_round_to(Float64 a1, uint_fast8_t rm, bint exact): + cdef cfloat.float64_t f = cfloat.f64_roundToInt(a1._c_float, rm, exact) + return Float64.from_c_float(f) + +cpdef Float64 f64_round(Float64 a1): + cdef cfloat.float64_t f = cfloat.f64_roundToInt(a1._c_float, cfloat.softfloat_roundingMode, True) + return Float64.from_c_float(f) + +cpdef Float64 f64_add(Float64 a1, Float64 a2): + cdef cfloat.float64_t f = cfloat.f64_add(a1._c_float, a2._c_float) + return Float64.from_c_float(f) + +cpdef Float64 f64_sub(Float64 a1, Float64 a2): + cdef cfloat.float64_t f = cfloat.f64_sub(a1._c_float, a2._c_float) + return Float64.from_c_float(f) + +cpdef Float64 f64_mul(Float64 a1, Float64 a2): + cdef cfloat.float64_t f = cfloat.f64_mul(a1._c_float, a2._c_float) + return Float64.from_c_float(f) + +cpdef Float64 f64_fma(Float64 a1, Float64 a2, Float64 a3): + cdef cfloat.float64_t f = cfloat.f64_mulAdd(a1._c_float, a2._c_float, a3._c_float) + return Float64.from_c_float(f) + +cpdef Float64 f64_qma(Float64 a3, Float64 a1, Float64 a2): + cdef cfloat.float64_t f = cfloat.f64_mulAdd(a1._c_float, a2._c_float, a3._c_float) + return Float64.from_c_float(f) + +cpdef Float64 f64_div(Float64 a1, Float64 a2): + cdef cfloat.float64_t f = cfloat.f64_div(a1._c_float, a2._c_float) + return Float64.from_c_float(f) + +cpdef Float64 f64_rem(Float64 a1, Float64 a2): + cdef cfloat.float64_t f = cfloat.f64_rem(a1._c_float, a2._c_float) + return Float64.from_c_float(f) + +cpdef Float64 f64_sqrt(Float64 a1): + cdef cfloat.float64_t f = cfloat.f64_sqrt(a1._c_float) + return Float64.from_c_float(f) + +cpdef bint f64_eq(Float64 a1, Float64 a2): + return cfloat.f64_eq(a1._c_float, a2._c_float) + +cpdef bint f64_le(Float64 a1, Float64 a2): + return cfloat.f64_le(a1._c_float, a2._c_float) + +cpdef bint f64_lt(Float64 a1, Float64 a2): + return cfloat.f64_lt(a1._c_float, a2._c_float) + +cpdef Float16 f64_to_f16(Float64 a1): + cdef cfloat.float16_t f = cfloat.f64_to_f16(a1._c_float) + return Float16.from_c_float(f) + +cpdef Float32 f64_to_f32(Float64 a1): + cdef cfloat.float32_t f = cfloat.f64_to_f32(a1._c_float) + return Float32.from_c_float(f) -- 2.30.2