aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Smeding <t.j.smeding@uu.nl>2024-05-27 14:10:57 +0200
committerTom Smeding <t.j.smeding@uu.nl>2024-05-27 14:10:57 +0200
commit9e5945120bbcfeff15ee7356398e06ab5ba25561 (patch)
tree9e9432d60b901776ebf552b501724e4c0a7b18f3
parente80b2593edc3d216905279ebcfa797593a1efbfc (diff)
Fast (C) Floating ops
-rw-r--r--bench/Main.hs27
-rw-r--r--cbits/arith.c130
-rw-r--r--cbits/arith_lists.h21
-rw-r--r--ox-arrays.cabal2
-rw-r--r--src/Data/Array/Nested/Internal.hs56
-rw-r--r--src/Data/Array/Nested/Internal/Arith.hs63
6 files changed, 259 insertions, 40 deletions
diff --git a/bench/Main.hs b/bench/Main.hs
index 8f3b670..41eb3b3 100644
--- a/bench/Main.hs
+++ b/bench/Main.hs
@@ -6,7 +6,7 @@ import qualified Numeric.LinearAlgebra as LA
import Test.Tasty.Bench
import Data.Array.Nested
-import Data.Array.Nested.Internal (mliftPrim2, arithPromoteRanked2)
+import Data.Array.Nested.Internal (mliftPrim, mliftPrim2, arithPromoteRanked, arithPromoteRanked2)
main :: IO ()
@@ -24,6 +24,14 @@ main = defaultMain
let n = 1_000_000
in nf (\(a, b) -> runScalar (rsumOuter1 (arithPromoteRanked2 (mliftPrim2 (/)) a b)))
(riota @Double n, riota n)
+ ,bench "sum(**) Double [1e6]" $
+ let n = 1_000_000
+ in nf (\(a, b) -> runScalar (rsumOuter1 (arithPromoteRanked2 (mliftPrim2 (**)) a b)))
+ (riota @Double n, riota n)
+ ,bench "sum(sin) Double [1e6]" $
+ let n = 1_000_000
+ in nf (\a -> runScalar (rsumOuter1 (arithPromoteRanked (mliftPrim sin) a)))
+ (riota @Double n)
,bench "sum Double [1e6]" $
let n = 1_000_000
in nf (\a -> runScalar (rsumOuter1 a))
@@ -42,6 +50,14 @@ main = defaultMain
let n = 1_000_000
in nf (\(a, b) -> runScalar (rsumOuter1 (a / b)))
(riota @Double n, riota n)
+ ,bench "sum(**) Double [1e6]" $
+ let n = 1_000_000
+ in nf (\(a, b) -> runScalar (rsumOuter1 (a ** b)))
+ (riota @Double n, riota n)
+ ,bench "sum(sin) Double [1e6]" $
+ let n = 1_000_000
+ in nf (\a -> runScalar (rsumOuter1 (sin a)))
+ (riota @Double n)
,bench "sum Double [1e6]" $
let n = 1_000_000
in nf (\a -> runScalar (rsumOuter1 a))
@@ -63,6 +79,15 @@ main = defaultMain
in nf (\(a, b) -> LA.sumElements (a / b))
(LA.linspace @Double n (0.0, fromIntegral (n - 1))
,LA.linspace @Double n (0.0, fromIntegral (n - 1)))
+ ,bench "sum(**) Double [1e6]" $
+ let n = 1_000_000
+ in nf (\(a, b) -> LA.sumElements (a ** b))
+ (LA.linspace @Double n (0.0, fromIntegral (n - 1))
+ ,LA.linspace @Double n (0.0, fromIntegral (n - 1)))
+ ,bench "sum(sin) Double [1e6]" $
+ let n = 1_000_000
+ in nf (\a -> LA.sumElements (sin a))
+ (LA.linspace @Double n (0.0, fromIntegral (n - 1)))
,bench "sum Double [1e6]" $
let n = 1_000_000
in nf (\a -> LA.sumElements a)
diff --git a/cbits/arith.c b/cbits/arith.c
index a71c1b9..e20578b 100644
--- a/cbits/arith.c
+++ b/cbits/arith.c
@@ -18,6 +18,66 @@
typedef int32_t i32;
typedef int64_t i64;
+/*****************************************************************************
+ * Additional math functions *
+ *****************************************************************************/
+
+#define GEN_ABS(x) \
+ _Generic((x), \
+ int: abs, \
+ long: labs, \
+ long long: llabs, \
+ float: fabsf, \
+ double: fabs)(x)
+
+// This does not result in multiple loads with GCC 13.
+#define GEN_SIGNUM(x) ((x) < 0 ? -1 : (x) > 0 ? 1 : 0)
+
+#define GEN_POW(x, y) _Generic((x), float: powf, double: pow)(x, y)
+#define GEN_LOGBASE(x, y) _Generic((x), float: logf(y) / logf(x), double: log(y) / log(x))
+#define GEN_EXP(x) _Generic((x), float: expf, double: exp)(x)
+#define GEN_LOG(x) _Generic((x), float: logf, double: log)(x)
+#define GEN_SQRT(x) _Generic((x), float: sqrtf, double: sqrt)(x)
+#define GEN_SIN(x) _Generic((x), float: sinf, double: sin)(x)
+#define GEN_COS(x) _Generic((x), float: cosf, double: cos)(x)
+#define GEN_TAN(x) _Generic((x), float: tanf, double: tan)(x)
+#define GEN_ASIN(x) _Generic((x), float: asinf, double: asin)(x)
+#define GEN_ACOS(x) _Generic((x), float: acosf, double: acos)(x)
+#define GEN_ATAN(x) _Generic((x), float: atanf, double: atan)(x)
+#define GEN_SINH(x) _Generic((x), float: sinhf, double: sinh)(x)
+#define GEN_COSH(x) _Generic((x), float: coshf, double: cosh)(x)
+#define GEN_TANH(x) _Generic((x), float: tanhf, double: tanh)(x)
+#define GEN_ASINH(x) _Generic((x), float: asinhf, double: asinh)(x)
+#define GEN_ACOSH(x) _Generic((x), float: acoshf, double: acosh)(x)
+#define GEN_ATANH(x) _Generic((x), float: atanhf, double: atanh)(x)
+#define GEN_LOG1P(x) _Generic((x), float: log1pf, double: log1p)(x)
+#define GEN_EXPM1(x) _Generic((x), float: expm1f, double: expm1)(x)
+
+// Taken from Haskell's implementation:
+// https://hackage.haskell.org/package/ghc-internal-9.1001.0/docs/src//GHC.Internal.Float.html#log1mexpOrd
+#define LOG1MEXP_IMPL(x) do { \
+ if (x > _Generic((x), float: logf, double: log)(2)) return GEN_LOG(-GEN_EXPM1(x)); \
+ else return GEN_LOG1P(-GEN_EXP(x)); \
+ } while (0)
+
+static float log1mexp_float(float x) { LOG1MEXP_IMPL(x); }
+static double log1mexp_double(double x) { LOG1MEXP_IMPL(x); }
+
+#define GEN_LOG1MEXP(x) _Generic((x), float: log1mexp_float, double: log1mexp_double)(x)
+
+// Taken from Haskell's implementation:
+// https://hackage.haskell.org/package/ghc-internal-9.1001.0/docs/src//GHC.Internal.Float.html#line-595
+#define LOG1PEXP_IMPL(x) do { \
+ if (x <= 18) return GEN_LOG1P(GEN_EXP(x)); \
+ if (x <= 100) return x + GEN_EXP(-x); \
+ return x; \
+ } while (0)
+
+static float log1pexp_float(float x) { LOG1PEXP_IMPL(x); }
+static double log1pexp_double(double x) { LOG1PEXP_IMPL(x); }
+
+#define GEN_LOG1PEXP(x) _Generic((x), float: log1pexp_float, double: log1pexp_double)(x)
+
/*****************************************************************************
* Kernel functions *
@@ -37,22 +97,22 @@ typedef int64_t i64;
for (i64 i = 0; i < n; i++) out[i] = x[i] op y; \
}
+#define PREFIX_BINOP(name, op, typ) \
+ static void oxarop_op_ ## name ## _ ## typ ## _sv(i64 n, typ *out, typ x, const typ *y) { \
+ for (i64 i = 0; i < n; i++) out[i] = op(x, y[i]); \
+ } \
+ static void oxarop_op_ ## name ## _ ## typ ## _vv(i64 n, typ *out, const typ *x, const typ *y) { \
+ for (i64 i = 0; i < n; i++) out[i] = op(x[i], y[i]); \
+ } \
+ static void oxarop_op_ ## name ## _ ## typ ## _vs(i64 n, typ *out, const typ *x, typ y) { \
+ for (i64 i = 0; i < n; i++) out[i] = op(x[i], y); \
+ }
+
#define UNARY_OP(name, op, typ) \
static void oxarop_op_ ## name ## _ ## typ(i64 n, typ *out, const typ *x) { \
for (i64 i = 0; i < n; i++) out[i] = op(x[i]); \
}
-#define GEN_ABS(x) \
- _Generic((x), \
- int: abs, \
- long: labs, \
- long long: llabs, \
- float: fabsf, \
- double: fabs)(x)
-
-// This does not result in multiple loads with GCC 13.
-#define GEN_SIGNUM(x) ((x) < 0 ? -1 : (x) > 0 ? 1 : 0)
-
// Walk a orthotope-style strided array, except for the inner dimension. The
// body is run for every "inner vector".
#define TARRAY_WALK_NOINNER(again_label_name, rank, shape, strides, body) \
@@ -161,18 +221,24 @@ enum fbinop_tag_t {
void oxarop_fbinary_ ## typ ## _sv(enum binop_tag_t tag, i64 n, typ *out, typ x, const typ *y) { \
switch (tag) { \
case FB_DIV: oxarop_op_fdiv_ ## typ ## _sv(n, out, x, y); break; \
+ case FB_POW: oxarop_op_pow_ ## typ ## _sv(n, out, x, y); break; \
+ case FB_LOGBASE: oxarop_op_logbase_ ## typ ## _sv(n, out, x, y); break; \
default: wrong_op("binary_sv", tag); \
} \
} \
void oxarop_fbinary_ ## typ ## _vs(enum binop_tag_t tag, i64 n, typ *out, const typ *x, typ y) { \
switch (tag) { \
case FB_DIV: oxarop_op_fdiv_ ## typ ## _vs(n, out, x, y); break; \
+ case FB_POW: oxarop_op_pow_ ## typ ## _vs(n, out, x, y); break; \
+ case FB_LOGBASE: oxarop_op_logbase_ ## typ ## _vs(n, out, x, y); break; \
default: wrong_op("binary_vs", tag); \
} \
} \
void oxarop_fbinary_ ## typ ## _vv(enum binop_tag_t tag, i64 n, typ *out, const typ *x, const typ *y) { \
switch (tag) { \
case FB_DIV: oxarop_op_fdiv_ ## typ ## _vv(n, out, x, y); break; \
+ case FB_POW: oxarop_op_pow_ ## typ ## _vv(n, out, x, y); break; \
+ case FB_LOGBASE: oxarop_op_logbase_ ## typ ## _vv(n, out, x, y); break; \
default: wrong_op("binary_vv", tag); \
} \
}
@@ -204,9 +270,28 @@ enum funop_tag_t {
};
#define ENTRY_FUNARY_OPS(typ) \
- void oxarop_funary_ ## typ(enum unop_tag_t tag, i64 n, typ *out, const typ *x) { \
+ void oxarop_funary_ ## typ(enum funop_tag_t tag, i64 n, typ *out, const typ *x) { \
switch (tag) { \
case FU_RECIP: oxarop_op_recip_ ## typ(n, out, x); break; \
+ case FU_EXP: oxarop_op_exp_ ## typ(n, out, x); break; \
+ case FU_LOG: oxarop_op_log_ ## typ(n, out, x); break; \
+ case FU_SQRT: oxarop_op_sqrt_ ## typ(n, out, x); break; \
+ case FU_SIN: oxarop_op_sin_ ## typ(n, out, x); break; \
+ case FU_COS: oxarop_op_cos_ ## typ(n, out, x); break; \
+ case FU_TAN: oxarop_op_tan_ ## typ(n, out, x); break; \
+ case FU_ASIN: oxarop_op_asin_ ## typ(n, out, x); break; \
+ case FU_ACOS: oxarop_op_acos_ ## typ(n, out, x); break; \
+ case FU_ATAN: oxarop_op_atan_ ## typ(n, out, x); break; \
+ case FU_SINH: oxarop_op_sinh_ ## typ(n, out, x); break; \
+ case FU_COSH: oxarop_op_cosh_ ## typ(n, out, x); break; \
+ case FU_TANH: oxarop_op_tanh_ ## typ(n, out, x); break; \
+ case FU_ASINH: oxarop_op_asinh_ ## typ(n, out, x); break; \
+ case FU_ACOSH: oxarop_op_acosh_ ## typ(n, out, x); break; \
+ case FU_ATANH: oxarop_op_atanh_ ## typ(n, out, x); break; \
+ case FU_LOG1P: oxarop_op_log1p_ ## typ(n, out, x); break; \
+ case FU_EXPM1: oxarop_op_expm1_ ## typ(n, out, x); break; \
+ case FU_LOG1PEXP: oxarop_op_log1pexp_ ## typ(n, out, x); break; \
+ case FU_LOG1MEXP: oxarop_op_log1mexp_ ## typ(n, out, x); break; \
default: wrong_op("unary", tag); \
} \
}
@@ -253,7 +338,28 @@ NUM_TYPES_XLIST
#define X(typ) \
NONCOMM_OP(fdiv, /, typ) \
+ PREFIX_BINOP(pow, GEN_POW, typ) \
+ PREFIX_BINOP(logbase, GEN_LOGBASE, typ) \
UNARY_OP(recip, 1.0/, typ) \
+ UNARY_OP(exp, GEN_EXP, typ) \
+ UNARY_OP(log, GEN_LOG, typ) \
+ UNARY_OP(sqrt, GEN_SQRT, typ) \
+ UNARY_OP(sin, GEN_SIN, typ) \
+ UNARY_OP(cos, GEN_COS, typ) \
+ UNARY_OP(tan, GEN_TAN, typ) \
+ UNARY_OP(asin, GEN_ASIN, typ) \
+ UNARY_OP(acos, GEN_ACOS, typ) \
+ UNARY_OP(atan, GEN_ATAN, typ) \
+ UNARY_OP(sinh, GEN_SINH, typ) \
+ UNARY_OP(cosh, GEN_COSH, typ) \
+ UNARY_OP(tanh, GEN_TANH, typ) \
+ UNARY_OP(asinh, GEN_ASINH, typ) \
+ UNARY_OP(acosh, GEN_ACOSH, typ) \
+ UNARY_OP(atanh, GEN_ATANH, typ) \
+ UNARY_OP(log1p, GEN_LOG1P, typ) \
+ UNARY_OP(expm1, GEN_EXPM1, typ) \
+ UNARY_OP(log1pexp, GEN_LOG1PEXP, typ) \
+ UNARY_OP(log1mexp, GEN_LOG1MEXP, typ) \
ENTRY_FBINARY_OPS(typ) \
ENTRY_FUNARY_OPS(typ)
FLOAT_TYPES_XLIST
diff --git a/cbits/arith_lists.h b/cbits/arith_lists.h
index 1137c18..2e37575 100644
--- a/cbits/arith_lists.h
+++ b/cbits/arith_lists.h
@@ -3,12 +3,33 @@ LIST_BINOP(BO_SUB, 2, -)
LIST_BINOP(BO_MUL, 3, *)
LIST_FBINOP(FB_DIV, 1, /)
+LIST_FBINOP(FB_POW, 2, **)
+LIST_FBINOP(FB_LOGBASE, 3, logBase)
LIST_UNOP(UO_NEG, 1,)
LIST_UNOP(UO_ABS, 2,)
LIST_UNOP(UO_SIGNUM, 3,)
LIST_FUNOP(FU_RECIP, 1,)
+LIST_FUNOP(FU_EXP, 2,)
+LIST_FUNOP(FU_LOG, 3,)
+LIST_FUNOP(FU_SQRT, 4,)
+LIST_FUNOP(FU_SIN, 5,)
+LIST_FUNOP(FU_COS, 6,)
+LIST_FUNOP(FU_TAN, 7,)
+LIST_FUNOP(FU_ASIN, 8,)
+LIST_FUNOP(FU_ACOS, 9,)
+LIST_FUNOP(FU_ATAN, 10,)
+LIST_FUNOP(FU_SINH, 11,)
+LIST_FUNOP(FU_COSH, 12,)
+LIST_FUNOP(FU_TANH, 13,)
+LIST_FUNOP(FU_ASINH, 14,)
+LIST_FUNOP(FU_ACOSH, 15,)
+LIST_FUNOP(FU_ATANH, 16,)
+LIST_FUNOP(FU_LOG1P, 17,)
+LIST_FUNOP(FU_EXPM1, 18,)
+LIST_FUNOP(FU_LOG1PEXP, 19,)
+LIST_FUNOP(FU_LOG1MEXP, 20,)
LIST_REDOP(RO_SUM1, 1,)
LIST_REDOP(RO_PRODUCT1, 2,)
diff --git a/ox-arrays.cabal b/ox-arrays.cabal
index 875c54e..d0aed82 100644
--- a/ox-arrays.cabal
+++ b/ox-arrays.cabal
@@ -5,6 +5,8 @@ author: Tom Smeding
license: BSD-3-Clause
build-type: Simple
+extra-source-files: cbits/arith_lists.h
+
library
exposed-modules:
Data.Array.Mixed
diff --git a/src/Data/Array/Nested/Internal.hs b/src/Data/Array/Nested/Internal.hs
index ef2ad6b..f8d16aa 100644
--- a/src/Data/Array/Nested/Internal.hs
+++ b/src/Data/Array/Nested/Internal.hs
@@ -1048,34 +1048,36 @@ instance (NumElt a, PrimElt a) => Num (Mixed sh a) where
signum = mliftNumElt1 numEltSignum
fromInteger _ = error "Data.Array.Nested.fromIntegral: No singletons available, use explicit mreplicate"
-instance (FloatElt a, NumElt a, PrimElt a, Fractional a) => Fractional (Mixed sh a) where
+instance (FloatElt a, NumElt a, PrimElt a) => Fractional (Mixed sh a) where
fromRational _ = error "Data.Array.Nested.fromRational: No singletons available, use explicit mreplicate"
recip = mliftNumElt1 floatEltRecip
(/) = mliftNumElt2 floatEltDiv
-instance (FloatElt a, NumElt a, PrimElt a, Floating a) => Floating (Mixed sh a) where
+instance (FloatElt a, NumElt a, PrimElt a) => Floating (Mixed sh a) where
pi = error "Data.Array.Nested.pi: No singletons available, use explicit mreplicate"
- exp = mliftPrim exp
- log = mliftPrim log
- sqrt = mliftPrim sqrt
- (**) = mliftPrim2 (**)
- logBase = mliftPrim2 logBase
- sin = mliftPrim sin
- cos = mliftPrim cos
- tan = mliftPrim tan
- asin = mliftPrim asin
- acos = mliftPrim acos
- atan = mliftPrim atan
- sinh = mliftPrim sinh
- cosh = mliftPrim cosh
- tanh = mliftPrim tanh
- asinh = mliftPrim asinh
- acosh = mliftPrim acosh
- atanh = mliftPrim atanh
- log1p = mliftPrim GHC.Float.log1p
- expm1 = mliftPrim GHC.Float.expm1
- log1pexp = mliftPrim GHC.Float.log1pexp
- log1mexp = mliftPrim GHC.Float.log1mexp
+ exp = mliftNumElt1 floatEltExp
+ log = mliftNumElt1 floatEltLog
+ sqrt = mliftNumElt1 floatEltSqrt
+
+ (**) = mliftNumElt2 floatEltPow
+ logBase = mliftNumElt2 floatEltLogbase
+
+ sin = mliftNumElt1 floatEltSin
+ cos = mliftNumElt1 floatEltCos
+ tan = mliftNumElt1 floatEltTan
+ asin = mliftNumElt1 floatEltAsin
+ acos = mliftNumElt1 floatEltAcos
+ atan = mliftNumElt1 floatEltAtan
+ sinh = mliftNumElt1 floatEltSinh
+ cosh = mliftNumElt1 floatEltCosh
+ tanh = mliftNumElt1 floatEltTanh
+ asinh = mliftNumElt1 floatEltAsinh
+ acosh = mliftNumElt1 floatEltAcosh
+ atanh = mliftNumElt1 floatEltAtanh
+ log1p = mliftNumElt1 floatEltLog1p
+ expm1 = mliftNumElt1 floatEltExpm1
+ log1pexp = mliftNumElt1 floatEltLog1pexp
+ log1mexp = mliftNumElt1 floatEltLog1mexp
mtoRanked :: forall sh a. Elt a => Mixed sh a -> Ranked (X.Rank sh) a
mtoRanked arr
@@ -1367,12 +1369,12 @@ instance (NumElt a, PrimElt a) => Num (Ranked n a) where
signum = arithPromoteRanked signum
fromInteger _ = error "Data.Array.Nested.fromIntegral: No singletons available, use explicit rreplicateScal"
-instance (FloatElt a, NumElt a, PrimElt a, Fractional a) => Fractional (Ranked n a) where
+instance (FloatElt a, NumElt a, PrimElt a) => Fractional (Ranked n a) where
fromRational _ = error "Data.Array.Nested.fromRational: No singletons available, use explicit rreplicateScal"
recip = arithPromoteRanked recip
(/) = arithPromoteRanked2 (/)
-instance (FloatElt a, NumElt a, PrimElt a, Floating a) => Floating (Ranked n a) where
+instance (FloatElt a, NumElt a, PrimElt a) => Floating (Ranked n a) where
pi = error "Data.Array.Nested.pi: No singletons available, use explicit rreplicateScal"
exp = arithPromoteRanked exp
log = arithPromoteRanked log
@@ -1698,12 +1700,12 @@ instance (NumElt a, PrimElt a) => Num (Shaped sh a) where
signum = arithPromoteShaped signum
fromInteger _ = error "Data.Array.Nested.fromIntegral: No singletons available, use explicit sreplicateScal"
-instance (FloatElt a, NumElt a, PrimElt a, Fractional a) => Fractional (Shaped sh a) where
+instance (FloatElt a, NumElt a, PrimElt a) => Fractional (Shaped sh a) where
fromRational _ = error "Data.Array.Nested.fromRational: No singletons available, use explicit sreplicateScal"
recip = arithPromoteShaped recip
(/) = arithPromoteShaped2 (/)
-instance (FloatElt a, NumElt a, PrimElt a, Floating a) => Floating (Shaped sh a) where
+instance (FloatElt a, NumElt a, PrimElt a) => Floating (Shaped sh a) where
pi = error "Data.Array.Nested.pi: No singletons available, use explicit sreplicateScal"
exp = arithPromoteShaped exp
log = arithPromoteShaped log
diff --git a/src/Data/Array/Nested/Internal/Arith.hs b/src/Data/Array/Nested/Internal/Arith.hs
index 07d5d8a..95fcfcf 100644
--- a/src/Data/Array/Nested/Internal/Arith.hs
+++ b/src/Data/Array/Nested/Internal/Arith.hs
@@ -361,12 +361,75 @@ instance NumElt CInt where
class FloatElt a where
floatEltDiv :: SNat n -> RS.Array n a -> RS.Array n a -> RS.Array n a
+ floatEltPow :: SNat n -> RS.Array n a -> RS.Array n a -> RS.Array n a
+ floatEltLogbase :: SNat n -> RS.Array n a -> RS.Array n a -> RS.Array n a
floatEltRecip :: SNat n -> RS.Array n a -> RS.Array n a
+ floatEltExp :: SNat n -> RS.Array n a -> RS.Array n a
+ floatEltLog :: SNat n -> RS.Array n a -> RS.Array n a
+ floatEltSqrt :: SNat n -> RS.Array n a -> RS.Array n a
+ floatEltSin :: SNat n -> RS.Array n a -> RS.Array n a
+ floatEltCos :: SNat n -> RS.Array n a -> RS.Array n a
+ floatEltTan :: SNat n -> RS.Array n a -> RS.Array n a
+ floatEltAsin :: SNat n -> RS.Array n a -> RS.Array n a
+ floatEltAcos :: SNat n -> RS.Array n a -> RS.Array n a
+ floatEltAtan :: SNat n -> RS.Array n a -> RS.Array n a
+ floatEltSinh :: SNat n -> RS.Array n a -> RS.Array n a
+ floatEltCosh :: SNat n -> RS.Array n a -> RS.Array n a
+ floatEltTanh :: SNat n -> RS.Array n a -> RS.Array n a
+ floatEltAsinh :: SNat n -> RS.Array n a -> RS.Array n a
+ floatEltAcosh :: SNat n -> RS.Array n a -> RS.Array n a
+ floatEltAtanh :: SNat n -> RS.Array n a -> RS.Array n a
+ floatEltLog1p :: SNat n -> RS.Array n a -> RS.Array n a
+ floatEltExpm1 :: SNat n -> RS.Array n a -> RS.Array n a
+ floatEltLog1pexp :: SNat n -> RS.Array n a -> RS.Array n a
+ floatEltLog1mexp :: SNat n -> RS.Array n a -> RS.Array n a
instance FloatElt Float where
floatEltDiv = divVectorFloat
+ floatEltPow = powVectorFloat
+ floatEltLogbase = logbaseVectorFloat
floatEltRecip = recipVectorFloat
+ floatEltExp = expVectorFloat
+ floatEltLog = logVectorFloat
+ floatEltSqrt = sqrtVectorFloat
+ floatEltSin = sinVectorFloat
+ floatEltCos = cosVectorFloat
+ floatEltTan = tanVectorFloat
+ floatEltAsin = asinVectorFloat
+ floatEltAcos = acosVectorFloat
+ floatEltAtan = atanVectorFloat
+ floatEltSinh = sinhVectorFloat
+ floatEltCosh = coshVectorFloat
+ floatEltTanh = tanhVectorFloat
+ floatEltAsinh = asinhVectorFloat
+ floatEltAcosh = acoshVectorFloat
+ floatEltAtanh = atanhVectorFloat
+ floatEltLog1p = log1pVectorFloat
+ floatEltExpm1 = expm1VectorFloat
+ floatEltLog1pexp = log1pexpVectorFloat
+ floatEltLog1mexp = log1mexpVectorFloat
instance FloatElt Double where
floatEltDiv = divVectorDouble
+ floatEltPow = powVectorDouble
+ floatEltLogbase = logbaseVectorDouble
floatEltRecip = recipVectorDouble
+ floatEltExp = expVectorDouble
+ floatEltLog = logVectorDouble
+ floatEltSqrt = sqrtVectorDouble
+ floatEltSin = sinVectorDouble
+ floatEltCos = cosVectorDouble
+ floatEltTan = tanVectorDouble
+ floatEltAsin = asinVectorDouble
+ floatEltAcos = acosVectorDouble
+ floatEltAtan = atanVectorDouble
+ floatEltSinh = sinhVectorDouble
+ floatEltCosh = coshVectorDouble
+ floatEltTanh = tanhVectorDouble
+ floatEltAsinh = asinhVectorDouble
+ floatEltAcosh = acoshVectorDouble
+ floatEltAtanh = atanhVectorDouble
+ floatEltLog1p = log1pVectorDouble
+ floatEltExpm1 = expm1VectorDouble
+ floatEltLog1pexp = log1pexpVectorDouble
+ floatEltLog1mexp = log1mexpVectorDouble