kfr

Fast, modern C++ DSP framework, FFT, Sample Rate Conversion, FIR/IIR/Biquad Filters (SSE, AVX, AVX-512, ARM NEON)
Log | Files | Refs | README

commit 46fd746b0950ba6298194c3700d1584d48c44786
parent 02febf79ec1cff575d3c220126d1746ad6b5e99c
Author: d.levin256@gmail.com <d.levin256@gmail.com>
Date:   Mon,  9 Dec 2019 15:05:31 +0000

MSVC2019 fixes

Diffstat:
Minclude/kfr/cometa.hpp | 10+++++-----
Minclude/kfr/math/impl/atan.hpp | 12++++--------
Minclude/kfr/math/impl/log_exp.hpp | 14++++++--------
Minclude/kfr/simd/impl/backend_generic.hpp | 14+++++++-------
Minclude/kfr/simd/shuffle.hpp | 2+-
Minclude/kfr/simd/vec.hpp | 8++++----
Mtests/all_tests.cpp | 19+++++++++++++++++--
Mtests/asm_test.cpp | 25++++++++++++++++++++-----
Mtests/dsp_test.cpp | 18+++++++++---------
Mtests/intrinsic_test.cpp | 6+++---
Mtests/numeric_tests.hpp | 4++--
Mtests/unit/simd/operators.cpp | 4++--
Mtests/unit/simd/vec.cpp | 22+++++++++++-----------
13 files changed, 91 insertions(+), 67 deletions(-)

