X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=sfpy%2Ffloat.pyx;h=d1e7134b2e18563e07fcc6e5b88a5f0aef1150db;hb=HEAD;hp=261226c55366c8ec98e99c750b358c4e85d09391;hpb=03cecad0b5793eb349e5d9f07524583df5ba09b6;p=sfpy.git diff --git a/sfpy/float.pyx b/sfpy/float.pyx index 261226c..d1e7134 100644 --- a/sfpy/float.pyx +++ b/sfpy/float.pyx @@ -110,6 +110,33 @@ cpdef void flag_clear_invalid(): cfloat.softfloat_exceptionFlags &= ~cfloat.softfloat_flag_invalid +# C helpers + +cdef inline cfloat.float16_t _f16_neg(cfloat.float16_t f): + f.v ^= 0x8000 + return f + +cdef inline cfloat.float32_t _f32_neg(cfloat.float32_t f): + f.v ^= 0x80000000 + return f + +cdef inline cfloat.float64_t _f64_neg(cfloat.float64_t f): + f.v ^= 0x8000000000000000 + return f + +cdef inline cfloat.float16_t _f16_abs(cfloat.float16_t f): + f.v &= 0x7fff + return f + +cdef inline cfloat.float32_t _f32_abs(cfloat.float32_t f): + f.v &= 0x7fffffff + return f + +cdef inline cfloat.float64_t _f64_abs(cfloat.float64_t f): + f.v &= 0x7fffffffffffffff + return f + + cdef class Float16: # the wrapped float value @@ -152,6 +179,10 @@ cdef class Float16: # convenience interface for use inside Python def __init__(self, value): + """Given an int, create a Float16 from the bitpattern represented by + that int. Otherwise, given some value, create a Float16 by rounding + float(value). + """ cdef cfloat.ui64_double ud cdef cfloat.float64_t d @@ -188,6 +219,20 @@ cdef class Float16: # arithmetic + cpdef Float16 neg(self): + cdef cfloat.float16_t f = _f16_neg(self._c_float) + return Float16.from_c_float(f) + + def __neg__(self): + return self.neg() + + cpdef Float16 abs(self): + cdef cfloat.float16_t f = _f16_abs(self._c_float) + return Float16.from_c_float(f) + + def __abs__(self): + return self.abs() + 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) @@ -220,11 +265,7 @@ cdef class Float16: 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): + cpdef Float16 fma(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) @@ -245,6 +286,12 @@ cdef class Float16: # in-place arithmetic + cpdef void ineg(self): + self._c_float = _f16_neg(self._c_float) + + cpdef void iabs(self): + self._c_float = _f16_abs(self._c_float) + cpdef void iround_to(self, uint_fast8_t rm, bint exact): self._c_float = cfloat.f16_roundToInt(self._c_float, rm, exact) @@ -272,10 +319,7 @@ cdef class Float16: 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): + cpdef void ifma(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): @@ -333,6 +377,14 @@ cdef class Float16: # external, non-method arithmetic +cpdef Float16 f16_neg(Float16 a1): + cdef cfloat.float16_t f = _f16_neg(a1._c_float) + return Float16.from_c_float(f) + +cpdef Float16 f16_abs(Float16 a1): + cdef cfloat.float16_t f = _f16_abs(a1._c_float) + return Float16.from_c_float(f) + 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) @@ -353,12 +405,8 @@ 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) +cpdef Float16 f16_fma(Float16 acc, Float16 a1, Float16 a2): + cdef cfloat.float16_t f = cfloat.f16_mulAdd(a1._c_float, a2._c_float, acc._c_float) return Float16.from_c_float(f) cpdef Float16 f16_div(Float16 a1, Float16 a2): @@ -433,6 +481,10 @@ cdef class Float32: # convenience interface for use inside Python def __init__(self, value): + """Given an int, create a Float32 from the bitpattern represented by + that int. Otherwise, given some value, create a Float32 by rounding + float(value). + """ cdef cfloat.ui64_double ud cdef cfloat.float64_t d @@ -469,6 +521,20 @@ cdef class Float32: # arithmetic + cpdef Float32 neg(self): + cdef cfloat.float32_t f = _f32_neg(self._c_float) + return Float32.from_c_float(f) + + def __neg__(self): + return self.neg() + + cpdef Float32 abs(self): + cdef cfloat.float32_t f = _f32_abs(self._c_float) + return Float32.from_c_float(f) + + def __abs__(self): + return self.abs() + 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) @@ -501,11 +567,7 @@ cdef class Float32: 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): + cpdef Float32 fma(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) @@ -526,6 +588,12 @@ cdef class Float32: # in-place arithmetic + cpdef void ineg(self): + self._c_float = _f32_neg(self._c_float) + + cpdef void iabs(self): + self._c_float = _f32_abs(self._c_float) + cpdef void iround_to(self, uint_fast8_t rm, bint exact): self._c_float = cfloat.f32_roundToInt(self._c_float, rm, exact) @@ -553,10 +621,7 @@ cdef class Float32: 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): + cpdef void ifma(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): @@ -611,9 +676,140 @@ cdef class Float32: cdef cfloat.float64_t f = cfloat.f32_to_f64(self._c_float) return Float64.from_c_float(f) +######## +# integer conversions +######## + +# u/i32 <-> f16 + +cpdef Float16 i32_to_f16(int32_t value): + cdef cfloat.float16_t f = cfloat.i32_to_f16(value) + return Float16.from_c_float(f) + +cpdef Float16 ui32_to_f16(uint32_t value): + cdef cfloat.float16_t f = cfloat.ui32_to_f16(value) + return Float16.from_c_float(f) + +cpdef uint32_t f16_to_ui32(Float16 a1): + cdef uint32_t i = cfloat.f16_to_ui32(a1._c_float, + cfloat.softfloat_roundingMode, True) + return i + +cpdef int32_t f16_to_i32(Float16 a1): + cdef int32_t i = cfloat.f16_to_i32(a1._c_float, + cfloat.softfloat_roundingMode, True) + return i + +# u/i32 <-> f32 + +cpdef Float32 i32_to_f32(int32_t value): + cdef cfloat.float32_t f = cfloat.i32_to_f32(value) + return Float32.from_c_float(f) + +cpdef Float32 ui32_to_f32(uint32_t value): + cdef cfloat.float32_t f = cfloat.ui32_to_f32(value) + return Float32.from_c_float(f) + +cpdef uint32_t f32_to_ui32(Float32 a1): + cdef uint32_t i = cfloat.f32_to_ui32(a1._c_float, + cfloat.softfloat_roundingMode, True) + return i + +cpdef int32_t f32_to_i32(Float32 a1): + cdef int32_t i = cfloat.f32_to_i32(a1._c_float, + cfloat.softfloat_roundingMode, True) + return i + +# u/i32 <-> f64 + +cpdef Float64 i32_to_f64(int32_t value): + cdef cfloat.float64_t f = cfloat.i32_to_f64(value) + return Float64.from_c_float(f) + +cpdef Float64 ui32_to_f64(uint32_t value): + cdef cfloat.float64_t f = cfloat.ui32_to_f64(value) + return Float64.from_c_float(f) + +cpdef uint32_t f64_to_ui32(Float64 a1): + cdef uint32_t i = cfloat.f64_to_ui32(a1._c_float, + cfloat.softfloat_roundingMode, True) + return i + +cpdef int32_t f64_to_i32(Float64 a1): + cdef int32_t i = cfloat.f64_to_i32(a1._c_float, + cfloat.softfloat_roundingMode, True) + return i + +# u/i64 <-> f16 + +cpdef Float16 i64_to_f16(int64_t value): + cdef cfloat.float16_t f = cfloat.i64_to_f16(value) + return Float16.from_c_float(f) + +cpdef Float16 ui64_to_f16(uint64_t value): + cdef cfloat.float16_t f = cfloat.ui64_to_f16(value) + return Float16.from_c_float(f) + +cpdef uint64_t f16_to_ui64(Float16 a1): + cdef uint64_t i = cfloat.f16_to_ui64(a1._c_float, + cfloat.softfloat_roundingMode, True) + return i + +cpdef int64_t f16_to_i64(Float16 a1): + cdef int64_t i = cfloat.f16_to_i64(a1._c_float, + cfloat.softfloat_roundingMode, True) + return i + +# u/i64 <-> f32 + +cpdef Float32 i64_to_f32(int64_t value): + cdef cfloat.float32_t f = cfloat.i64_to_f32(value) + return Float32.from_c_float(f) + +cpdef Float32 ui64_to_f32(uint64_t value): + cdef cfloat.float32_t f = cfloat.ui64_to_f32(value) + return Float32.from_c_float(f) + +cpdef uint32_t f32_to_ui64(Float32 a1): + cdef uint32_t i = cfloat.f32_to_ui64(a1._c_float, + cfloat.softfloat_roundingMode, True) + return i + +cpdef int32_t f32_to_i64(Float32 a1): + cdef int32_t i = cfloat.f32_to_i64(a1._c_float, + cfloat.softfloat_roundingMode, True) + return i + +# u/i64 <-> f64 + +cpdef Float64 i64_to_f64(int64_t value): + cdef cfloat.float64_t f = cfloat.i64_to_f64(value) + return Float64.from_c_float(f) + +cpdef Float64 ui64_to_f64(uint64_t value): + cdef cfloat.float64_t f = cfloat.ui64_to_f64(value) + return Float64.from_c_float(f) + +cpdef uint64_t f64_to_ui64(Float64 a1): + cdef uint64_t i = cfloat.f64_to_ui64(a1._c_float, + cfloat.softfloat_roundingMode, True) + return i + +cpdef int64_t f64_to_i64(Float64 a1): + cdef int64_t i = cfloat.f64_to_i64(a1._c_float, + cfloat.softfloat_roundingMode, True) + return i # external, non-method arithmetic +cpdef Float32 f32_neg(Float32 a1): + cdef cfloat.float32_t f = _f32_neg(a1._c_float) + return Float32.from_c_float(f) + +cpdef Float32 f32_abs(Float32 a1): + cdef cfloat.float32_t f = _f32_abs(a1._c_float) + return Float32.from_c_float(f) + 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) @@ -634,12 +830,8 @@ 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) +cpdef Float32 f32_fma(Float32 acc, Float32 a1, Float32 a2): + cdef cfloat.float32_t f = cfloat.f32_mulAdd(a1._c_float, a2._c_float, acc._c_float) return Float32.from_c_float(f) cpdef Float32 f32_div(Float32 a1, Float32 a2): @@ -713,6 +905,10 @@ cdef class Float64: # convenience interface for use inside Python def __init__(self, value): + """Given an int, create a Float64 from the bitpattern represented by + that int. Otherwise, given some value, create a Float64 from + float(value). + """ cdef cfloat.ui64_double ud cdef cfloat.float64_t d @@ -748,6 +944,20 @@ cdef class Float64: # arithmetic + cpdef Float64 neg(self): + cdef cfloat.float64_t f = _f64_neg(self._c_float) + return Float64.from_c_float(f) + + def __neg__(self): + return self.neg() + + cpdef Float64 abs(self): + cdef cfloat.float64_t f = _f64_abs(self._c_float) + return Float64.from_c_float(f) + + def __abs__(self): + return self.abs() + 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) @@ -780,11 +990,7 @@ cdef class Float64: 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): + cpdef Float64 fma(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) @@ -805,6 +1011,12 @@ cdef class Float64: # in-place arithmetic + cpdef void ineg(self): + self._c_float = _f64_neg(self._c_float) + + cpdef void iabs(self): + self._c_float = _f64_abs(self._c_float) + cpdef void iround_to(self, uint_fast8_t rm, bint exact): self._c_float = cfloat.f64_roundToInt(self._c_float, rm, exact) @@ -832,10 +1044,7 @@ cdef class Float64: 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): + cpdef void ifma(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): @@ -893,6 +1102,14 @@ cdef class Float64: # external, non-method arithmetic +cpdef Float64 f64_neg(Float64 a1): + cdef cfloat.float64_t f = _f64_neg(a1._c_float) + return Float64.from_c_float(f) + +cpdef Float64 f64_abs(Float64 a1): + cdef cfloat.float64_t f = _f64_abs(a1._c_float) + return Float64.from_c_float(f) + 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) @@ -913,12 +1130,8 @@ 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) +cpdef Float64 f64_fma(Float64 acc, Float64 a1, Float64 a2): + cdef cfloat.float64_t f = cfloat.f64_mulAdd(a1._c_float, a2._c_float, acc._c_float) return Float64.from_c_float(f) cpdef Float64 f64_div(Float64 a1, Float64 a2):