commit 609dc3a14cbd60fe438637d7582dd5c78aeb3690
parent b063114b7bb195a28a3d6e40a9ba203594891523
Author: d.levin256@gmail.com <d.levin256@gmail.com>
Date: Wed, 10 Aug 2016 10:18:48 +0300
Merge branch 'dev'
Diffstat:
20 files changed, 592 insertions(+), 280 deletions(-)
diff --git a/.travis.yml b/.travis.yml
@@ -1,5 +1,4 @@
language: cpp
-
matrix:
include:
- os: linux
@@ -15,15 +14,39 @@ matrix:
- clang-3.8
- libmpfr-dev
env:
- - CXXCOMPILER=clang++-3.8 CCOMPILER=clang-3.8
+ - TEST=LINUX-X86-64 CMAKEARGS="-DCMAKE_CXX_COMPILER=clang++-3.8 -DCMAKE_C_COMPILER=clang-3.8 -DCMAKE_BUILD_TYPE=Release .."
+ - os: linux
+ compiler: clang
+ sudo: required
+ dist: trusty
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-precise-3.8
+ packages:
+ - g++-5
+ - clang-3.8
+ - qemu
+ - g++-arm-linux-gnueabihf
+ env:
+ - TEST=LINUX-ARMV7 CMAKEARGS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../cmake/arm.cmake -DARCH_FLAGS=-DLIBC_WORKAROUND_GETS=1 .."
- os: osx
osx_image: xcode8
+ env:
+ - TEST=XCODE8 CMAKEARGS="-DCMAKE_BUILD_TYPE=Release .."
- os: osx
osx_image: xcode7.3
+ env:
+ - TEST=XCODE7.3 CMAKEARGS="-DCMAKE_BUILD_TYPE=Release .."
- os: osx
osx_image: xcode7
+ env:
+ - TEST=XCODE7 CMAKEARGS="-DCMAKE_BUILD_TYPE=Release .."
- os: osx
osx_image: beta-xcode6.3
+ env:
+ - TEST=XCODE6.3 CMAKEARGS="-DCMAKE_BUILD_TYPE=Release .."
before_install:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi
@@ -33,7 +56,7 @@ before_install:
script:
- mkdir build
- cd build
- - cmake -DCMAKE_CXX_COMPILER=$CXXCOMPILER -DCMAKE_C_COMPILER=$CCOMPILER -DCMAKE_BUILD_TYPE=Release ..
+ - cmake $CMAKEARGS
- make -j4
- cd tests
- ctest
diff --git a/cmake/arm.cmake b/cmake/arm.cmake
@@ -0,0 +1,29 @@
+set (CMAKE_SYSTEM_NAME Linux)
+set (CMAKE_SYSTEM_VERSION 1)
+set (UNIX True)
+set (ARM True)
+set (CMAKE_SYSTEM_PROCESSOR arm)
+
+include (CMakeForceCompiler)
+CMAKE_FORCE_CXX_COMPILER (/usr/bin/clang++-3.8 Clang)
+CMAKE_FORCE_C_COMPILER (/usr/bin/clang-3.8 Clang)
+set (CMAKE_CXX_COMPILER_WORKS TRUE)
+set (CMAKE_C_COMPILER_WORKS TRUE)
+
+set (ARM_ROOT "/usr/arm-linux-gnueabihf/include")
+set (GCC_VER 4.8.4)
+set (SYS_PATHS "-isystem ${ARM_ROOT}/c++/${GCC_VER} -isystem ${ARM_ROOT}/c++/${GCC_VER}/backward -isystem ${ARM_ROOT}/c++/${GCC_VER}/arm-linux-gnueabihf -isystem ${ARM_ROOT}")
+
+set (ARM_COMMON_FLAGS "-target arm-linux-gnueabihf -mcpu=cortex-a15 -mfpu=neon-vfpv4 -mfloat-abi=hard -static")
+
+set (CMAKE_CXX_FLAGS "${SYS_PATHS} ${ARM_COMMON_FLAGS}")
+set (CMAKE_C_FLAGS " ${SYS_PATHS} ${ARM_COMMON_FLAGS}")
+
+set (CMAKE_CXX_LINK_FLAGS " ${ARM_COMMON_FLAGS} ${CMAKE_CXX_LINK_FLAGS}")
+set (CMAKE_C_LINK_FLAGS " ${ARM_COMMON_FLAGS} ${CMAKE_C_LINK_FLAGS}")
+
+message(STATUS "${ARM_COMMON_FLAGS}")
+
+set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
+set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
diff --git a/include/kfr/base/asin_acos.hpp b/include/kfr/base/asin_acos.hpp
@@ -46,8 +46,8 @@ KFR_SINTRIN vec<Tout, N> acos(const vec<T, N>& x)
const vec<Tout, N> xx = x;
return atan2(sqrt(Tout(1) - xx * xx), xx);
}
-KFR_I_CONVERTER(asin)
-KFR_I_CONVERTER(acos)
+KFR_I_FLT_CONVERTER(asin)
+KFR_I_FLT_CONVERTER(acos)
}
KFR_I_FN(asin)
KFR_I_FN(acos)
diff --git a/include/kfr/base/atan.hpp b/include/kfr/base/atan.hpp
@@ -188,20 +188,34 @@ KFR_SINTRIN vec<f64, N> atan(const vec<f64, N>& s)
return t;
}
-template <typename T>
-KFR_SINTRIN T atandeg(const T& x)
+template <size_t N>
+KFR_SINTRIN vec<f32, N> atandeg(const vec<f32, N>& x)
+{
+ return atan(x) * c_radtodeg<f32>;
+}
+
+template <size_t N>
+KFR_SINTRIN vec<f64, N> atandeg(const vec<f64, N>& x)
{
- return atan(x) * c_radtodeg<T>;
+ return atan(x) * c_radtodeg<f64>;
}
-template <typename T1, typename T2>
-KFR_SINTRIN common_type<T1, T2> atan2deg(const T1& y, const T2& x)
+template <size_t N>
+KFR_SINTRIN vec<f32, N> atan2deg(const vec<f32, N>& y, const vec<f32, N>& x)
+{
+ return atan2(y, x) * c_radtodeg<f32>;
+}
+
+template <size_t N>
+KFR_SINTRIN vec<f64, N> atan2deg(const vec<f64, N>& y, const vec<f64, N>& x)
{
- return atan2(y, x) * c_radtodeg<common_type<T1, T2>>;
+ return atan2(y, x) * c_radtodeg<f64>;
}
-KFR_I_CONVERTER(atan)
-KFR_I_CONVERTER(atan2)
+KFR_I_FLT_CONVERTER(atan)
+KFR_I_FLT_CONVERTER(atan2)
+KFR_I_FLT_CONVERTER(atandeg)
+KFR_I_FLT_CONVERTER(atan2deg)
}
KFR_I_FN(atan)
KFR_I_FN(atandeg)
@@ -209,7 +223,7 @@ KFR_I_FN(atan2)
KFR_I_FN(atan2deg)
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN ftype<T1> atan(const T1& x)
+KFR_INTRIN flt_type<T1> atan(const T1& x)
{
return intrinsics::atan(x);
}
@@ -221,7 +235,7 @@ KFR_INTRIN internal::expression_function<fn::atan, E1> atan(E1&& x)
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN ftype<T1> atandeg(const T1& x)
+KFR_INTRIN flt_type<T1> atandeg(const T1& x)
{
return intrinsics::atandeg(x);
}
diff --git a/include/kfr/base/function.hpp b/include/kfr/base/function.hpp
@@ -41,8 +41,54 @@ namespace kfr
return to_scalar(::kfr::intrinsics::fn(vecout(a), vecout(b)...)); \
}
+#define KFR_I_FLT_CONVERTER(fn) \
+ template <typename T1, typename... Args, \
+ typename Tout = ::kfr::flt_type<::cometa::common_type<T1, Args...>>> \
+ KFR_SINTRIN Tout fn(const T1& a, const Args&... b) \
+ { \
+ using vecout = vec1<Tout>; \
+ return to_scalar(::kfr::intrinsics::fn(vecout(a), vecout(b)...)); \
+ }
+
+namespace internal
+{
+template <typename T>
+struct flt_type_impl
+{
+ using type = fbase;
+};
+
+template <typename T, size_t N>
+struct flt_type_impl<vec<T, N>>
+{
+ using type = vec<fbase, N>;
+};
+
+template <>
+struct flt_type_impl<float>
+{
+ using type = float;
+};
+template <>
+struct flt_type_impl<double>
+{
+ using type = double;
+};
+
+template <size_t N>
+struct flt_type_impl<vec<float, N>>
+{
+ using type = vec<float, N>;
+};
+template <size_t N>
+struct flt_type_impl<vec<double, N>>
+{
+ using type = vec<double, N>;
+};
+}
+
template <typename T>
-using flt_type = conditional<std::is_floating_point<deep_subtype<T>>::value, T, deep_rebind<T, fbase>>;
+using flt_type = typename internal::flt_type_impl<T>::type;
namespace intrinsics
{
diff --git a/include/kfr/base/gamma.hpp b/include/kfr/base/gamma.hpp
@@ -58,14 +58,14 @@ KFR_SINTRIN vec<T, N> factorial_approx(const vec<T, N>& x)
{
return gamma(x + T(1));
}
-KFR_I_CONVERTER(gamma)
-KFR_I_CONVERTER(factorial_approx)
+KFR_I_FLT_CONVERTER(gamma)
+KFR_I_FLT_CONVERTER(factorial_approx)
}
KFR_I_FN(gamma)
KFR_I_FN(factorial_approx)
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 gamma(const T1& x)
+KFR_INTRIN flt_type<T1> gamma(const T1& x)
{
return intrinsics::gamma(x);
}
@@ -77,7 +77,7 @@ KFR_INTRIN internal::expression_function<fn::gamma, E1> gamma(E1&& x)
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 factorial_approx(const T1& x)
+KFR_INTRIN flt_type<T1> factorial_approx(const T1& x)
{
return intrinsics::factorial_approx(x);
}
diff --git a/include/kfr/base/hyperbolic.hpp b/include/kfr/base/hyperbolic.hpp
@@ -35,54 +35,54 @@ namespace kfr
namespace intrinsics
{
-template <typename T, size_t N>
-KFR_SINTRIN vec<T, N> sinh(const vec<T, N>& x)
+template <typename T, size_t N, typename Tout = flt_type<T>>
+KFR_SINTRIN vec<Tout, N> sinh(const vec<T, N>& x)
{
- return (exp(x) - exp(-x)) * T(0.5);
+ return (exp(x) - exp(-x)) * Tout(0.5);
}
-template <typename T, size_t N>
-KFR_SINTRIN vec<T, N> cosh(const vec<T, N>& x)
+template <typename T, size_t N, typename Tout = flt_type<T>>
+KFR_SINTRIN vec<Tout, N> cosh(const vec<T, N>& x)
{
- return (exp(x) + exp(-x)) * T(0.5);
+ return (exp(x) + exp(-x)) * Tout(0.5);
}
-template <typename T, size_t N>
-KFR_SINTRIN vec<T, N> tanh(const vec<T, N>& x)
+template <typename T, size_t N, typename Tout = flt_type<T>>
+KFR_SINTRIN vec<Tout, N> tanh(const vec<T, N>& x)
{
- x = -2 * x;
- return (1 - exp(x)) / (1 + exp(x));
+ const vec<Tout, N> a = exp(2 * x);
+ return (a - 1) / (a + 1);
}
-template <typename T, size_t N>
-KFR_SINTRIN vec<T, N> coth(const vec<T, N>& x)
+template <typename T, size_t N, typename Tout = flt_type<T>>
+KFR_SINTRIN vec<Tout, N> coth(const vec<T, N>& x)
{
- x = -2 * x;
- return (1 + exp(x)) / (1 - exp(x));
+ const vec<Tout, N> a = exp(2 * x);
+ return (a + 1) / (a - 1);
}
-template <typename T, size_t N, KFR_ENABLE_IF(N > 1)>
-KFR_SINTRIN vec<T, N> sinhcosh(const vec<T, N>& x)
+template <typename T, size_t N, typename Tout = flt_type<T>>
+KFR_SINTRIN vec<Tout, N> sinhcosh(const vec<T, N>& x)
{
- const vec<T, N> a = exp(x);
- const vec<T, N> b = exp(-x);
- return subadd(a, b) * T(0.5);
+ const vec<Tout, N> a = exp(x);
+ const vec<Tout, N> b = exp(-x);
+ return subadd(a, b) * Tout(0.5);
}
-template <typename T, size_t N, KFR_ENABLE_IF(N > 1)>
-KFR_SINTRIN vec<T, N> coshsinh(const vec<T, N>& x)
+template <typename T, size_t N, typename Tout = flt_type<T>>
+KFR_SINTRIN vec<Tout, N> coshsinh(const vec<T, N>& x)
{
- const vec<T, N> a = exp(x);
- const vec<T, N> b = exp(-x);
- return addsub(a, b) * T(0.5);
+ const vec<Tout, N> a = exp(x);
+ const vec<Tout, N> b = exp(-x);
+ return addsub(a, b) * Tout(0.5);
}
-KFR_I_CONVERTER(sinh)
-KFR_I_CONVERTER(cosh)
-KFR_I_CONVERTER(tanh)
-KFR_I_CONVERTER(coth)
-KFR_I_CONVERTER(sinhcosh)
-KFR_I_CONVERTER(coshsinh)
+KFR_I_FLT_CONVERTER(sinh)
+KFR_I_FLT_CONVERTER(cosh)
+KFR_I_FLT_CONVERTER(tanh)
+KFR_I_FLT_CONVERTER(coth)
+KFR_I_FLT_CONVERTER(sinhcosh)
+KFR_I_FLT_CONVERTER(coshsinh)
}
KFR_I_FN(sinh)
KFR_I_FN(cosh)
@@ -92,7 +92,7 @@ KFR_I_FN(sinhcosh)
KFR_I_FN(coshsinh)
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 sinh(const T1& x)
+KFR_INTRIN flt_type<T1> sinh(const T1& x)
{
return intrinsics::sinh(x);
}
@@ -104,7 +104,7 @@ KFR_INTRIN internal::expression_function<fn::sinh, E1> sinh(E1&& x)
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 cosh(const T1& x)
+KFR_INTRIN flt_type<T1> cosh(const T1& x)
{
return intrinsics::cosh(x);
}
@@ -116,7 +116,7 @@ KFR_INTRIN internal::expression_function<fn::cosh, E1> cosh(E1&& x)
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 tanh(const T1& x)
+KFR_INTRIN flt_type<T1> tanh(const T1& x)
{
return intrinsics::tanh(x);
}
@@ -128,7 +128,7 @@ KFR_INTRIN internal::expression_function<fn::tanh, E1> tanh(E1&& x)
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 coth(const T1& x)
+KFR_INTRIN flt_type<T1> coth(const T1& x)
{
return intrinsics::coth(x);
}
@@ -140,7 +140,7 @@ KFR_INTRIN internal::expression_function<fn::coth, E1> coth(E1&& x)
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 sinhcosh(const T1& x)
+KFR_INTRIN flt_type<T1> sinhcosh(const T1& x)
{
return intrinsics::sinhcosh(x);
}
@@ -152,7 +152,7 @@ KFR_INTRIN internal::expression_function<fn::sinhcosh, E1> sinhcosh(E1&& x)
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 coshsinh(const T1& x)
+KFR_INTRIN flt_type<T1> coshsinh(const T1& x)
{
return intrinsics::coshsinh(x);
}
diff --git a/include/kfr/base/log_exp.hpp b/include/kfr/base/log_exp.hpp
@@ -133,15 +133,15 @@ KFR_SINTRIN vec<f64, N> log(const vec<f64, N>& d)
return x;
}
-template <typename T, size_t N, KFR_ENABLE_IF(is_f_class<T>::value)>
-KFR_SINTRIN vec<T, N> log2(const vec<T, N>& x)
+template <typename T, size_t N, typename Tout = flt_type<T>>
+KFR_SINTRIN vec<Tout, N> log2(const vec<T, N>& x)
{
- return log(x) * c_recip_log_2<T>;
+ return log(cast<Tout>(x)) * c_recip_log_2<Tout>;
}
-template <typename T, size_t N, KFR_ENABLE_IF(is_f_class<T>::value)>
-KFR_SINTRIN vec<T, N> log10(const vec<T, N>& x)
+template <typename T, size_t N, typename Tout = flt_type<T>>
+KFR_SINTRIN vec<Tout, N> log10(const vec<T, N>& x)
{
- return log(x) * c_recip_log_10<T>;
+ return log(cast<Tout>(x)) * c_recip_log_10<Tout>;
}
template <size_t N>
@@ -219,39 +219,15 @@ KFR_SINTRIN vec<f64, N> exp(const vec<f64, N>& d)
return u;
}
-template <typename T, size_t N, KFR_ENABLE_IF(is_f_class<T>::value)>
-KFR_SINTRIN vec<T, N> exp2(const vec<T, N>& x)
-{
- return exp(x * c_log_2<T>);
-}
-template <typename T, size_t N, KFR_ENABLE_IF(is_f_class<T>::value)>
-KFR_SINTRIN vec<T, N> exp10(const vec<T, N>& x)
-{
- return exp(x * c_log_10<T>);
-}
-
-template <typename T1, typename T2>
-KFR_SINTRIN common_type<T1, T2> logn(const T1& a, const T2& b)
-{
- return log(a) / log(b);
-}
-
-template <typename T1, typename T2>
-KFR_SINTRIN common_type<T1, T2> logm(const T1& a, const T2& b)
-{
- return log(a) * b;
-}
-
-template <typename T1, typename T2, typename T3>
-KFR_SINTRIN common_type<T1, T2, T3> exp_fmadd(const T1& x, const T2& m, const T3& a)
+template <typename T, size_t N, typename Tout = flt_type<T>>
+KFR_SINTRIN vec<Tout, N> exp2(const vec<T, N>& x)
{
- return exp(fmadd(x, m, a));
+ return exp(x * c_log_2<Tout>);
}
-
-template <typename T1, typename T2, typename T3>
-KFR_SINTRIN common_type<T1, T2, T3> log_fmadd(const T1& x, const T2& m, const T3& a)
+template <typename T, size_t N, typename Tout = flt_type<T>>
+KFR_SINTRIN vec<Tout, N> exp10(const vec<T, N>& x)
{
- return fmadd(log(x), m, a);
+ return exp(x * c_log_10<Tout>);
}
template <typename T, size_t N>
@@ -276,52 +252,46 @@ KFR_SINTRIN vec<T, N> cbrt(const vec<T, N>& x)
return pow<T, N>(x, T(0.333333333333333333333333333333333));
}
-template <typename T, size_t N, KFR_ENABLE_IF(!is_f_class<T>::value), typename Tout = ftype<T>>
-KFR_SINTRIN vec<Tout, N> exp(const vec<T, N>& x)
-{
- return exp(cast<Tout>(x));
-}
-template <typename T, size_t N, KFR_ENABLE_IF(!is_f_class<T>::value), typename Tout = ftype<T>>
-KFR_SINTRIN vec<Tout, N> exp2(const vec<T, N>& x)
-{
- return exp2(cast<Tout>(x));
-}
-template <typename T, size_t N, KFR_ENABLE_IF(!is_f_class<T>::value), typename Tout = ftype<T>>
-KFR_SINTRIN vec<Tout, N> exp10(const vec<T, N>& x)
+template <typename T, size_t N, KFR_ENABLE_IF(!is_f_class<T>::value), typename Tout = flt_type<T>>
+KFR_SINTRIN vec<Tout, N> cbrt(const vec<T, N>& x)
{
- return exp10(cast<Tout>(x));
+ return cbrt(cast<Tout>(x));
}
-template <typename T, size_t N, KFR_ENABLE_IF(!is_f_class<T>::value), typename Tout = ftype<T>>
-KFR_SINTRIN vec<Tout, N> log(const vec<T, N>& x)
+
+KFR_I_FLT_CONVERTER(exp)
+KFR_I_FLT_CONVERTER(exp2)
+KFR_I_FLT_CONVERTER(exp10)
+KFR_I_FLT_CONVERTER(log)
+KFR_I_FLT_CONVERTER(log2)
+KFR_I_FLT_CONVERTER(log10)
+KFR_I_FLT_CONVERTER(logb)
+KFR_I_FLT_CONVERTER(pow)
+KFR_I_FLT_CONVERTER(root)
+KFR_I_FLT_CONVERTER(cbrt)
+
+template <typename T1, typename T2>
+KFR_SINTRIN flt_type<common_type<T1, T2>> logn(const T1& a, const T2& b)
{
- return log(cast<Tout>(x));
+ return log(a) / log(b);
}
-template <typename T, size_t N, KFR_ENABLE_IF(!is_f_class<T>::value), typename Tout = ftype<T>>
-KFR_SINTRIN vec<Tout, N> log2(const vec<T, N>& x)
+
+template <typename T1, typename T2>
+KFR_SINTRIN flt_type<common_type<T1, T2>> logm(const T1& a, const T2& b)
{
- return log2(cast<Tout>(x));
+ return log(a) * b;
}
-template <typename T, size_t N, KFR_ENABLE_IF(!is_f_class<T>::value), typename Tout = ftype<T>>
-KFR_SINTRIN vec<Tout, N> log10(const vec<T, N>& x)
+
+template <typename T1, typename T2, typename T3>
+KFR_SINTRIN flt_type<common_type<T1, T2, T3>> exp_fmadd(const T1& x, const T2& m, const T3& a)
{
- return log10(cast<Tout>(x));
+ return exp(fmadd(x, m, a));
}
-template <typename T, size_t N, KFR_ENABLE_IF(!is_f_class<T>::value), typename Tout = ftype<T>>
-KFR_SINTRIN vec<Tout, N> cbrt(const vec<T, N>& x)
+
+template <typename T1, typename T2, typename T3>
+KFR_SINTRIN flt_type<common_type<T1, T2, T3>> log_fmadd(const T1& x, const T2& m, const T3& a)
{
- return cbrt(cast<Tout>(x));
+ return fmadd(log(x), m, a);
}
-
-KFR_I_CONVERTER(exp)
-KFR_I_CONVERTER(exp2)
-KFR_I_CONVERTER(exp10)
-KFR_I_CONVERTER(log)
-KFR_I_CONVERTER(log2)
-KFR_I_CONVERTER(log10)
-KFR_I_CONVERTER(logb)
-KFR_I_CONVERTER(pow)
-KFR_I_CONVERTER(root)
-KFR_I_CONVERTER(cbrt)
}
KFR_I_FN(exp)
KFR_I_FN(exp2)
@@ -339,7 +309,7 @@ KFR_I_FN(root)
KFR_I_FN(cbrt)
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 exp(const T1& x)
+KFR_INTRIN flt_type<T1> exp(const T1& x)
{
return intrinsics::exp(x);
}
@@ -351,7 +321,7 @@ KFR_INTRIN internal::expression_function<fn::exp, E1> exp(E1&& x)
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 exp2(const T1& x)
+KFR_INTRIN flt_type<T1> exp2(const T1& x)
{
return intrinsics::exp2(x);
}
@@ -363,7 +333,7 @@ KFR_INTRIN internal::expression_function<fn::exp2, E1> exp2(E1&& x)
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 exp10(const T1& x)
+KFR_INTRIN flt_type<T1> exp10(const T1& x)
{
return intrinsics::exp10(x);
}
@@ -375,7 +345,7 @@ KFR_INTRIN internal::expression_function<fn::exp10, E1> exp10(E1&& x)
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 log(const T1& x)
+KFR_INTRIN flt_type<T1> log(const T1& x)
{
return intrinsics::log(x);
}
@@ -387,7 +357,7 @@ KFR_INTRIN internal::expression_function<fn::log, E1> log(E1&& x)
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 log2(const T1& x)
+KFR_INTRIN flt_type<T1> log2(const T1& x)
{
return intrinsics::log2(x);
}
@@ -399,7 +369,7 @@ KFR_INTRIN internal::expression_function<fn::log2, E1> log2(E1&& x)
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 log10(const T1& x)
+KFR_INTRIN flt_type<T1> log10(const T1& x)
{
return intrinsics::log10(x);
}
@@ -411,7 +381,7 @@ KFR_INTRIN internal::expression_function<fn::log10, E1> log10(E1&& x)
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 logb(const T1& x)
+KFR_INTRIN flt_type<T1> logb(const T1& x)
{
return intrinsics::logb(x);
}
@@ -423,7 +393,7 @@ KFR_INTRIN internal::expression_function<fn::logb, E1> logb(E1&& x)
}
template <typename T1, typename T2, KFR_ENABLE_IF(is_numeric_args<T1, T2>::value)>
-KFR_INTRIN common_type<T1, T2> logn(const T1& x, const T2& y)
+KFR_INTRIN flt_type<common_type<T1, T2>> logn(const T1& x, const T2& y)
{
return intrinsics::logn(x, y);
}
@@ -435,7 +405,7 @@ KFR_INTRIN internal::expression_function<fn::logn, E1, E2> logn(E1&& x, E2&& y)
}
template <typename T1, typename T2, KFR_ENABLE_IF(is_numeric_args<T1, T2>::value)>
-KFR_INTRIN common_type<T1, T2> logm(const T1& x, const T2& y)
+KFR_INTRIN flt_type<common_type<T1, T2>> logm(const T1& x, const T2& y)
{
return intrinsics::logm(x, y);
}
@@ -447,7 +417,7 @@ KFR_INTRIN internal::expression_function<fn::logm, E1, E2> logm(E1&& x, E2&& y)
}
template <typename T1, typename T2, typename T3, KFR_ENABLE_IF(is_numeric_args<T1, T2, T3>::value)>
-KFR_INTRIN common_type<T1, T2, T3> exp_fmadd(const T1& x, const T2& y, const T3& z)
+KFR_INTRIN flt_type<common_type<T1, T2, T3>> exp_fmadd(const T1& x, const T2& y, const T3& z)
{
return intrinsics::exp_fmadd(x, y, z);
}
@@ -459,7 +429,7 @@ KFR_INTRIN internal::expression_function<fn::exp_fmadd, E1, E2, E3> exp_fmadd(E1
}
template <typename T1, typename T2, typename T3, KFR_ENABLE_IF(is_numeric_args<T1, T2, T3>::value)>
-KFR_INTRIN common_type<T1, T2, T3> log_fmadd(const T1& x, const T2& y, const T3& z)
+KFR_INTRIN flt_type<common_type<T1, T2, T3>> log_fmadd(const T1& x, const T2& y, const T3& z)
{
return intrinsics::log_fmadd(x, y, z);
}
@@ -471,7 +441,7 @@ KFR_INTRIN internal::expression_function<fn::log_fmadd, E1, E2, E3> log_fmadd(E1
}
template <typename T1, typename T2, KFR_ENABLE_IF(is_numeric_args<T1, T2>::value)>
-KFR_INTRIN common_type<T1, T2> pow(const T1& x, const T2& y)
+KFR_INTRIN flt_type<common_type<T1, T2>> pow(const T1& x, const T2& y)
{
return intrinsics::pow(x, y);
}
@@ -483,7 +453,7 @@ KFR_INTRIN internal::expression_function<fn::pow, E1, E2> pow(E1&& x, E2&& y)
}
template <typename T1, typename T2, KFR_ENABLE_IF(is_numeric_args<T1, T2>::value)>
-KFR_INTRIN common_type<T1, T2> root(const T1& x, const T2& y)
+KFR_INTRIN flt_type<common_type<T1, T2>> root(const T1& x, const T2& y)
{
return intrinsics::root(x, y);
}
@@ -495,7 +465,7 @@ KFR_INTRIN internal::expression_function<fn::root, E1, E2> root(E1&& x, E2&& y)
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 cbrt(const T1& x)
+KFR_INTRIN flt_type<T1> cbrt(const T1& x)
{
return intrinsics::cbrt(x);
}
diff --git a/include/kfr/base/min_max.hpp b/include/kfr/base/min_max.hpp
@@ -111,6 +111,8 @@ KFR_SINTRIN i16neon min(const i16neon& x, const i16neon& y) { return vminq_s16(*
KFR_SINTRIN u16neon min(const u16neon& x, const u16neon& y) { return vminq_u16(*x, *y); }
KFR_SINTRIN i32neon min(const i32neon& x, const i32neon& y) { return vminq_s32(*x, *y); }
KFR_SINTRIN u32neon min(const u32neon& x, const u32neon& y) { return vminq_u32(*x, *y); }
+KFR_SINTRIN i64neon min(const i64neon& x, const i64neon& y) { return select(x < y, x, y); }
+KFR_SINTRIN u64neon min(const u64neon& x, const u64neon& y) { return select(x < y, x, y); }
KFR_SINTRIN i8neon max(const i8neon& x, const i8neon& y) { return vmaxq_s8(*x, *y); }
KFR_SINTRIN u8neon max(const u8neon& x, const u8neon& y) { return vmaxq_u8(*x, *y); }
@@ -118,8 +120,8 @@ KFR_SINTRIN i16neon max(const i16neon& x, const i16neon& y) { return vmaxq_s16(*
KFR_SINTRIN u16neon max(const u16neon& x, const u16neon& y) { return vmaxq_u16(*x, *y); }
KFR_SINTRIN i32neon max(const i32neon& x, const i32neon& y) { return vmaxq_s32(*x, *y); }
KFR_SINTRIN u32neon max(const u32neon& x, const u32neon& y) { return vmaxq_u32(*x, *y); }
-KFR_SINTRIN i64neon min(const i64neon& x, const i64neon& y) { return select(x < y, x, y); }
-KFR_SINTRIN u64neon min(const u64neon& x, const u64neon& y) { return select(x < y, x, y); }
+KFR_SINTRIN i64neon max(const i64neon& x, const i64neon& y) { return select(x > y, x, y); }
+KFR_SINTRIN u64neon max(const u64neon& x, const u64neon& y) { return select(x > y, x, y); }
KFR_SINTRIN f32neon min(const f32neon& x, const f32neon& y) { return vminq_f32(*x, *y); }
KFR_SINTRIN f32neon max(const f32neon& x, const f32neon& y) { return vmaxq_f32(*x, *y); }
diff --git a/include/kfr/base/round.hpp b/include/kfr/base/round.hpp
@@ -92,25 +92,25 @@ template <size_t N>
KFR_SINTRIN vec<f32, N> floor(const vec<f32, N>& x)
{
vec<f32, N> t = cast<f32>(cast<i32>(x));
- return t - (bitcast<f32>(x < t) & 1.f);
+ return t - (tovec(x < t) & 1.f);
}
template <size_t N>
KFR_SINTRIN vec<f64, N> floor(const vec<f64, N>& x)
{
vec<f64, N> t = cast<f64>(cast<i64>(x));
- return t - (bitcast<f64>(x < t) & 1.0);
+ return t - (tovec(x < t) & 1.0);
}
template <size_t N>
KFR_SINTRIN vec<f32, N> ceil(const vec<f32, N>& x)
{
vec<f32, N> t = cast<f32>(cast<i32>(x));
- return t + (bitcast<f32>(x > t) & 1.f);
+ return t + (tovec(x > t) & 1.f);
}
template <size_t N>
KFR_SINTRIN vec<f64, N> ceil(const vec<f64, N>& x)
{
vec<f64, N> t = cast<f64>(cast<i64>(x));
- return t + (bitcast<f64>(x > t) & 1.0);
+ return t + (tovec(x > t) & 1.0);
}
template <size_t N>
KFR_SINTRIN vec<f32, N> round(const vec<f32, N>& x)
diff --git a/include/kfr/base/saturation.hpp b/include/kfr/base/saturation.hpp
@@ -111,21 +111,19 @@ KFR_SINTRIN u8neon satadd(const u8neon& x, const u8neon& y) { return vqaddq_u8(*
KFR_SINTRIN i8neon satadd(const i8neon& x, const i8neon& y) { return vqaddq_s8(*x, *y); }
KFR_SINTRIN u16neon satadd(const u16neon& x, const u16neon& y) { return vqaddq_u16(*x, *y); }
KFR_SINTRIN i16neon satadd(const i16neon& x, const i16neon& y) { return vqaddq_s16(*x, *y); }
-
-KFR_SINTRIN u8neon satsub(const u8neon& x, const u8neon& y) { return vqsubq_u8(*x, *y); }
-KFR_SINTRIN i8neon satsub(const i8neon& x, const i8neon& y) { return vqsubq_s8(*x, *y); }
-KFR_SINTRIN u16neon satsub(const u16neon& x, const u16neon& y) { return vqsubq_u16(*x, *y); }
-KFR_SINTRIN i16neon satsub(const i16neon& x, const i16neon& y) { return vqsubq_s16(*x, *y); }
-
KFR_SINTRIN u32neon satadd(const u32neon& a, const u32neon& b) { return vqaddq_u32(*a, *b); }
KFR_SINTRIN i32neon satadd(const i32neon& a, const i32neon& b) { return vqaddq_s32(*a, *b); }
KFR_SINTRIN u64neon satadd(const u64neon& a, const u64neon& b) { return vqaddq_u64(*a, *b); }
KFR_SINTRIN i64neon satadd(const i64neon& a, const i64neon& b) { return vqaddq_s64(*a, *b); }
-KFR_SINTRIN i32neon satsub(const i32neon& a, const i32neon& b) { return vqsubq_u32(*a, *b); }
-KFR_SINTRIN i64neon satsub(const i64neon& a, const i64neon& b) { return vqsubq_s32(*a, *b); }
-KFR_SINTRIN u32neon satsub(const u32neon& a, const u32neon& b) { return vqsubq_u64(*a, *b); }
-KFR_SINTRIN u64neon satsub(const u64neon& a, const u64neon& b) { return vqsubq_s64(*a, *b); }
+KFR_SINTRIN u8neon satsub(const u8neon& x, const u8neon& y) { return vqsubq_u8(*x, *y); }
+KFR_SINTRIN i8neon satsub(const i8neon& x, const i8neon& y) { return vqsubq_s8(*x, *y); }
+KFR_SINTRIN u16neon satsub(const u16neon& x, const u16neon& y) { return vqsubq_u16(*x, *y); }
+KFR_SINTRIN i16neon satsub(const i16neon& x, const i16neon& y) { return vqsubq_s16(*x, *y); }
+KFR_SINTRIN u32neon satsub(const u32neon& a, const u32neon& b) { return vqsubq_u32(*a, *b); }
+KFR_SINTRIN i32neon satsub(const i32neon& a, const i32neon& b) { return vqsubq_s32(*a, *b); }
+KFR_SINTRIN u64neon satsub(const u64neon& a, const u64neon& b) { return vqsubq_u64(*a, *b); }
+KFR_SINTRIN i64neon satsub(const i64neon& a, const i64neon& b) { return vqsubq_s64(*a, *b); }
KFR_HANDLE_ALL_SIZES_2(satadd)
KFR_HANDLE_ALL_SIZES_2(satsub)
diff --git a/include/kfr/base/sin_cos.hpp b/include/kfr/base/sin_cos.hpp
@@ -238,91 +238,91 @@ KFR_SINTRIN vec<T, N> sinc(const vec<T, N>& x)
return select(abs(x) <= c_epsilon<T>, T(1), sin(x) / x);
}
-template <typename T, size_t N, KFR_ENABLE_IF(!is_f_class<T>::value), typename Tout = ftype<T>>
+template <typename T, size_t N, KFR_ENABLE_IF(!is_f_class<T>::value), typename Tout = flt_type<T>>
KFR_SINTRIN vec<Tout, N> sin(const vec<T, N>& x)
{
return sin(cast<Tout>(x));
}
-template <typename T, size_t N, KFR_ENABLE_IF(!is_f_class<T>::value), typename Tout = ftype<T>>
+template <typename T, size_t N, KFR_ENABLE_IF(!is_f_class<T>::value), typename Tout = flt_type<T>>
KFR_SINTRIN vec<Tout, N> cos(const vec<T, N>& x)
{
return cos(cast<Tout>(x));
}
-template <typename T, size_t N, KFR_ENABLE_IF(!is_f_class<T>::value), typename Tout = ftype<T>>
+template <typename T, size_t N, KFR_ENABLE_IF(!is_f_class<T>::value), typename Tout = flt_type<T>>
KFR_SINTRIN vec<Tout, N> fastsin(const vec<T, N>& x)
{
return fastsin(cast<Tout>(x));
}
-template <typename T, size_t N, KFR_ENABLE_IF(!is_f_class<T>::value), typename Tout = ftype<T>>
+template <typename T, size_t N, KFR_ENABLE_IF(!is_f_class<T>::value), typename Tout = flt_type<T>>
KFR_SINTRIN vec<Tout, N> fastcos(const vec<T, N>& x)
{
return fastcos(cast<Tout>(x));
}
-template <typename T, size_t N, KFR_ENABLE_IF(!is_f_class<T>::value), typename Tout = ftype<T>>
+template <typename T, size_t N, KFR_ENABLE_IF(!is_f_class<T>::value), typename Tout = flt_type<T>>
KFR_SINTRIN vec<Tout, N> sincos(const vec<T, N>& x)
{
return sincos(cast<Tout>(x));
}
-template <typename T, size_t N, KFR_ENABLE_IF(!is_f_class<T>::value), typename Tout = ftype<T>>
+template <typename T, size_t N, KFR_ENABLE_IF(!is_f_class<T>::value), typename Tout = flt_type<T>>
KFR_SINTRIN vec<Tout, N> cossin(const vec<T, N>& x)
{
return cossin(cast<Tout>(x));
}
-template <typename T, size_t N, KFR_ENABLE_IF(!is_f_class<T>::value), typename Tout = ftype<T>>
+template <typename T, size_t N, KFR_ENABLE_IF(!is_f_class<T>::value), typename Tout = flt_type<T>>
KFR_SINTRIN vec<Tout, N> sinc(const vec<T, N>& x)
{
return sinc(cast<Tout>(x));
}
-template <typename T>
-KFR_SINTRIN T sindeg(const T& x)
+KFR_I_FLT_CONVERTER(sin)
+KFR_I_FLT_CONVERTER(cos)
+KFR_I_FLT_CONVERTER(fastsin)
+KFR_I_FLT_CONVERTER(fastcos)
+KFR_I_FLT_CONVERTER(sincos)
+KFR_I_FLT_CONVERTER(cossin)
+KFR_I_FLT_CONVERTER(sinc)
+
+template <typename T, typename Tout = flt_type<T>>
+KFR_SINTRIN Tout sindeg(const T& x)
{
- return sin(x * c_degtorad<T>);
+ return sin(x * c_degtorad<Tout>);
}
-template <typename T>
-KFR_SINTRIN T cosdeg(const T& x)
+template <typename T, typename Tout = flt_type<T>>
+KFR_SINTRIN Tout cosdeg(const T& x)
{
- return cos(x * c_degtorad<T>);
+ return cos(x * c_degtorad<Tout>);
}
-template <typename T>
-KFR_SINTRIN T fastsindeg(const T& x)
+template <typename T, typename Tout = flt_type<T>>
+KFR_SINTRIN Tout fastsindeg(const T& x)
{
- return fastsin(x * c_degtorad<T>);
+ return fastsin(x * c_degtorad<Tout>);
}
-template <typename T>
-KFR_SINTRIN T fastcosdeg(const T& x)
+template <typename T, typename Tout = flt_type<T>>
+KFR_SINTRIN Tout fastcosdeg(const T& x)
{
- return fastcos(x * c_degtorad<T>);
+ return fastcos(x * c_degtorad<Tout>);
}
-template <typename T>
-KFR_SINTRIN T sincosdeg(const T& x)
+template <typename T, typename Tout = flt_type<T>>
+KFR_SINTRIN Tout sincosdeg(const T& x)
{
- return sincos(x * c_degtorad<T>);
+ return sincos(x * c_degtorad<Tout>);
}
-template <typename T>
-KFR_SINTRIN T cossindeg(const T& x)
+template <typename T, typename Tout = flt_type<T>>
+KFR_SINTRIN Tout cossindeg(const T& x)
{
- return cossin(x * c_degtorad<T>);
+ return cossin(x * c_degtorad<Tout>);
}
-
-KFR_I_CONVERTER(sin)
-KFR_I_CONVERTER(cos)
-KFR_I_CONVERTER(fastsin)
-KFR_I_CONVERTER(fastcos)
-KFR_I_CONVERTER(sincos)
-KFR_I_CONVERTER(cossin)
-KFR_I_CONVERTER(sinc)
}
KFR_I_FN(sin)
@@ -331,10 +331,18 @@ KFR_I_FN(fastsin)
KFR_I_FN(fastcos)
KFR_I_FN(sincos)
KFR_I_FN(cossin)
+
+KFR_I_FN(sindeg)
+KFR_I_FN(cosdeg)
+KFR_I_FN(fastsindeg)
+KFR_I_FN(fastcosdeg)
+KFR_I_FN(sincosdeg)
+KFR_I_FN(cossindeg)
+
KFR_I_FN(sinc)
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN ftype<T1> sin(const T1& x)
+KFR_INTRIN flt_type<T1> sin(const T1& x)
{
return intrinsics::sin(x);
}
@@ -346,7 +354,7 @@ KFR_INTRIN internal::expression_function<fn::sin, E1> sin(E1&& x)
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN ftype<T1> cos(const T1& x)
+KFR_INTRIN flt_type<T1> cos(const T1& x)
{
return intrinsics::cos(x);
}
@@ -358,7 +366,7 @@ KFR_INTRIN internal::expression_function<fn::cos, E1> cos(E1&& x)
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN ftype<T1> fastsin(const T1& x)
+KFR_INTRIN flt_type<T1> fastsin(const T1& x)
{
return intrinsics::fastsin(x);
}
@@ -370,7 +378,7 @@ KFR_INTRIN internal::expression_function<fn::fastsin, E1> fastsin(E1&& x)
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN ftype<T1> fastcos(const T1& x)
+KFR_INTRIN flt_type<T1> fastcos(const T1& x)
{
return intrinsics::fastcos(x);
}
@@ -382,7 +390,7 @@ KFR_INTRIN internal::expression_function<fn::fastcos, E1> fastcos(E1&& x)
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN ftype<T1> sincos(const T1& x)
+KFR_INTRIN flt_type<T1> sincos(const T1& x)
{
return intrinsics::sincos(x);
}
@@ -394,7 +402,7 @@ KFR_INTRIN internal::expression_function<fn::sincos, E1> sincos(E1&& x)
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN ftype<T1> cossin(const T1& x)
+KFR_INTRIN flt_type<T1> cossin(const T1& x)
{
return intrinsics::cossin(x);
}
@@ -406,7 +414,79 @@ KFR_INTRIN internal::expression_function<fn::cossin, E1> cossin(E1&& x)
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN ftype<T1> sinc(const T1& x)
+KFR_INTRIN flt_type<T1> sindeg(const T1& x)
+{
+ return intrinsics::sindeg(x);
+}
+
+template <typename E1, KFR_ENABLE_IF(is_input_expression<E1>::value)>
+KFR_INTRIN internal::expression_function<fn::sindeg, E1> sindeg(E1&& x)
+{
+ return { fn::sindeg(), std::forward<E1>(x) };
+}
+
+template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
+KFR_INTRIN flt_type<T1> cosdeg(const T1& x)
+{
+ return intrinsics::cosdeg(x);
+}
+
+template <typename E1, KFR_ENABLE_IF(is_input_expression<E1>::value)>
+KFR_INTRIN internal::expression_function<fn::cosdeg, E1> cosdeg(E1&& x)
+{
+ return { fn::cosdeg(), std::forward<E1>(x) };
+}
+
+template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
+KFR_INTRIN flt_type<T1> fastsindeg(const T1& x)
+{
+ return intrinsics::fastsindeg(x);
+}
+
+template <typename E1, KFR_ENABLE_IF(is_input_expression<E1>::value)>
+KFR_INTRIN internal::expression_function<fn::fastsindeg, E1> fastsindeg(E1&& x)
+{
+ return { fn::fastsindeg(), std::forward<E1>(x) };
+}
+
+template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
+KFR_INTRIN flt_type<T1> fastcosdeg(const T1& x)
+{
+ return intrinsics::fastcosdeg(x);
+}
+
+template <typename E1, KFR_ENABLE_IF(is_input_expression<E1>::value)>
+KFR_INTRIN internal::expression_function<fn::fastcosdeg, E1> fastcosdeg(E1&& x)
+{
+ return { fn::fastcosdeg(), std::forward<E1>(x) };
+}
+
+template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
+KFR_INTRIN flt_type<T1> sincosdeg(const T1& x)
+{
+ return intrinsics::sincosdeg(x);
+}
+
+template <typename E1, KFR_ENABLE_IF(is_input_expression<E1>::value)>
+KFR_INTRIN internal::expression_function<fn::sincosdeg, E1> sincosdeg(E1&& x)
+{
+ return { fn::sincosdeg(), std::forward<E1>(x) };
+}
+
+template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
+KFR_INTRIN flt_type<T1> cossindeg(const T1& x)
+{
+ return intrinsics::cossindeg(x);
+}
+
+template <typename E1, KFR_ENABLE_IF(is_input_expression<E1>::value)>
+KFR_INTRIN internal::expression_function<fn::cossindeg, E1> cossindeg(E1&& x)
+{
+ return { fn::cossindeg(), std::forward<E1>(x) };
+}
+
+template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
+KFR_INTRIN flt_type<T1> sinc(const T1& x)
{
return intrinsics::sinc(x);
}
diff --git a/include/kfr/base/sqrt.hpp b/include/kfr/base/sqrt.hpp
@@ -53,10 +53,10 @@ KFR_HANDLE_ALL_SIZES_FLT_1(sqrt)
template <typename T, size_t N, typename Tout = flt_type<T>>
KFR_SINTRIN vec<Tout, N> sqrt(const vec<T, N>& x)
{
- return apply([](T x) { return std::sqrt(static_cast<Tout>(x)); }, x);
+ return apply([](Tout x) { return std::sqrt(x); }, cast<Tout>(x));
}
#endif
-KFR_I_CONVERTER(sqrt)
+KFR_I_FLT_CONVERTER(sqrt)
}
KFR_I_FN(sqrt)
diff --git a/include/kfr/base/tan.hpp b/include/kfr/base/tan.hpp
@@ -119,19 +119,19 @@ KFR_SINTRIN vec<f64, N> tan(const vec<f64, N>& x_full)
const vec<f64, N> z = select(inverse, val / -x, val * x);
return mulsign(z, x_full);
}
+
+KFR_I_FLT_CONVERTER(tan)
template <typename T>
-KFR_SINTRIN T tandeg(const T& x)
+KFR_SINTRIN flt_type<T> tandeg(const T& x)
{
- return tan(x * c_degtorad<T>);
+ return tan(x * c_degtorad<flt_type<T>>);
}
-
-KFR_I_CONVERTER(tan)
}
KFR_I_FN(tan)
KFR_I_FN(tandeg)
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 tan(const T1& x)
+KFR_INTRIN flt_type<T1> tan(const T1& x)
{
return intrinsics::tan(x);
}
@@ -143,7 +143,7 @@ KFR_INTRIN internal::expression_function<fn::tan, E1> tan(E1&& x)
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 tandeg(const T1& x)
+KFR_INTRIN flt_type<T1> tandeg(const T1& x)
{
return intrinsics::tandeg(x);
}
diff --git a/include/kfr/base/vec.hpp b/include/kfr/base/vec.hpp
@@ -611,8 +611,15 @@ constexpr CMT_INLINE vec<SubType, N> pack(const Arg& x, const Args&... rest)
}
KFR_FN(pack)
+namespace operators
+{
+struct empty
+{
+};
+}
+
template <typename T, size_t N>
-struct vec : vec_t<T, N>
+struct vec : vec_t<T, N>, operators::empty
{
static_assert(N > 0 && N <= 256, "Invalid vector size");
@@ -737,32 +744,6 @@ struct vec : vec_t<T, N>
KFR_ASGN_OP(>>=, >>)
#undef KFR_ASGN_OP
- template <typename U, typename C = common_type<U, T>>
- friend constexpr CMT_INLINE vec<C, N> operator+(const vec& x, const vec<U, N>& y)
- {
- return vec_op<C>::add(static_cast<vec<C, N>>(x).v, static_cast<vec<C, N>>(y).v);
- }
- template <typename U, typename C = common_type<U, T>>
- friend constexpr CMT_INLINE vec<C, N> operator-(const vec& x, const vec<U, N>& y)
- {
- return vec_op<C>::sub(static_cast<vec<C, N>>(x).v, static_cast<vec<C, N>>(y).v);
- }
- template <typename U, typename C = common_type<U, T>>
- friend constexpr CMT_INLINE vec<C, N> operator*(const vec& x, const vec<U, N>& y)
- {
- return vec_op<C>::mul(static_cast<vec<C, N>>(x).v, static_cast<vec<C, N>>(y).v);
- }
- template <typename U, typename C = common_type<U, T>>
- friend constexpr CMT_INLINE vec<C, N> operator/(const vec& x, const vec<U, N>& y)
- {
- return vec_op<C>::div(static_cast<vec<C, N>>(x).v, static_cast<vec<C, N>>(y).v);
- }
- template <typename U, typename C = common_type<U, T>>
- friend constexpr CMT_INLINE vec<C, N> operator%(const vec& x, const vec<U, N>& y)
- {
- return vec_op<C>::rem(static_cast<vec<C, N>>(x).v, static_cast<vec<C, N>>(y).v);
- }
-
constexpr CMT_INLINE simd_t operator*() const { return v; }
constexpr CMT_INLINE simd_t& operator*() { return v; }
CMT_INLINE mask<T, N>& asmask() { return ref_cast<mask<T, N>>(*this); }
@@ -811,6 +792,72 @@ private:
};
};
+namespace operators
+{
+template <typename T1, typename T2, size_t N, typename C = common_type<T1, T2>>
+constexpr CMT_INLINE vec<C, N> operator+(const vec<T1, N>& x, const T2& y)
+{
+ return vec_op<C>::add(*static_cast<vec<C, N>>(x), *static_cast<vec<C, N>>(y));
+}
+template <typename T1, typename T2, size_t N, typename C = common_type<T1, T2>>
+constexpr CMT_INLINE vec<C, N> operator-(const vec<T1, N>& x, const T2& y)
+{
+ return vec_op<C>::sub(*static_cast<vec<C, N>>(x), *static_cast<vec<C, N>>(y));
+}
+template <typename T1, typename T2, size_t N, typename C = common_type<T1, T2>>
+constexpr CMT_INLINE vec<C, N> operator*(const vec<T1, N>& x, const T2& y)
+{
+ return vec_op<C>::mul(*static_cast<vec<C, N>>(x), *static_cast<vec<C, N>>(y));
+}
+template <typename T1, typename T2, size_t N, typename C = common_type<T1, T2>>
+constexpr CMT_INLINE vec<C, N> operator/(const vec<T1, N>& x, const T2& y)
+{
+ return vec_op<C>::div(*static_cast<vec<C, N>>(x), *static_cast<vec<C, N>>(y));
+}
+
+template <typename T1, typename T2, size_t N, typename C = common_type<T1, T2>>
+constexpr CMT_INLINE vec<C, N> operator+(const T1& x, const vec<T2, N>& y)
+{
+ return vec_op<C>::add(*static_cast<vec<C, N>>(x), *static_cast<vec<C, N>>(y));
+}
+template <typename T1, typename T2, size_t N, typename C = common_type<T1, T2>>
+constexpr CMT_INLINE vec<C, N> operator-(const T1& x, const vec<T2, N>& y)
+{
+ return vec_op<C>::sub(*static_cast<vec<C, N>>(x), *static_cast<vec<C, N>>(y));
+}
+template <typename T1, typename T2, size_t N, typename C = common_type<T1, T2>>
+constexpr CMT_INLINE vec<C, N> operator*(const T1& x, const vec<T2, N>& y)
+{
+ return vec_op<C>::mul(*static_cast<vec<C, N>>(x), *static_cast<vec<C, N>>(y));
+}
+template <typename T1, typename T2, size_t N, typename C = common_type<T1, T2>>
+constexpr CMT_INLINE vec<C, N> operator/(const T1& x, const vec<T2, N>& y)
+{
+ return vec_op<C>::div(*static_cast<vec<C, N>>(x), *static_cast<vec<C, N>>(y));
+}
+
+template <typename T1, typename T2, size_t N, typename C = common_type<T1, T2>>
+constexpr CMT_INLINE vec<C, N> operator+(const vec<T1, N>& x, const vec<T2, N>& y)
+{
+ return vec_op<C>::add(*static_cast<vec<C, N>>(x), *static_cast<vec<C, N>>(y));
+}
+template <typename T1, typename T2, size_t N, typename C = common_type<T1, T2>>
+constexpr CMT_INLINE vec<C, N> operator-(const vec<T1, N>& x, const vec<T2, N>& y)
+{
+ return vec_op<C>::sub(*static_cast<vec<C, N>>(x), *static_cast<vec<C, N>>(y));
+}
+template <typename T1, typename T2, size_t N, typename C = common_type<T1, T2>>
+constexpr CMT_INLINE vec<C, N> operator*(const vec<T1, N>& x, const vec<T2, N>& y)
+{
+ return vec_op<C>::mul(*static_cast<vec<C, N>>(x), *static_cast<vec<C, N>>(y));
+}
+template <typename T1, typename T2, size_t N, typename C = common_type<T1, T2>>
+constexpr CMT_INLINE vec<C, N> operator/(const vec<T1, N>& x, const vec<T2, N>& y)
+{
+ return vec_op<C>::div(*static_cast<vec<C, N>>(x), *static_cast<vec<C, N>>(y));
+}
+}
+
template <typename T, size_t N>
struct mask : public vec<T, N>
{
@@ -1252,10 +1299,15 @@ constexpr CMT_INLINE vec<T, N> apply(Fn&& fn)
}
template <typename T, int N>
-CMT_INLINE vec<T, N> tovec(simd<T, N> x)
+CMT_INLINE vec<T, N> tovec(const simd<T, N>& x)
{
return x;
}
+template <typename T, size_t N>
+CMT_INLINE vec<T, N> tovec(const mask<T, N>& x)
+{
+ return *x;
+}
#ifdef CMT_ARCH_SSE2
CMT_INLINE f32x4 tovec(__m128 x) { return f32x4(x); }
@@ -1443,6 +1495,16 @@ struct common_type<kfr::vec<T1, N>, kfr::vec<T2, N>>
{
using type = kfr::vec<typename common_type<T1, T2>::type, N>;
};
+template <typename T1, typename T2, size_t N>
+struct common_type<kfr::vec<T1, N>, T2>
+{
+ using type = kfr::vec<typename common_type<T1, T2>::type, N>;
+};
+template <typename T1, typename T2, size_t N>
+struct common_type<T1, kfr::vec<T2, N>>
+{
+ using type = kfr::vec<typename common_type<T1, T2>::type, N>;
+};
template <typename T1, typename T2, size_t N>
struct common_type<kfr::mask<T1, N>, kfr::mask<T2, N>>
diff --git a/include/kfr/cometa.hpp b/include/kfr/cometa.hpp
@@ -198,8 +198,15 @@ struct compound_type_traits<std::pair<T, T>>
}
};
+namespace ops
+{
+struct empty
+{
+};
+}
+
template <typename T, T val>
-struct cval_t
+struct cval_t : ops::empty
{
constexpr static T value = val;
constexpr cval_t() noexcept = default;
@@ -337,7 +344,7 @@ struct get_nth_type<index>
}
template <typename T, T... values>
-struct cvals_t
+struct cvals_t : ops::empty
{
using type = cvals_t<T, values...>;
constexpr static size_t size() { return sizeof...(values); }
@@ -371,7 +378,7 @@ struct cvals_t
};
template <typename T>
-struct cvals_t<T>
+struct cvals_t<T> : ops::empty
{
using type = cvals_t<T>;
constexpr static size_t size() { return 0; }
@@ -591,7 +598,8 @@ constexpr inline Ret cfilter(cvals_t<T, vals...>, cvals_t<bool, flags...>)
{ \
return Ret{}; \
}
-
+namespace ops
+{
// clang-format off
CMT_UN_OP(-)
CMT_UN_OP(+)
@@ -617,6 +625,7 @@ CMT_BIN_OP(&)
CMT_BIN_OP(|)
CMT_BIN_OP(^)
// clang-format on
+}
namespace details
{
diff --git a/include/kfr/dsp/units.hpp b/include/kfr/dsp/units.hpp
@@ -38,28 +38,28 @@ using sample_rate_t = double;
namespace intrinsics
{
-template <typename T, typename TF = ftype<T>>
+template <typename T, typename TF = flt_type<T>>
KFR_SINTRIN TF amp_to_dB(T amp)
{
return log(static_cast<TF>(amp)) * subtype<TF>(8.6858896380650365530225783783322);
// return T( 20.0 ) * log10( level );
}
-template <typename T, typename TF = ftype<T>>
+template <typename T, typename TF = flt_type<T>>
KFR_SINTRIN TF dB_to_amp(T dB)
{
return exp(dB * subtype<TF>(0.11512925464970228420089957273422));
// return exp10( dB / 20 );
}
-template <typename T, typename TF = ftype<T>>
+template <typename T, typename TF = flt_type<T>>
KFR_SINTRIN TF amp_to_dB(T amp, T offset)
{
return log_fmadd(amp, subtype<TF>(8.6858896380650365530225783783322), offset);
// return T( 20.0 ) * log10( level );
}
-template <typename T, typename TF = ftype<T>>
+template <typename T, typename TF = flt_type<T>>
KFR_SINTRIN TF dB_to_amp(T dB, T offset)
{
auto offs = -subtype<TF>(0.11512925464970228420089957273422) * offset;
@@ -67,51 +67,51 @@ KFR_SINTRIN TF dB_to_amp(T dB, T offset)
// return exp10( dB / 20 );
}
-template <typename T>
-KFR_SINTRIN T power_to_dB(T x)
+template <typename T, typename Tout = flt_type<T>>
+KFR_SINTRIN Tout power_to_dB(T x)
{
- return log(x) * (10 * c_recip_log_10<T>);
+ return log(x) * (10 * c_recip_log_10<Tout>);
}
-template <typename T>
-KFR_SINTRIN T dB_to_power(T x)
+template <typename T, typename Tout = flt_type<T>>
+KFR_SINTRIN Tout dB_to_power(T x)
{
- if (x == -c_infinity<T>)
+ if (x == -c_infinity<Tout>)
return 0.0;
else
- return exp(x * (c_log_10<T> / 10.0));
+ return exp(x * (c_log_10<Tout> / 10.0));
}
-template <typename T, typename TF = ftype<T>>
+template <typename T, typename TF = flt_type<T>>
KFR_SINTRIN TF note_to_hertz(T note)
{
const subtype<TF> offset = 2.1011784386926213177653145771814;
- return exp_fmadd(note, subtype<TF>(0.05776226504666210911810267678818), offset);
+ return intrinsics::exp_fmadd(note, subtype<TF>(0.05776226504666210911810267678818), offset);
}
-template <typename T, typename TF = ftype<T>>
+template <typename T, typename TF = flt_type<T>>
KFR_SINTRIN TF hertz_to_note(T hertz)
{
const subtype<TF> offset = -36.376316562295915248836189714583;
- return log_fmadd(hertz, subtype<TF>(17.312340490667560888319096172023), offset);
+ return intrinsics::log_fmadd(hertz, subtype<TF>(17.312340490667560888319096172023), offset);
}
-template <typename T1, typename T2, typename T3, typename Tc = common_type<T1, T2, T3, f32>>
+template <typename T1, typename T2, typename T3, typename Tc = flt_type<common_type<T1, T2, T3, f32>>>
KFR_SINTRIN Tc note_to_hertz(T1 note, T2 tunenote, T3 tunehertz)
{
const Tc offset = log(tunehertz) - tunenote * subtype<Tc>(0.05776226504666210911810267678818);
- return exp_fmadd(note, subtype<Tc>(0.05776226504666210911810267678818), offset);
+ return intrinsics::exp_fmadd(note, subtype<Tc>(0.05776226504666210911810267678818), offset);
}
-template <typename T1, typename T2, typename T3, typename Tc = common_type<T1, T2, T3, f32>>
+template <typename T1, typename T2, typename T3, typename Tc = flt_type<common_type<T1, T2, T3, f32>>>
KFR_SINTRIN Tc hertz_to_note(T1 hertz, T2 tunenote, T3 tunehertz)
{
const Tc offset = tunenote - log(tunehertz) * subtype<Tc>(17.312340490667560888319096172023);
- return log_fmadd(hertz, subtype<Tc>(17.312340490667560888319096172023), offset);
+ return intrinsics::log_fmadd(hertz, subtype<Tc>(17.312340490667560888319096172023), offset);
}
}
KFR_I_FN(note_to_hertz)
@@ -122,7 +122,7 @@ KFR_I_FN(power_to_dB)
KFR_I_FN(dB_to_power)
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 note_to_hertz(const T1& x)
+KFR_INTRIN flt_type<T1> note_to_hertz(const T1& x)
{
return intrinsics::note_to_hertz(x);
}
@@ -134,7 +134,7 @@ KFR_INTRIN internal::expression_function<fn::note_to_hertz, E1> note_to_hertz(E1
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 hertz_to_note(const T1& x)
+KFR_INTRIN flt_type<T1> hertz_to_note(const T1& x)
{
return intrinsics::hertz_to_note(x);
}
@@ -146,7 +146,7 @@ KFR_INTRIN internal::expression_function<fn::hertz_to_note, E1> hertz_to_note(E1
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 amp_to_dB(const T1& x)
+KFR_INTRIN flt_type<T1> amp_to_dB(const T1& x)
{
return intrinsics::amp_to_dB(x);
}
@@ -158,7 +158,7 @@ KFR_INTRIN internal::expression_function<fn::amp_to_dB, E1> amp_to_dB(E1&& x)
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 dB_to_amp(const T1& x)
+KFR_INTRIN flt_type<T1> dB_to_amp(const T1& x)
{
return intrinsics::dB_to_amp(x);
}
@@ -170,7 +170,7 @@ KFR_INTRIN internal::expression_function<fn::dB_to_amp, E1> dB_to_amp(E1&& x)
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 power_to_dB(const T1& x)
+KFR_INTRIN flt_type<T1> power_to_dB(const T1& x)
{
return intrinsics::power_to_dB(x);
}
@@ -182,7 +182,7 @@ KFR_INTRIN internal::expression_function<fn::power_to_dB, E1> power_to_dB(E1&& x
}
template <typename T1, KFR_ENABLE_IF(is_numeric<T1>::value)>
-KFR_INTRIN T1 dB_to_power(const T1& x)
+KFR_INTRIN flt_type<T1> dB_to_power(const T1& x)
{
return intrinsics::dB_to_power(x);
}
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
@@ -63,29 +63,38 @@ add_executable(complex_test complex_test.cpp ${KFR_SRC})
add_executable(vec_test vec_test.cpp ${KFR_SRC})
add_executable(stat_test stat_test.cpp ${KFR_SRC})
+if (ARM)
+ find_program(EMULATOR "qemu-arm")
+else ()
+ set(EMULATOR "")
+endif ()
+
if (NOT IOS)
enable_testing()
add_test(NAME basic_vector_test
- COMMAND ${PROJECT_BINARY_DIR}/tests/basic_vector_test)
+ COMMAND ${EMULATOR} ${PROJECT_BINARY_DIR}/tests/basic_vector_test)
add_test(NAME intrinsic_test
- COMMAND ${PROJECT_BINARY_DIR}/tests/intrinsic_test)
+ COMMAND ${EMULATOR} ${PROJECT_BINARY_DIR}/tests/intrinsic_test)
add_test(NAME fracdelay_test
- COMMAND ${PROJECT_BINARY_DIR}/tests/fracdelay_test)
+ COMMAND ${EMULATOR} ${PROJECT_BINARY_DIR}/tests/fracdelay_test)
add_test(NAME conv_test
- COMMAND ${PROJECT_BINARY_DIR}/tests/conv_test)
+ COMMAND ${EMULATOR} ${PROJECT_BINARY_DIR}/tests/conv_test)
if (MPFR_FOUND)
add_test(NAME transcendental_test
- COMMAND ${PROJECT_BINARY_DIR}/tests/transcendental_test)
+ COMMAND ${EMULATOR} ${PROJECT_BINARY_DIR}/tests/transcendental_test)
endif ()
add_test(NAME complex_test
- COMMAND ${PROJECT_BINARY_DIR}/tests/complex_test)
+ COMMAND ${EMULATOR} ${PROJECT_BINARY_DIR}/tests/complex_test)
add_test(NAME vec_test
- COMMAND ${PROJECT_BINARY_DIR}/tests/vec_test)
+ COMMAND ${EMULATOR} ${PROJECT_BINARY_DIR}/tests/vec_test)
add_test(NAME stat_test
- COMMAND ${PROJECT_BINARY_DIR}/tests/stat_test)
- add_test(NAME multiarch
- COMMAND ${PROJECT_BINARY_DIR}/tests/multiarch)
+ COMMAND ${EMULATOR} ${PROJECT_BINARY_DIR}/tests/stat_test)
+
+ if (NOT ARM)
+ add_test(NAME multiarch
+ COMMAND ${EMULATOR} ${PROJECT_BINARY_DIR}/tests/multiarch)
+ endif ()
add_test(NAME dft_test
- COMMAND ${PROJECT_BINARY_DIR}/tests/dft_test)
+ COMMAND ${EMULATOR} ${PROJECT_BINARY_DIR}/tests/dft_test)
endif ()
diff --git a/tests/intrinsic_test.cpp b/tests/intrinsic_test.cpp
@@ -159,10 +159,12 @@ TEST(intrin_abs)
TEST(intrin_sqrt)
{
testo::assert_is_same<decltype(kfr::sqrt(9)), fbase>();
+ testo::assert_is_same<decltype(kfr::intrinsics::sqrt(9)), fbase>();
testo::assert_is_same<decltype(kfr::sqrt(make_vector(9))), vec<fbase, 1>>();
testo::assert_is_same<decltype(kfr::sqrt(make_vector(9, 25))), vec<fbase, 2>>();
- CHECK(kfr::sqrt(9) == 3.0);
- CHECK(kfr::sqrt(-9) == qnan);
+ CHECK(kfr::sqrt(9) == fbase(3.0));
+ CHECK(kfr::sqrt(2) == fbase(1.4142135623730950488));
+ CHECK(kfr::sqrt(-9) == fbase(qnan));
CHECK(kfr::sqrt(make_vector(9)) == make_vector<fbase>(3.0));
CHECK(kfr::sqrt(make_vector(-9)) == make_vector<fbase>(qnan));
testo::matrix(named("type") = float_types, named("value") = std::vector<int>{ 0, 2, 65536 },
diff --git a/tests/vec_test.cpp b/tests/vec_test.cpp
@@ -7,7 +7,7 @@
#include <kfr/io/tostring.hpp>
#include "testo/testo.hpp"
-#include <kfr/dsp/mixdown.hpp>
+#include <kfr/dsp.hpp>
#include <kfr/math.hpp>
using namespace kfr;
@@ -120,17 +120,85 @@ TEST(vec_conv)
testo::assert_is_same<common_type<i32, f32>, f32>();
testo::assert_is_same<common_type<f32, f64>, f64>();
testo::assert_is_same<common_type<i32, f32x4>, f32x4>();
- testo::assert_is_same<common_type<f32x4, f64>, f32x4>();
+ testo::assert_is_same<common_type<f32x4, f64>, f64x4>();
+ testo::assert_is_same<common_type<f64, f32x4>, f64x4>();
testo::assert_is_same<common_type<f32x4, f64x4>, f64x4>();
testo::assert_is_same<decltype(min(1, 2)), int>();
testo::assert_is_same<decltype(min(1, 2u)), unsigned int>();
testo::assert_is_same<decltype(min(1, 2)), int>();
- testo::assert_is_same<decltype(min(pack(1), 2u)), i32x1>();
- testo::assert_is_same<decltype(min(2u, pack(1))), i32x1>();
+ testo::assert_is_same<decltype(min(pack(1), 2u)), u32x1>();
+ testo::assert_is_same<decltype(min(2u, pack(1))), u32x1>();
testo::assert_is_same<decltype(min(pack(1), pack(2u))), u32x1>();
testo::assert_is_same<decltype(min(pack(1, 2, 3), pack(1.0, 2.0, 3.0))), f64x3>();
testo::assert_is_same<decltype(min(pack(1.0, 2.0, 3.0), pack(1, 2, 3))), f64x3>();
+
+ testo::assert_is_same<decltype(pack(11) * pack(0.5)), f64x1>();
+ testo::assert_is_same<decltype(pack(11) * 0.5), f64x1>();
+
+ testo::assert_is_same<decltype(kfr::sin(2)), fbase>();
+ testo::assert_is_same<decltype(kfr::sin(pack(2))), vec<fbase, 1>>();
+ testo::assert_is_same<decltype(kfr::sindeg(2)), fbase>();
+ testo::assert_is_same<decltype(kfr::sindeg(pack(2))), vec<fbase, 1>>();
+
+ CHECK(pack(11) * pack(0.5) == 5.5);
+ CHECK(pack(11) * 0.5 == 5.5);
+ CHECK(kfr::sin(2) == fbase(0.90929742682568169539601986591174));
+ CHECK(kfr::sin(pack(2)) == pack(fbase(0.90929742682568169539601986591174)));
+ CHECK(kfr::sindeg(2) == fbase(0.03489949670250097164599518162533));
+ CHECK(kfr::sindeg(pack(2)) == pack(fbase(0.03489949670250097164599518162533)));
+ CHECK(kfr::cos(2) == fbase(-0.41614683654714238699756822950076));
+ CHECK(kfr::cos(pack(2)) == pack(fbase(-0.41614683654714238699756822950076)));
+ CHECK(kfr::cosdeg(2) == fbase(0.99939082701909573000624344004393));
+ CHECK(kfr::cosdeg(pack(2)) == pack(fbase(0.99939082701909573000624344004393)));
+
+ CHECK(kfr::log(2) == fbase(0.6931471805599453));
+ CHECK(kfr::log(pack(2)) == pack(fbase(0.6931471805599453)));
+ CHECK(kfr::log2(2) == fbase(1.0));
+ CHECK(kfr::log2(pack(2)) == pack(fbase(1.0)));
+ CHECK(kfr::log10(2) == fbase(0.30102999566398119521373889472449));
+ CHECK(kfr::log10(pack(2)) == pack(fbase(0.30102999566398119521373889472449)));
+
+ CHECK(kfr::exp(2) == fbase(7.3890560989306502));
+ CHECK(kfr::exp(pack(2)) == pack(fbase(7.3890560989306502)));
+ CHECK(kfr::exp2(2) == fbase(4.0));
+ CHECK(kfr::exp2(pack(2)) == pack(fbase(4.0)));
+
+ CHECK(kfr::logn(2, 10) == fbase(0.30102999566398119521373889472449));
+ CHECK(kfr::logn(pack(2), pack(10)) == pack(fbase(0.30102999566398119521373889472449)));
+
+ CHECK(kfr::pow(2, fbase(0.9)) == fbase(1.8660659830736148319626865322999));
+ CHECK(kfr::pow(pack(2), pack(fbase(0.9))) == pack(fbase(1.8660659830736148319626865322999)));
+
+ CHECK(kfr::root(fbase(1.5), 2) == fbase(1.2247448713915890490986420373529));
+ CHECK(kfr::root(pack(fbase(1.5)), pack(2)) == pack(fbase(1.2247448713915890490986420373529)));
+
+ testo::epsilon<float>() *= 10.0;
+ testo::epsilon<double>() *= 10.0;
+
+ CHECK(kfr::sinh(2) == fbase(3.6268604078470187676682139828013));
+ CHECK(kfr::sinh(pack(2)) == pack(fbase(3.6268604078470187676682139828013)));
+ CHECK(kfr::cosh(2) == fbase(3.7621956910836314595622134777737));
+ CHECK(kfr::cosh(pack(2)) == pack(fbase(3.7621956910836314595622134777737)));
+
+ CHECK(kfr::tanh(2) == fbase(0.96402758007581688394641372410092));
+ CHECK(kfr::tanh(pack(2)) == pack(fbase(0.96402758007581688394641372410092)));
+ CHECK(kfr::coth(2) == fbase(1.0373147207275480958778097647678));
+ CHECK(kfr::coth(pack(2)) == pack(fbase(1.0373147207275480958778097647678)));
+
+ testo::epsilon<float>() *= 10.0;
+ testo::epsilon<double>() *= 10.0;
+
+ CHECK(kfr::tan(2) == fbase(-2.1850398632615189916433061023137));
+ CHECK(kfr::tan(pack(2)) == pack(fbase(-2.1850398632615189916433061023137)));
+ CHECK(kfr::tandeg(2) == fbase(0.03492076949174773050040262577373));
+ CHECK(kfr::tandeg(pack(2)) == pack(fbase(0.03492076949174773050040262577373)));
+
+ testo::epsilon<float>() *= 10.0;
+ testo::epsilon<double>() *= 10.0;
+
+ CHECK(kfr::note_to_hertz(60) == fbase(261.6255653005986346778499935233));
+ CHECK(kfr::note_to_hertz(pack(60)) == pack(fbase(261.6255653005986346778499935233)));
}
TEST(vec_matrix)