diff --git a/include/kfr/cometa.hpp b/include/kfr/cometa.hpp @@ -443,17 +443,17 @@ struct cvals_t : ops::empty return {}; } - constexpr bool operator==(cvals_t<T, values...>) const noexcept { return true; } + constexpr bool equal(cvals_t<T, values...>) const noexcept { return true; } template <T... values2> - constexpr bool operator==(cvals_t<T, values2...>) const noexcept + constexpr bool equal(cvals_t<T, values2...>) const noexcept { return false; } template <T... values2> - constexpr bool operator!=(cvals_t<T, values...> ind) const noexcept + constexpr bool notequal(cvals_t<T, values...> ind) const noexcept { - return !operator==(ind); + return !equal(ind); } }; @@ -1478,7 +1478,7 @@ namespace details template <size_t index, typename... types> CMT_INTRINSIC auto get_type_arg(ctypes_t<types...>) { - return ctype_t<type_of<details::get_nth_type<index, types...>>>(); + return ctype_t<typename details::get_nth_type<index, types...>::type>(); } template <typename T0, typename... types, typename Fn, size_t... indices> diff --git a/include/kfr/math/impl/atan.hpp b/include/kfr/math/impl/atan.hpp @@ -51,8 +51,7 @@ KFR_INTRINSIC vec<f32, N> atan2k(const vec<f32, N>& yy, const vec<f32, N>& xx) q = select(m, q + 1, q); s = y / x; t = s * s; - u = 0.00282363896258175373077393f; - u = fmadd(u, t, -0.0159569028764963150024414f); + u = fmadd(0.00282363896258175373077393f, t, -0.0159569028764963150024414f); u = fmadd(u, t, 0.0425049886107444763183594f); u = fmadd(u, t, -0.0748900920152664184570312f); u = fmadd(u, t, 0.106347933411598205566406f); @@ -80,8 +79,7 @@ KFR_INTRINSIC vec<f64, N> atan2k(const vec<f64, N>& yy, const vec<f64, N>& xx) q = select(m, q + i64(1), q); s = y / x; t = s * s; - u = -1.88796008463073496563746e-05; - u = fmadd(u, t, 0.000209850076645816976906797); + u = fmadd(-1.88796008463073496563746e-05, t, 0.000209850076645816976906797); u = fmadd(u, t, -0.00110611831486672482563471); u = fmadd(u, t, 0.00370026744188713119232403); u = fmadd(u, t, -0.00889896195887655491740809); @@ -144,8 +142,7 @@ KFR_INTRINSIC vec<f32, N> atan(const vec<f32, N>& x) q = select(s > 1.f, q | 1, q); s = select(s > 1.f, 1.0f / s, s); t = s * s; - u = 0.00282363896258175373077393f; - u = fmadd(u, t, -0.0159569028764963150024414f); + u = fmadd(0.00282363896258175373077393f, t, -0.0159569028764963150024414f); u = fmadd(u, t, 0.0425049886107444763183594f); u = fmadd(u, t, -0.0748900920152664184570312f); u = fmadd(u, t, 0.106347933411598205566406f); @@ -168,8 +165,7 @@ KFR_INTRINSIC vec<f64, N> atan(const vec<f64, N>& x) q = select(s > 1.0, q | 1, q); s = select(s > 1.0, 1.0 / s, s); t = s * s; - u = -1.88796008463073496563746e-05; - u = fmadd(u, t, 0.000209850076645816976906797); + u = fmadd(-1.88796008463073496563746e-05, t, 0.000209850076645816976906797); u = fmadd(u, t, -0.00110611831486672482563471); u = fmadd(u, t, 0.00370026744188713119232403); u = fmadd(u, t, -0.00889896195887655491740809); diff --git a/include/kfr/math/impl/log_exp.hpp b/include/kfr/math/impl/log_exp.hpp @@ -97,8 +97,8 @@ KFR_INTRINSIC vec<f32, N> log(const vec<f32, N>& d) vec<f32, N> sp = select(d < 0, constants<f32>::qnan, constants<f32>::neginfinity); - vec<f32, N> t = 0.2371599674224853515625f; - t = fmadd(t, x2, 0.285279005765914916992188f); + vec<f32, N> t; + t = fmadd(0.2371599674224853515625f, x2, 0.285279005765914916992188f); t = fmadd(t, x2, 0.400005519390106201171875f); t = fmadd(t, x2, 0.666666567325592041015625f); t = fmadd(t, x2, 2.0f); @@ -120,8 +120,8 @@ KFR_INTRINSIC vec<f64, N> log(const vec<f64, N>& d) vec<f64, N> sp = select(d < 0, constants<f64>::qnan, constants<f64>::neginfinity); - vec<f64, N> t = 0.148197055177935105296783; - t = fmadd(t, x2, 0.153108178020442575739679); + vec<f64, N> t; + t = fmadd(0.148197055177935105296783, x2, 0.153108178020442575739679); t = fmadd(t, x2, 0.181837339521549679055568); t = fmadd(t, x2, 0.22222194152736701733275); t = fmadd(t, x2, 0.285714288030134544449368); @@ -165,8 +165,7 @@ KFR_INTRINSIC vec<f32, N> exp(const vec<f32, N>& d) const f32 c6 = 1.304379315115511417388916015625e-3f; const f32 c7 = 2.7555381529964506626129150390625e-4f; - u = c7; - u = fmadd(u, s, c6); + u = fmadd(c7, s, c6); u = fmadd(u, s, c5); u = fmadd(u, s, c4); u = fmadd(u, s, c3); @@ -203,8 +202,7 @@ KFR_INTRINSIC vec<f64, N> exp(const vec<f64, N>& d) const f64 c10 = 2.59589616274586264243611237120812340606335055781528e-7; const f64 c11 = 3.43801438838789632454461529017381016259946591162588e-8; - u = c11; - u = fmadd(u, s, c10); + u = fmadd(c11, s, c10); u = fmadd(u, s, c9); u = fmadd(u, s, c8); u = fmadd(u, s, c7); diff --git a/include/kfr/simd/impl/backend_generic.hpp b/include/kfr/simd/impl/backend_generic.hpp @@ -1639,7 +1639,7 @@ KFR_INTRINSIC simd<float, 8> simd_vec_shuffle(simd_t<float, 8>, const simd<float csizes_t<I0, I1, I2, I3, I4, I5, I6, I7>) { // AVX -> AVX - if constexpr (cmaxof(csizes<I0, I1, I2, I3>) < 4 && csizes<I0, I1, I2, I3> == csizes<I4, I5, I6, I7>) + if constexpr (cmaxof(csizes<I0, I1, I2, I3>) < 4 && csizes<I0, I1, I2, I3>.equal(csizes<I4, I5, I6, I7>)) { const simd<float, 4> tmp = universal_shuffle(simd_t<float, 4>{}, simd_get_low(simd_t<float, 8>{}, x), csizes<I0, I1, I2, I3>); @@ -1647,8 +1647,8 @@ KFR_INTRINSIC simd<float, 8> simd_vec_shuffle(simd_t<float, 8>, const simd<float } else if constexpr (cmaxof(csizes<I0, I1, I2, I3>) < 4 && cminof(csizes<I4, I5, I6, I7>) >= 4) { - if constexpr (csizes<I0, I1, I2, I3, I4, I5, I6, I7> == - csizes<I0, I1, I2, I3, I0 + 4, I1 + 4, I2 + 4, I3 + 4>) + if constexpr (csizes<I0, I1, I2, I3, I4, I5, I6, I7>.equal( + csizes<I0, I1, I2, I3, I0 + 4, I1 + 4, I2 + 4, I3 + 4>)) { return _mm256_shuffle_ps(x, x, shuffle_mask<8, I0, I1, I2, I3>::value); } @@ -1680,7 +1680,7 @@ KFR_INTRINSIC simd<double, 4> simd_vec_shuffle(simd_t<double, 4>, const simd<dou csizes_t<I0, I1, I2, I3>) { // AVX -> AVX - if constexpr (cmaxof(csizes<I0, I1>) < 2 && csizes<I0, I1> == csizes<I2, I3>) + if constexpr (cmaxof(csizes<I0, I1>) < 2 && csizes<I0, I1>.equal(csizes<I2, I3>)) { const simd<double, 2> tmp = universal_shuffle(simd_t<double, 2>{}, simd_get_low(simd_t<double, 4>{}, x), csizes<I0, I1>); @@ -1688,7 +1688,7 @@ KFR_INTRINSIC simd<double, 4> simd_vec_shuffle(simd_t<double, 4>, const simd<dou } else if constexpr (cmaxof(csizes<I0, I1>) < 4 && cminof(csizes<I2, I3>) >= 4) { - if constexpr (csizes<I0, I1, I2, I3> == csizes<I0, I1, I2 + 2, I3 + 2>) + if constexpr (csizes<I0, I1, I2, I3>.equal(csizes<I0, I1, I2 + 2, I3 + 2>)) { return _mm256_shuffle_ps(x, x, shuffle_mask<2, I0, I1>::value); } @@ -1790,7 +1790,7 @@ KFR_INTRINSIC simd<T, Nout> universal_shuffle(simd_t<T, Nin>, const simd<T, Nin> { return x; } - else if constexpr (next_poweroftwo(Nin) == next_poweroftwo(Nout) && Indices{} == csizeseq<Nout>) + else if constexpr (next_poweroftwo(Nin) == next_poweroftwo(Nout) && Indices{}.equal(csizeseq<Nout>)) { return x; } @@ -1824,7 +1824,7 @@ KFR_INTRINSIC simd<T, Nout> universal_shuffle(simd_t<T, Nin>, const simd<T, Nin> { auto lowi = Indices{}[csizeseq<Nout / 2, 0>]; auto highi = Indices{}[csizeseq<Nout / 2, Nout / 2>]; - if constexpr (lowi == highi) + if constexpr (lowi.equal(highi)) { auto tmp = universal_shuffle(simd_t<T, Nin>{}, x, lowi); return { tmp, tmp }; diff --git a/include/kfr/simd/shuffle.hpp b/include/kfr/simd/shuffle.hpp @@ -518,7 +518,7 @@ KFR_INTRINSIC vec<T, N> splitpairs(const vec<T, N>& x) } KFR_FN(splitpairs) -template <size_t group = 1, typename T, size_t N> +template <size_t group = 1, typename T, size_t N, KFR_ENABLE_IF(!is_vec<T>)> KFR_INTRINSIC vec<T, N> reverse(const vec<T, N>& x) { constexpr size_t size = N / group; diff --git a/include/kfr/simd/vec.hpp b/include/kfr/simd/vec.hpp @@ -1126,7 +1126,7 @@ void test_function1(cint_t<Cat> cat, Fn&& fn, RefFn&& reffn, IsApplicable&& isap testo::matrix( named("value") = special_values(), named("type") = test_catogories::types(cat), [&](special_value value, auto type) { - using T = type_of<decltype(type)>; + using T = typename decltype(type)::type; if (isapplicable(ctype<T>, value)) { const T x(value); @@ -1141,7 +1141,7 @@ void test_function1(cint_t<Cat> cat, Fn&& fn, RefFn&& reffn, IsApplicable&& isap }); testo::matrix(named("type") = test_catogories::types(cint<Cat & ~1>), [&](auto type) { - using T = type_of<decltype(type)>; + using T = typename decltype(type)::type; const T x = test_enumerate(T::shape(), csizeseq<T::size()>, 0); CHECK(fn(x) == apply(reffn, x)); }); @@ -1153,7 +1153,7 @@ void test_function2(cint_t<Cat> cat, Fn&& fn, RefFn&& reffn, IsApplicable&& isap testo::matrix(named("value1") = special_values(), // named("value2") = special_values(), named("type") = test_catogories::types(cat), [&](special_value value1, special_value value2, auto type) { - using T = type_of<decltype(type)>; + using T = typename decltype(type)::type; const T x1(value1); const T x2(value2); if (isapplicable(ctype<T>, value1, value2)) @@ -1166,7 +1166,7 @@ void test_function2(cint_t<Cat> cat, Fn&& fn, RefFn&& reffn, IsApplicable&& isap }); testo::matrix(named("type") = test_catogories::types(cint<Cat & ~1>), [&](auto type) { - using T = type_of<decltype(type)>; + using T = typename decltype(type)::type; const T x1 = test_enumerate(T::shape(), csizeseq<T::size()>, 0, 1); const T x2 = test_enumerate(T::shape(), csizeseq<T::size()>, 100, -1); CHECK(fn(x1, x2) == apply(reffn, x1, x2)); diff --git a/tests/all_tests.cpp b/tests/all_tests.cpp @@ -34,8 +34,23 @@ FORCE_LINK(avx2) int main() { println(library_version(), " running on ", cpu_runtime()); + try + { #ifdef HAVE_MPFR - mpfr::scoped_precision p(64); + mpfr::scoped_precision p(64); #endif - return testo::run_all(""); + return testo::run_all(""); + } + catch (const std::exception& e) + { + errorln("****************************************"); + errorln("***** Exception: ", typeid(e).name(), ": ", e.what()); + return -1; + } + catch (...) + { + errorln("****************************************"); + errorln("***** Exception: unknown"); + return -1; + } } diff --git a/tests/asm_test.cpp b/tests/asm_test.cpp @@ -251,6 +251,26 @@ TEST_ASM_UIF(read, TEST_READ) TEST_ASM_UIF(write, TEST_WRITE) +TEST_ASM_F(sin, TEST_ASM_VTY1_F) + +TEST_ASM_F(log, TEST_ASM_VTY1_F) + +TEST_ASM_F(exp, TEST_ASM_VTY1_F) + +TEST_ASM_F(log2, TEST_ASM_VTY1_F) + +TEST_ASM_F(exp2, TEST_ASM_VTY1_F) + +TEST_ASM_F(cos, TEST_ASM_VTY1_F) + +TEST_ASM_F(tan, TEST_ASM_VTY1_F) + +TEST_ASM_F(atan, TEST_ASM_VTY1_F) + +TEST_ASM_F(asin, TEST_ASM_VTY1_F) + +TEST_ASM_F(acos, TEST_ASM_VTY1_F) + #ifdef HAVE_DFT #define TEST_FFT_SPEC(ty, size) \ @@ -287,11 +307,6 @@ TEST_FFT_GEN(f32) TEST_FFT_GEN(f64) #endif - -TEST_ASM_F(sin, TEST_ASM_VTY1_F) - -TEST_ASM_F(cos, TEST_ASM_VTY1_F) - #endif namespace kfr diff --git a/tests/dsp_test.cpp b/tests/dsp_test.cpp @@ -125,7 +125,7 @@ TEST(ebu_stereo_1_and_2) { testo::matrix(named("type") = ctypes_t<float, double>{}, named("sample_rate") = std::vector<int>{ 44100, 48000 }, [](auto type, int sample_rate) { - using T = type_of<decltype(type)>; + using T = typename decltype(type)::type; ebu_test_stereo<T>(sample_rate, { { -23.f, 20.f, 1000.f } }, -23.f, -23.f, -23.f, NAN); ebu_test_stereo<T>(sample_rate, { { -33.f, 20.f, 1000.f } }, -33.f, -33.f, -33.f, NAN); @@ -136,7 +136,7 @@ TEST(ebu_stereo_3_4_and_5) { testo::matrix(named("type") = ctypes_t<float, double>{}, named("sample_rate") = std::vector<int>{ 44100, 48000 }, [](auto type, int sample_rate) { - using T = type_of<decltype(type)>; + using T = typename decltype(type)::type; ebu_test_stereo<T>( sample_rate, @@ -156,7 +156,7 @@ TEST(ebu_multichannel_6) { testo::matrix(named("type") = ctypes_t<float, double>{}, named("sample_rate") = std::vector<int>{ 44100, 48000 }, [](auto type, int sample_rate) { - using T = type_of<decltype(type)>; + using T = typename decltype(type)::type; ebu_test_multichannel<T>(sample_rate, { { -28.f, -24.f, -30.f, 20.f, 1000.f } }, NAN, NAN, -23.f, NAN); @@ -167,7 +167,7 @@ TEST(ebu_stereo_9) { testo::matrix(named("type") = ctypes_t<float, double>{}, named("sample_rate") = std::vector<int>{ 44100, 48000 }, [](auto type, int sample_rate) { - using T = type_of<decltype(type)>; + using T = typename decltype(type)::type; ebu_test_stereo<T>(sample_rate, { { -20.f, 1.34f, 1000.f }, @@ -188,7 +188,7 @@ TEST(ebu_stereo_12) { testo::matrix(named("type") = ctypes_t<float, double>{}, named("sample_rate") = std::vector<int>{ 44100, 48000 }, [](auto type, int sample_rate) { - using T = type_of<decltype(type)>; + using T = typename decltype(type)::type; ebu_test_stereo<T>( sample_rate, @@ -217,7 +217,7 @@ TEST(ebu_lra_1_2_3_and_4) { testo::matrix(named("type") = ctypes_t<float, double>{}, named("sample_rate") = std::vector<int>{ 44100, 48000 }, [](auto type, int sample_rate) { - using T = type_of<decltype(type)>; + using T = typename decltype(type)::type; ebu_test_stereo<T>(sample_rate, { { -20.f, 20.f, 1000.f }, { -30.f, 20.f, 1000.f } }, NAN, NAN, NAN, 10.f); @@ -383,7 +383,7 @@ TEST(fir) #endif >{}, [](auto type) { - using T = type_of<decltype(type)>; + using T = typename decltype(type)::type; const univector<T, 100> data = counter() + sequence(1, 2, -10, 100) + sequence(0, -7, 0.5); @@ -498,7 +498,7 @@ inline const univector<T, Tag>& choose_array(const univector<T2, Tag>&, const un TEST(biquad_lowpass1) { testo::matrix(named("type") = ctypes_t<float, double>{}, [](auto type) { - using T = type_of<decltype(type)>; + using T = typename decltype(type)::type; const biquad_params<T> bq = biquad_lowpass<T>(0.1, 0.7); @@ -533,7 +533,7 @@ TEST(biquad_lowpass1) TEST(biquad_lowpass2) { testo::matrix(named("type") = ctypes_t<float, double>{}, [](auto type) { - using T = type_of<decltype(type)>; + using T = typename decltype(type)::type; const biquad_params<T> bq = biquad_lowpass<T>(0.45, 0.2); diff --git a/tests/intrinsic_test.cpp b/tests/intrinsic_test.cpp @@ -108,7 +108,7 @@ TEST(intrin_sqrt) CHECK(kfr::sqrt(make_vector(-9)) == make_vector<fbase>(qnan)); testo::matrix(named("type") = float_vector_types<vec>, named("value") = std::vector<int>{ 0, 2, 65536 }, [](auto type, int value) { - using T = type_of<decltype(type)>; + using T = typename decltype(type)::type; const T x(value); CHECK(kfr::sqrt(x) == apply([](auto x) -> decltype(x) { return std::sqrt(x); }, x)); }); @@ -118,7 +118,7 @@ TEST(intrin_satadd_satsub) { testo::matrix(named("type") = cconcat(signed_vector_types<vec>, unsigned_vector_types<vec>), [](auto type) { - using T = type_of<decltype(type)>; + using T = typename decltype(type)::type; using Tsub = subtype<T>; const T min = std::numeric_limits<Tsub>::min(); const T max = std::numeric_limits<Tsub>::max(); @@ -145,7 +145,7 @@ TEST(intrin_satadd_satsub) TEST(intrin_any_all) { testo::matrix(named("type") = unsigned_vector_types<vec>, [](auto type) { - using T = type_of<decltype(type)>; + using T = typename decltype(type)::type; constexpr size_t width = widthof<T>(); using Tsub = subtype<T>; const auto x = enumerate<Tsub, width>() == Tsub(0); diff --git a/tests/numeric_tests.hpp b/tests/numeric_tests.hpp @@ -74,7 +74,7 @@ inline const char* tname(ctype_t<f64>) { return "double"; } TEST(fn##_##datafile) \ { \ testo::matrix(named("type") = vector_types(), [&](auto type) { \ - using T = type_of<decltype(type)>; \ + using T = typename decltype(type)::type; \ using Tsub = subtype<T>; \ double error_sum = 0.0; \ uint64_t error_peak = 0; \ @@ -99,7 +99,7 @@ inline const char* tname(ctype_t<f64>) { return "double"; } TEST(fn##_##datafile) \ { \ testo::matrix(named("type") = vector_types(), [&](auto type) { \ - using T = type_of<decltype(type)>; \ + using T = typename decltype(type)::type; \ using Tsub = subtype<T>; \ double error_sum = 0.0; \ uint64_t error_peak = 0; \ diff --git a/tests/unit/simd/operators.cpp b/tests/unit/simd/operators.cpp @@ -103,7 +103,7 @@ TEST(shl) named("type") = test_catogories::types(test_catogories::vectors), named("value1") = special_values(), named("shift") = std::vector<unsigned>{ 1, 2, 7, 8, 9, 15, 16, 31, 32, 63, 64 }, [&](auto type, special_value value, unsigned shift) { - using T = type_of<decltype(type)>; + using T = typename decltype(type)::type; if (shift < sizeof(subtype<T>)) { const T x(value); @@ -131,7 +131,7 @@ TEST(shr) named("type") = test_catogories::types(test_catogories::vectors), named("value1") = special_values(), named("shift") = std::vector<unsigned>{ 1, 2, 7, 8, 9, 15, 16, 31, 32, 63, 64 }, [&](auto type, special_value value, unsigned shift) { - using T = type_of<decltype(type)>; + using T = typename decltype(type)::type; if (shift < sizeof(subtype<T>)) { const T x(value); diff --git a/tests/unit/simd/vec.cpp b/tests/unit/simd/vec.cpp @@ -90,58 +90,58 @@ TEST(cast) test_function1( test_catogories::all, [](auto x) { return kfr::innercast<u8>(x); }, [](auto x) -> u8 { return static_cast<u8>(x); }, - [](auto t, special_value x) { return is_in_range_of<u8>(x.get<subtype<type_of<decltype(t)>>>()); }); + [](auto t, special_value x) { return is_in_range_of<u8>(x.get<subtype<typename decltype(t)::type>>()); }); s.text = ("target_type = i8"); test_function1( test_catogories::all, [](auto x) { return kfr::innercast<i8>(x); }, [](auto x) -> i8 { return static_cast<i8>(x); }, - [](auto t, special_value x) { return is_in_range_of<i8>(x.get<subtype<type_of<decltype(t)>>>()); }); + [](auto t, special_value x) { return is_in_range_of<i8>(x.get<subtype<typename decltype(t)::type>>()); }); s.text = ("target_type = u16"); test_function1( test_catogories::all, [](auto x) { return kfr::innercast<u16>(x); }, [](auto x) -> u16 { return static_cast<u16>(x); }, - [](auto t, special_value x) { return is_in_range_of<u16>(x.get<subtype<type_of<decltype(t)>>>()); }); + [](auto t, special_value x) { return is_in_range_of<u16>(x.get<subtype<typename decltype(t)::type>>()); }); s.text = ("target_type = i16"); test_function1( test_catogories::all, [](auto x) { return kfr::innercast<i16>(x); }, [](auto x) -> i16 { return static_cast<i16>(x); }, - [](auto t, special_value x) { return is_in_range_of<i16>(x.get<subtype<type_of<decltype(t)>>>()); }); + [](auto t, special_value x) { return is_in_range_of<i16>(x.get<subtype<typename decltype(t)::type>>()); }); s.text = ("target_type = u32"); test_function1( test_catogories::all, [](auto x) { return kfr::innercast<u32>(x); }, [](auto x) -> u32 { return static_cast<u32>(x); }, - [](auto t, special_value x) { return is_in_range_of<u32>(x.get<subtype<type_of<decltype(t)>>>()); }); + [](auto t, special_value x) { return is_in_range_of<u32>(x.get<subtype<typename decltype(t)::type>>()); }); s.text = ("target_type = i32"); test_function1( test_catogories::all, [](auto x) { return kfr::innercast<i32>(x); }, [](auto x) -> i32 { return static_cast<i32>(x); }, - [](auto t, special_value x) { return is_in_range_of<i32>(x.get<subtype<type_of<decltype(t)>>>()); }); + [](auto t, special_value x) { return is_in_range_of<i32>(x.get<subtype<typename decltype(t)::type>>()); }); s.text = ("target_type = u64"); test_function1( test_catogories::all, [](auto x) { return kfr::innercast<u64>(x); }, [](auto x) -> u64 { return static_cast<u64>(x); }, - [](auto t, special_value x) { return is_in_range_of<u64>(x.get<subtype<type_of<decltype(t)>>>()); }); + [](auto t, special_value x) { return is_in_range_of<u64>(x.get<subtype<typename decltype(t)::type>>()); }); s.text = ("target_type = i64"); test_function1( test_catogories::all, [](auto x) { return kfr::innercast<i64>(x); }, [](auto x) -> i64 { return static_cast<i64>(x); }, - [](auto t, special_value x) { return is_in_range_of<i64>(x.get<subtype<type_of<decltype(t)>>>()); }); + [](auto t, special_value x) { return is_in_range_of<i64>(x.get<subtype<typename decltype(t)::type>>()); }); s.text = ("target_type = f32"); test_function1( test_catogories::all, [](auto x) { return kfr::innercast<f32>(x); }, [](auto x) -> f32 { return static_cast<f32>(x); }, - [](auto t, special_value x) { return is_in_range_of<f32>(x.get<subtype<type_of<decltype(t)>>>()); }); + [](auto t, special_value x) { return is_in_range_of<f32>(x.get<subtype<typename decltype(t)::type>>()); }); s.text = ("target_type = f64"); test_function1( test_catogories::all, [](auto x) { return kfr::innercast<f64>(x); }, [](auto x) -> f64 { return static_cast<f64>(x); }, - [](auto t, special_value x) { return is_in_range_of<f64>(x.get<subtype<type_of<decltype(t)>>>()); }); + [](auto t, special_value x) { return is_in_range_of<f64>(x.get<subtype<typename decltype(t)::type>>()); }); } TEST(unaligned_read) { testo::matrix(named("type") = numeric_vector_types<vec>, [](auto type) { - using T = type_of<decltype(type)>; + using T = typename decltype(type)::type; using Tsub = subtype<T>; constexpr static size_t N = T::size(); Tsub data[N * 2];