correcting use of uint32_t where uint64_t should be used
[sfpy.git] / sfpy / float.pyx
index d25a6dacc254a7f7446d256882f725e2dfa0dead..d1e7134b2e18563e07fcc6e5b88a5f0aef1150db 100644 (file)
@@ -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 fam(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 ifam(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_fam(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 fam(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 ifam(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_fam(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 fam(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 ifam(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_fam(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):