commit 13b58742840635285159dc077dccd4f2a9b07ea9
parent 89e11ed30d1a6984bfe73dbd773879b1c6c31d47
Author: d.levin256@gmail.com <d.levin256@gmail.com>
Date: Tue, 26 Jul 2016 19:36:43 +0300
Add intrinsic_test
Diffstat:
2 files changed, 262 insertions(+), 0 deletions(-)
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
@@ -28,6 +28,7 @@ endif ()
include_directories(../include)
add_executable(basic_vector_test basic_vector_test.cpp ${KFR_SRC})
+add_executable(intrinsic_test intrinsic_test.cpp ${KFR_SRC})
add_executable(dft_test dft_test.cpp ${KFR_SRC})
add_executable(conv_test conv_test.cpp ${KFR_SRC})
add_executable(fracdelay_test fracdelay_test.cpp ${KFR_SRC})
@@ -40,6 +41,8 @@ enable_testing()
add_test(NAME basic_vector_test
COMMAND ${PROJECT_BINARY_DIR}/tests/basic_vector_test)
+add_test(NAME intrinsic_test
+ COMMAND ${PROJECT_BINARY_DIR}/tests/intrinsic_test)
add_test(NAME fracdelay_test
COMMAND ${PROJECT_BINARY_DIR}/tests/fracdelay_test)
add_test(NAME conv_test
diff --git a/tests/intrinsic_test.cpp b/tests/intrinsic_test.cpp
@@ -0,0 +1,259 @@
+/**
+ * KFR (http://kfrlib.com)
+ * Copyright (C) 2016 D Levin
+ * See LICENSE.txt for details
+ */
+
+#include <kfr/io/tostring.hpp>
+
+#include "testo/testo.hpp"
+#include <kfr/math.hpp>
+#include <kfr/vec.hpp>
+
+using namespace kfr;
+
+template <typename Fn>
+void test_intrinsic(Fn&& fn)
+{
+}
+
+constexpr ctypes_t<i8x1, i16x1, i32x1, i64x1, //
+ i8x2, i16x2, i32x2, i64x2, //
+ i8x4, i16x4, i32x4, i64x4, //
+ i8x8, i16x8, i32x8, i64x8, //
+ i8x16, i16x16, i32x16, i64x16, //
+ i8x3, i16x3, i32x3, i64x3 //
+ >
+ signed_types{};
+
+constexpr ctypes_t<u8x1, u16x1, u32x1, u64x1, //
+ u8x2, u16x2, u32x2, u64x2, //
+ u8x4, u16x4, u32x4, u64x4, //
+ u8x8, u16x8, u32x8, u64x8, //
+ u8x16, u16x16, u32x16, u64x16, //
+ u8x3, u16x3, u32x3, u64x3 //
+ >
+ unsigned_types{};
+
+constexpr ctypes_t<f32x1, f64x1, //
+ f32x2, f64x2, //
+ f32x4, f64x4, //
+ f32x8, f64x8, //
+ f32x16, f64x16, //
+ f32x3, f64x3 //
+ >
+ float_types{};
+
+constexpr ctypes_t<u8x1, i8x1, u16x1, i16x1, u32x1, i32x1, u64x1, i64x1, f32x1, f64x1, //
+ u8x2, i8x2, u16x2, i16x2, u32x2, i32x2, u64x2, i64x2, f32x2, f64x2, //
+ u8x4, i8x4, u16x4, i16x4, u32x4, i32x4, u64x4, i64x4, f32x4, f64x4, //
+ u8x8, i8x8, u16x8, i16x8, u32x8, i32x8, u64x8, i64x8, f32x8, f64x8, //
+ u8x16, i8x16, u16x16, i16x16, u32x16, i32x16, u64x16, i64x16, f32x16, f64x16, //
+ u8x3, i8x3, u16x3, i16x3, u32x3, i32x3, u64x3, i64x3, f32x3, f64x3 //
+ >
+ all_types{};
+
+template <typename T>
+inline T ref_abs(T x)
+{
+ return x >= T(0) ? x : -x;
+}
+
+template <typename T>
+inline T ref_satadd(T x, T y)
+{
+ T result;
+ if (__builtin_add_overflow(x, y, &result))
+ return x < 0 ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
+ else
+ return result;
+}
+
+template <typename T>
+inline T ref_satsub(T x, T y)
+{
+ T result;
+ if (__builtin_sub_overflow(x, y, &result))
+ return x < y ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
+ else
+ return result;
+}
+
+TEST(intrin_abs)
+{
+ testo::assert_is_same<decltype(kfr::abs(1)), int>();
+ testo::assert_is_same<decltype(kfr::abs(1u)), unsigned int>();
+ testo::assert_is_same<decltype(kfr::abs(make_vector(1))), i32x1>();
+ testo::assert_is_same<decltype(kfr::abs(make_vector(1, 2))), i32x2>();
+ CHECK(kfr::abs(9u) == 9u);
+ CHECK(kfr::abs(9) == 9);
+ CHECK(kfr::abs(-9) == 9);
+ CHECK(kfr::abs(-infinity) == infinity);
+ CHECK(kfr::abs(make_vector(9)) == make_vector(9));
+ CHECK(kfr::abs(make_vector(-9)) == make_vector(9));
+
+ testo::matrix(named("type") = signed_types, named("value") = std::vector<int>{ -1, 0, +1 },
+ [](auto type, int value) {
+ using T = type_of<decltype(type)>;
+ using Tsub = subtype<T>;
+ const T x(value);
+ CHECK(kfr::abs(x) == apply([](auto x) { return ref_abs(x); }, x));
+ });
+ testo::matrix(named("type") = float_types, named("value") = std::vector<int>{ -1, 0, +1 },
+ [](auto type, int value) {
+ using T = type_of<decltype(type)>;
+ using Tsub = subtype<T>;
+ const T x(value);
+ CHECK(kfr::abs(x) == apply([](auto x) { return Tsub(std::abs(x)); }, x));
+ });
+}
+
+TEST(intrin_sqrt)
+{
+ testo::assert_is_same<decltype(kfr::sqrt(9)), double>();
+ testo::assert_is_same<decltype(kfr::sqrt(make_vector(9))), f64x1>();
+ testo::assert_is_same<decltype(kfr::sqrt(make_vector(9, 25))), f64x2>();
+ CHECK(kfr::sqrt(9) == 3.0);
+ CHECK(kfr::sqrt(-9) == qnan);
+ CHECK(kfr::sqrt(make_vector(9)) == make_vector(3.0));
+ CHECK(kfr::sqrt(make_vector(-9)) == make_vector(qnan));
+ testo::matrix(named("type") = float_types, named("value") = std::vector<int>{ 0, 2, 65536 },
+ [](auto type, int value) {
+ using T = type_of<decltype(type)>;
+ using Tsub = subtype<T>;
+ const T x(value);
+ CHECK(kfr::sqrt(x) == apply([](auto x) { return std::sqrt(x); }, x));
+ });
+}
+
+TEST(intrin_round)
+{
+ testo::assert_is_same<decltype(kfr::floor(100)), int>();
+ testo::assert_is_same<decltype(kfr::ceil(100)), int>();
+ testo::assert_is_same<decltype(kfr::round(100)), int>();
+ testo::assert_is_same<decltype(kfr::trunc(100)), int>();
+ testo::assert_is_same<decltype(kfr::fract(100)), int>();
+ CHECK(kfr::floor(100) == 100);
+ CHECK(kfr::ceil(100) == 100);
+ CHECK(kfr::round(100) == 100);
+ CHECK(kfr::trunc(100) == 100);
+ CHECK(kfr::fract(100) == 0);
+
+ testo::matrix(named("type") = float_types,
+ named("value") = std::vector<double>{ -1.51, -1.49, 0.0, +1.49, +1.51 },
+ [](auto type, double value) {
+ using T = type_of<decltype(type)>;
+ using Tsub = subtype<T>;
+ const T x(value);
+ CHECK(kfr::floor(x) == apply([](auto x) { return std::floor(x); }, x));
+ CHECK(kfr::ceil(x) == apply([](auto x) { return std::ceil(x); }, x));
+ CHECK(kfr::round(x) == apply([](auto x) { return std::round(x); }, x));
+ CHECK(kfr::trunc(x) == apply([](auto x) { return std::trunc(x); }, x));
+ CHECK(kfr::fract(x) == apply([](auto x) { return x - std::floor(x); }, x));
+ });
+}
+
+TEST(intrin_min_max)
+{
+ testo::matrix(named("type") = float_types,
+ named("value") =
+ std::vector<std::pair<double, double>>{ { -100, +100 }, { infinity, 0.0 } },
+ [](auto type, std::pair<double, double> value) {
+ using T = type_of<decltype(type)>;
+ using Tsub = subtype<T>;
+ const T x(value.first);
+ const T y(value.second);
+ CHECK(kfr::min(x, y) == apply([](auto x, auto y) { return std::min(x, y); }, x, y));
+ CHECK(kfr::max(x, y) == apply([](auto x, auto y) { return std::max(x, y); }, x, y));
+ CHECK(kfr::absmin(x, y) ==
+ apply([](auto x, auto y) { return std::min(ref_abs(x), ref_abs(y)); }, x, y));
+ CHECK(kfr::absmax(x, y) ==
+ apply([](auto x, auto y) { return std::max(ref_abs(x), ref_abs(y)); }, x, y));
+ });
+ testo::matrix(named("type") = signed_types,
+ named("value") = std::vector<std::pair<int, int>>{ { -100, +100 } },
+ [](auto type, std::pair<int, int> value) {
+ using T = type_of<decltype(type)>;
+ using Tsub = subtype<T>;
+ const T x(value.first);
+ const T y(value.second);
+ CHECK(kfr::min(x, y) == apply([](auto x, auto y) { return std::min(x, y); }, x, y));
+ CHECK(kfr::max(x, y) == apply([](auto x, auto y) { return std::max(x, y); }, x, y));
+ CHECK(kfr::absmin(x, y) ==
+ apply([](auto x, auto y) { return std::min(ref_abs(x), ref_abs(y)); }, x, y));
+ CHECK(kfr::absmax(x, y) ==
+ apply([](auto x, auto y) { return std::max(ref_abs(x), ref_abs(y)); }, x, y));
+ });
+ testo::matrix(named("type") = unsigned_types,
+ named("value") = std::vector<std::pair<unsigned, unsigned>>{ { 0, +200 } },
+ [](auto type, std::pair<unsigned, unsigned> value) {
+ using T = type_of<decltype(type)>;
+ using Tsub = subtype<T>;
+ const T x(value.first);
+ const T y(value.second);
+ CHECK(kfr::min(x, y) == apply([](auto x, auto y) { return std::min(x, y); }, x, y));
+ CHECK(kfr::max(x, y) == apply([](auto x, auto y) { return std::max(x, y); }, x, y));
+ CHECK(kfr::absmin(x, y) ==
+ apply([](auto x, auto y) { return std::min(ref_abs(x), ref_abs(y)); }, x, y));
+ CHECK(kfr::absmax(x, y) ==
+ apply([](auto x, auto y) { return std::max(ref_abs(x), ref_abs(y)); }, x, y));
+ });
+}
+
+TEST(intrin_satadd_satsub)
+{
+ testo::matrix(named("type") = signed_types, [](auto type) {
+ using T = type_of<decltype(type)>;
+ using Tsub = subtype<T>;
+ const T min = std::numeric_limits<Tsub>::min();
+ const T max = std::numeric_limits<Tsub>::max();
+ CHECK(kfr::satadd(min, min) == apply([](auto x, auto y) { return ref_satadd(x, y); }, min, min));
+ CHECK(kfr::satadd(max, max) == apply([](auto x, auto y) { return ref_satadd(x, y); }, max, max));
+ CHECK(kfr::satadd(min, max) == apply([](auto x, auto y) { return ref_satadd(x, y); }, min, max));
+ CHECK(kfr::satadd(max, min) == apply([](auto x, auto y) { return ref_satadd(x, y); }, max, min));
+
+ CHECK(kfr::satsub(min, min) == apply([](auto x, auto y) { return ref_satsub(x, y); }, min, min));
+ CHECK(kfr::satsub(max, max) == apply([](auto x, auto y) { return ref_satsub(x, y); }, max, max));
+ CHECK(kfr::satsub(min, max) == apply([](auto x, auto y) { return ref_satsub(x, y); }, min, max));
+ CHECK(kfr::satsub(max, min) == apply([](auto x, auto y) { return ref_satsub(x, y); }, max, min));
+ });
+
+ testo::matrix(named("type") = unsigned_types, [](auto type) {
+ using T = type_of<decltype(type)>;
+ using Tsub = subtype<T>;
+ const T& min = std::numeric_limits<Tsub>::min();
+ const T& max = std::numeric_limits<Tsub>::max();
+ CHECK(kfr::satadd(min, min) == apply([](auto x, auto y) { return ref_satadd(x, y); }, min, min));
+ CHECK(kfr::satadd(max, max) == apply([](auto x, auto y) { return ref_satadd(x, y); }, max, max));
+ CHECK(kfr::satadd(min, max) == apply([](auto x, auto y) { return ref_satadd(x, y); }, min, max));
+ CHECK(kfr::satadd(max, min) == apply([](auto x, auto y) { return ref_satadd(x, y); }, max, min));
+
+ CHECK(kfr::satsub(min, min) == apply([](auto x, auto y) { return ref_satsub(x, y); }, min, min));
+ CHECK(kfr::satsub(max, max) == apply([](auto x, auto y) { return ref_satsub(x, y); }, max, max));
+ CHECK(kfr::satsub(min, max) == apply([](auto x, auto y) { return ref_satsub(x, y); }, min, max));
+ CHECK(kfr::satsub(max, min) == apply([](auto x, auto y) { return ref_satsub(x, y); }, max, min));
+ });
+}
+
+TEST(intrin_any_all)
+{
+ testo::matrix(named("type") = unsigned_types, [](auto type) {
+ using T = type_of<decltype(type)>;
+ constexpr size_t width = widthof<T>();
+ using Tsub = subtype<T>;
+ const auto x = enumerate<Tsub, width>() == Tsub(0);
+ CHECK(any(x) == true);
+ if (width == 1)
+ CHECK(all(x) == true);
+ else
+ CHECK(all(x) == false);
+ const auto y = zerovector<Tsub, width>() == Tsub(127);
+ CHECK(all(y) == false);
+ CHECK(any(y) == false);
+ const auto z = zerovector<Tsub, width>() == Tsub(0);
+ CHECK(all(z) == true);
+ CHECK(any(z) == true);
+ });
+}
+
+int main(int argc, char** argv) { return testo::run_all("", false); }