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 e96e4ecfbd02ad6bb84f648fe627b3138fa8faa0
parent 5f27676d407ece9ac8d68842535260ec656a3519
Author: d.levin256@gmail.com <d.levin256@gmail.com>
Date:   Thu,  8 Sep 2016 17:55:01 +0300

Move expression types to expression.hpp

Diffstat:
Minclude/kfr/base/expression.hpp | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Minclude/kfr/base/types.hpp | 136-------------------------------------------------------------------------------
Minclude/kfr/base/vec.hpp | 47+----------------------------------------------
Minclude/kfr/cometa.hpp | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 183 insertions(+), 182 deletions(-)

diff --git a/include/kfr/base/expression.hpp b/include/kfr/base/expression.hpp @@ -37,6 +37,118 @@ namespace kfr { +constexpr size_t infinite_size = static_cast<size_t>(-1); + +constexpr inline size_t size_add(size_t x, size_t y) +{ + return (x == infinite_size || y == infinite_size) ? infinite_size : x + y; +} + +constexpr inline size_t size_sub(size_t x, size_t y) +{ + return (x == infinite_size || y == infinite_size) ? infinite_size : x - y; +} + +constexpr inline size_t size_min(size_t x) noexcept { return x; } + +template <typename... Ts> +constexpr inline size_t size_min(size_t x, size_t y, Ts... rest) noexcept +{ + return size_min(x < y ? x : y, rest...); +} + +/// @brief Base class of all input expressoins +struct input_expression +{ + constexpr static size_t size() noexcept { return infinite_size; } + + constexpr static bool is_incremental = false; + + CMT_INLINE void begin_block(size_t) const {} + CMT_INLINE void end_block(size_t) const {} +}; + +/// @brief Base class of all output expressoins +struct output_expression +{ + constexpr static size_t size() noexcept { return infinite_size; } + + constexpr static bool is_incremental = false; + + CMT_INLINE void output_begin_block(size_t) const {} + CMT_INLINE void output_end_block(size_t) const {} +}; + +/// @brief Check if the type argument is an input expression +template <typename E> +using is_input_expression = std::is_base_of<input_expression, decay<E>>; + +/// @brief Check if the type arguments are an input expressions +template <typename... Es> +using is_input_expressions = or_t<std::is_base_of<input_expression, decay<Es>>...>; + +/// @brief Check if the type argument is an output expression +template <typename E> +using is_output_expression = std::is_base_of<output_expression, decay<E>>; + +/// @brief Check if the type arguments are an output expressions +template <typename... Es> +using is_output_expressions = or_t<std::is_base_of<output_expression, decay<Es>>...>; + +/// @brief Check if the type argument is a number or a vector of numbers +template <typename T> +using is_numeric = is_number<deep_subtype<T>>; + +/// @brief Check if the type arguments are a numbers or a vectors of numbers +template <typename... Ts> +using is_numeric_args = and_t<is_numeric<Ts>...>; + +namespace internal +{ + +template <typename T, typename Fn> +struct expression_lambda : input_expression +{ + using value_type = T; + CMT_INLINE expression_lambda(Fn&& fn) : fn(std::move(fn)) {} + + template <size_t N, KFR_ENABLE_IF(N&& is_callable<Fn, cinput_t, size_t, vec_t<T, N>>::value)> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const + { + return fn(cinput, index, y); + } + + template <size_t N, KFR_ENABLE_IF(N&& is_callable<Fn, size_t>::value)> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const + { + vec<T, N> result; + for (size_t i = 0; i < N; i++) + { + result(i) = fn(index + i); + } + return result; + } + template <size_t N, KFR_ENABLE_IF(N&& is_callable<Fn>::value)> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t, vec_t<T, N>) const + { + vec<T, N> result; + for (size_t i = 0; i < N; i++) + { + result(i) = fn(); + } + return result; + } + + Fn fn; +}; +} + +template <typename T, typename Fn> +internal::expression_lambda<T, decay<Fn>> lambda(Fn&& fn) +{ + return internal::expression_lambda<T, decay<Fn>>(std::move(fn)); +} + namespace internal { template <typename T, typename = void> diff --git a/include/kfr/base/types.hpp b/include/kfr/base/types.hpp @@ -226,76 +226,6 @@ template <typename T> using returns = cometa::fn_returns<T>; } -namespace internal -{ -template <size_t bits> -struct float_type_impl; -template <size_t bits> -struct int_type_impl; -template <size_t bits> -struct unsigned_type_impl; - -template <> -struct float_type_impl<32> -{ - using type = f32; -}; -template <> -struct float_type_impl<64> -{ - using type = f64; -}; - -template <> -struct int_type_impl<8> -{ - using type = i8; -}; -template <> -struct int_type_impl<16> -{ - using type = i16; -}; -template <> -struct int_type_impl<32> -{ - using type = i32; -}; -template <> -struct int_type_impl<64> -{ - using type = i64; -}; - -template <> -struct unsigned_type_impl<8> -{ - using type = u8; -}; -template <> -struct unsigned_type_impl<16> -{ - using type = u16; -}; -template <> -struct unsigned_type_impl<32> -{ - using type = u32; -}; -template <> -struct unsigned_type_impl<64> -{ - using type = u64; -}; -} - -template <size_t bits> -using float_type = typename internal::float_type_impl<bits>::type; -template <size_t bits> -using int_type = typename internal::int_type_impl<bits>::type; -template <size_t bits> -using unsigned_type = typename internal::unsigned_type_impl<bits>::type; - template <typename T> using ftype = deep_rebind<T, float_type<typebits<deep_subtype<T>>::bits>>; template <typename T> @@ -390,72 +320,6 @@ constexpr inline T maskbits(bool value) } } -constexpr size_t infinite_size = static_cast<size_t>(-1); - -constexpr inline size_t size_add(size_t x, size_t y) -{ - return (x == infinite_size || y == infinite_size) ? infinite_size : x + y; -} - -constexpr inline size_t size_sub(size_t x, size_t y) -{ - return (x == infinite_size || y == infinite_size) ? infinite_size : x - y; -} - -constexpr inline size_t size_min(size_t x) noexcept { return x; } - -template <typename... Ts> -constexpr inline size_t size_min(size_t x, size_t y, Ts... rest) noexcept -{ - return size_min(x < y ? x : y, rest...); -} - -/// @brief Base class of all input expressoins -struct input_expression -{ - constexpr static size_t size() noexcept { return infinite_size; } - - constexpr static bool is_incremental = false; - - CMT_INLINE void begin_block(size_t) const {} - CMT_INLINE void end_block(size_t) const {} -}; - -/// @brief Base class of all output expressoins -struct output_expression -{ - constexpr static size_t size() noexcept { return infinite_size; } - - constexpr static bool is_incremental = false; - - CMT_INLINE void output_begin_block(size_t) const {} - CMT_INLINE void output_end_block(size_t) const {} -}; - -/// @brief Check if the type argument is an input expression -template <typename E> -using is_input_expression = std::is_base_of<input_expression, decay<E>>; - -/// @brief Check if the type arguments are an input expressions -template <typename... Es> -using is_input_expressions = or_t<std::is_base_of<input_expression, decay<Es>>...>; - -/// @brief Check if the type argument is an output expression -template <typename E> -using is_output_expression = std::is_base_of<output_expression, decay<E>>; - -/// @brief Check if the type arguments are an output expressions -template <typename... Es> -using is_output_expressions = or_t<std::is_base_of<output_expression, decay<Es>>...>; - -/// @brief Check if the type argument is a number or a vector of numbers -template <typename T> -using is_numeric = is_number<deep_subtype<T>>; - -/// @brief Check if the type arguments are a numbers or a vectors of numbers -template <typename... Ts> -using is_numeric_args = and_t<is_numeric<Ts>...>; - namespace internal { template <size_t width, typename Fn> diff --git a/include/kfr/base/vec.hpp b/include/kfr/base/vec.hpp @@ -540,7 +540,7 @@ KFR_FN(make_vector) template <typename Type = void, typename Arg, typename... Args, size_t N = (sizeof...(Args) + 1), typename SubType = conditional<is_void<Type>::value, common_type<Arg, Args...>, Type>, - KFR_ENABLE_IF(is_numeric<SubType>::value)> + KFR_ENABLE_IF(is_number<subtype<SubType>>::value)> constexpr CMT_INLINE vec<SubType, N> pack(const Arg& x, const Args&... rest) { return internal::make_vector_impl<SubType>(csizeseq<N * widthof<SubType>()>, static_cast<SubType>(x), @@ -1333,51 +1333,6 @@ CMT_INLINE vec_t<T, Nout> high(vec_t<T, N>) KFR_FN(low) KFR_FN(high) -namespace internal -{ - -template <typename T, typename Fn> -struct expression_lambda : input_expression -{ - using value_type = T; - CMT_INLINE expression_lambda(Fn&& fn) : fn(std::move(fn)) {} - - template <size_t N, KFR_ENABLE_IF(N&& is_callable<Fn, cinput_t, size_t, vec_t<T, N>>::value)> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const - { - return fn(cinput, index, y); - } - - template <size_t N, KFR_ENABLE_IF(N&& is_callable<Fn, size_t>::value)> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const - { - vec<T, N> result; - for (size_t i = 0; i < N; i++) - { - result(i) = fn(index + i); - } - return result; - } - template <size_t N, KFR_ENABLE_IF(N&& is_callable<Fn>::value)> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t, vec_t<T, N>) const - { - vec<T, N> result; - for (size_t i = 0; i < N; i++) - { - result(i) = fn(); - } - return result; - } - - Fn fn; -}; -} - -template <typename T, typename Fn> -internal::expression_lambda<T, decay<Fn>> lambda(Fn&& fn) -{ - return internal::expression_lambda<T, decay<Fn>>(std::move(fn)); -} } #pragma clang diagnostic pop diff --git a/include/kfr/cometa.hpp b/include/kfr/cometa.hpp @@ -892,6 +892,69 @@ constexpr inline T lcm(T a, T b, T c, Ts... rest) namespace details { + +template <size_t bits> +struct float_type_impl; +template <size_t bits> +struct int_type_impl; +template <size_t bits> +struct unsigned_type_impl; + +template <> +struct float_type_impl<32> +{ + using type = float; + static_assert(sizeof(type) * 8 == 32, "float must represent IEEE single precision value"); +}; +template <> +struct float_type_impl<64> +{ + using type = double; + static_assert(sizeof(type) * 8 == 64, "double must represent IEEE double precision value"); +}; + +template <> +struct int_type_impl<8> +{ + using type = std::int8_t; +}; +template <> +struct int_type_impl<16> +{ + using type = std::int16_t; +}; +template <> +struct int_type_impl<32> +{ + using type = std::int32_t; +}; +template <> +struct int_type_impl<64> +{ + using type = std::int64_t; +}; + +template <> +struct unsigned_type_impl<8> +{ + using type = std::uint8_t; +}; +template <> +struct unsigned_type_impl<16> +{ + using type = std::uint16_t; +}; +template <> +struct unsigned_type_impl<32> +{ + using type = std::uint32_t; +}; +template <> +struct unsigned_type_impl<64> +{ + using type = std::uint64_t; +}; + template <int64_t min, int64_t max, typename... Types> struct findinttype_impl { @@ -914,6 +977,13 @@ using is_number_impl = !std::is_same<T, bool>::value>; } +template <size_t bits> +using float_type = typename details::float_type_impl<bits>::type; +template <size_t bits> +using int_type = typename details::int_type_impl<bits>::type; +template <size_t bits> +using unsigned_type = typename details::unsigned_type_impl<bits>::type; + template <int64_t min, int64_t max> using findinttype = typename details::findinttype_impl<min, max, uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t>::type;