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 1abc358a685ffe707673a41445a37cdc92a858d5
parent 26071f6d11374512526a9e456ca5b071e8f0e0a4
Author: d.levin256@gmail.com <d.levin256@gmail.com>
Date:   Fri, 11 Nov 2022 19:10:09 +0000

Fix common_type for GCC

Diffstat:
Minclude/kfr/base/basic_expressions.hpp | 5+----
Minclude/kfr/base/expression.hpp | 9+++++----
Minclude/kfr/base/handle.hpp | 5+++--
Minclude/kfr/base/shape.hpp | 8++++----
Minclude/kfr/base/tensor.hpp | 75+++++++++++++--------------------------------------------------------------
Minclude/kfr/dsp/biquad.hpp | 2+-
Minclude/kfr/simd/vec.hpp | 29+++++++++++++++++++++++++----
Mtests/unit/base/basic_expressions.cpp | 4+++-
Mtests/unit/base/tensor.cpp | 2+-
9 files changed, 56 insertions(+), 83 deletions(-)

diff --git a/include/kfr/base/basic_expressions.hpp b/include/kfr/base/basic_expressions.hpp @@ -294,7 +294,7 @@ KFR_INTRINSIC expression_lambda<T, Dims, Fn, false> lambda_generator(Fn&& fn) template <typename... Ts, typename T = std::common_type_t<Ts...>> KFR_INTRINSIC auto sequence(const Ts&... list) { - return lambda<T>([seq = std::array<T, sizeof...(Ts)>{ { static_cast<T>(list)... } }](size_t index) { // + return lambda<T>([seq = std::array<T, sizeof...(Ts)>{ { static_cast<T>(list)... } }](index_t index) { // return seq[index % seq.size()]; }); } @@ -320,9 +320,6 @@ KFR_INTRINSIC vec<T, N> get_elements(const expression_lambda<T, Dims, Fn, Rnd>& ++cur_index.back(); } return result; - // return vec<T, N>{ [&](size_t idx) { // - // return self.fn(index.add(idx)); - // } }; } else if constexpr (std::is_invocable_v<Fn>) return apply<N>(self.fn); diff --git a/include/kfr/base/expression.hpp b/include/kfr/base/expression.hpp @@ -533,8 +533,9 @@ KFR_MEM_INTRINSIC vec<typename Traits::value_type, N> get_arg(const expression_f if constexpr (last_dim != undefined_size) { constexpr index_t last_dim_pot = prev_poweroftwo(last_dim); - return repeat<N / std::min(last_dim_pot, N)>(get_elements( - std::get<idx>(self.args), indices, axis_params<Axis, std::min(last_dim_pot, N)>{})); + return repeat<N / std::min(last_dim_pot, static_cast<index_t>(N))>( + get_elements(std::get<idx>(self.args), indices, + axis_params<Axis, std::min(last_dim_pot, static_cast<index_t>(N))>{})); } else { @@ -657,7 +658,7 @@ constexpr KFR_INTRINSIC size_t select_process_width(size_t width, size_t vec_wid if (last_dim_size == 0) return vec_width; - return std::min(vec_width, last_dim_size); + return std::min(vec_width, static_cast<size_t>(last_dim_size)); } constexpr KFR_INTRINSIC index_t select_axis(index_t ndims, index_t axis) @@ -853,7 +854,7 @@ void test_expression(const E& expr, size_t size, Fn&& fn, const char* expression test->check(c <= expr_size == size, expression, file, line); if (expr_size != size) return; - size = min(shape{ size }, shape{ 200 }).front(); + size = min(shape<1>(size), shape<1>(200)).front(); constexpr size_t maxsize = 2 + ilog2(vector_width<T> * 2); size_t g = 1; for (size_t i = 0; i < size;) diff --git a/include/kfr/base/handle.hpp b/include/kfr/base/handle.hpp @@ -237,7 +237,7 @@ KFR_INTRINSIC vec<T, N> get_elements(const expression_handle<T, NDims>& self, co if constexpr (Nsize >= expression_vtable<T, NDims>::Nsizes) { constexpr size_t Nhalf = N / 2; - auto low = get_elements(self, index, axis_params_v<Axis, Nhalf>); + auto low = get_elements(self, index, axis_params_v<Axis, Nhalf>); auto high = get_elements(self, index.add_at(Nhalf, cval<index_t, Axis>), axis_params_v<Axis, Nhalf>); return concat(low, high); } @@ -259,7 +259,8 @@ KFR_INTRINSIC void set_elements(const expression_handle<T, NDims>& self, const s { constexpr size_t Nhalf = N / 2; set_elements(self, index, axis_params_v<Axis, Nhalf>, slice<0, Nhalf>(value)); - set_elements(self, index.add_at(Nhalf, cval<index_t, Axis>), axis_params_v<Axis, Nhalf>, slice<Nhalf, Nhalf>(value)); + set_elements(self, index.add_at(Nhalf, cval<index_t, Axis>), axis_params_v<Axis, Nhalf>, + slice<Nhalf, Nhalf>(value)); } else { diff --git a/include/kfr/base/shape.hpp b/include/kfr/base/shape.hpp @@ -252,12 +252,12 @@ struct shape : static_array_base<index_t, csizeseq_t<dims>> { if constexpr (dims == 1) { - return { index }; + return { static_cast<index_t>(index) }; } else if constexpr (dims == 2) { index_t sz = (*this)[1]; - return { index / sz, index % sz }; + return { static_cast<index_t>(index / sz), static_cast<index_t>(index % sz) }; } else { @@ -827,7 +827,7 @@ constexpr KFR_INTRINSIC index_t size_of_shape(const shape<dims>& shape) return n; } -template <index_t Axis, index_t N> +template <index_t Axis, size_t N> struct axis_params { constexpr static index_t axis = Axis; @@ -837,7 +837,7 @@ struct axis_params constexpr axis_params() = default; }; -template <index_t Axis, index_t N> +template <index_t Axis, size_t N> constexpr inline const axis_params<Axis, N> axis_params_v{}; } // namespace kfr diff --git a/include/kfr/base/tensor.hpp b/include/kfr/base/tensor.hpp @@ -77,7 +77,7 @@ template <typename T, typename Derived, typename Dims> struct tensor_subscript; template <typename T, typename Derived, index_t... Dims> -struct tensor_subscript<T, Derived, std::integer_sequence<size_t, Dims...>> +struct tensor_subscript<T, Derived, std::integer_sequence<index_t, Dims...>> { constexpr static inline size_t dims = sizeof...(Dims); @@ -91,7 +91,7 @@ struct tensor_subscript<T, Derived, std::integer_sequence<size_t, Dims...>> }; template <typename T, index_t NDims> -struct tensor : public tensor_subscript<T, tensor<T, NDims>, std::make_index_sequence<NDims>> +struct tensor : public tensor_subscript<T, tensor<T, NDims>, std::make_integer_sequence<index_t, NDims>> { public: using value_type = T; @@ -116,24 +116,10 @@ public: const tensor* src; shape_type indices; - KFR_MEM_INTRINSIC index_t flat_index() const { return src->calc_index(indices); } + KFR_MEM_INTRINSIC intptr_t flat_index() const { return src->calc_index(indices); } KFR_MEM_INTRINSIC bool is_end() const { return indices.front() == internal_generic::null_index; } - template <size_t num> - KFR_MEM_INTRINSIC kfr::shape<num> advance() - { - kfr::shape<num> result; - for (size_t i = 0; i < num; ++i) - { - result[i] = src->calc_index(indices); - ++*this; - if (is_end()) - break; - } - return result; - } - KFR_MEM_INTRINSIC T& operator*() { return src->m_data[flat_index()]; } KFR_MEM_INTRINSIC T* operator->() { return &operator*(); } @@ -225,19 +211,19 @@ public: } template <typename U, KFR_ENABLE_IF(std::is_convertible_v<U, T>&& dims == 1)> - KFR_INTRINSIC tensor(const std::initializer_list<U>& values) : tensor(shape_type{ values.size() }) + KFR_INTRINSIC tensor(const std::initializer_list<U>& values) : tensor(shape_type(values.size())) { internal_generic::list_copy_recursively(values, contiguous_begin_unsafe()); } template <typename U, KFR_ENABLE_IF(std::is_convertible_v<U, T>&& dims == 2)> KFR_INTRINSIC tensor(const std::initializer_list<std::initializer_list<U>>& values) - : tensor(shape_type{ values.size(), values.begin()->size() }) + : tensor(shape_type(values.size(), values.begin()->size())) { internal_generic::list_copy_recursively(values, contiguous_begin_unsafe()); } template <typename U, KFR_ENABLE_IF(std::is_convertible_v<U, T>&& dims == 3)> KFR_INTRINSIC tensor(const std::initializer_list<std::initializer_list<std::initializer_list<U>>>& values) - : tensor(shape_type{ values.size(), values.begin()->size(), values.begin()->begin()->size() }) + : tensor(shape_type(values.size(), values.begin()->size(), values.begin()->begin()->size())) { internal_generic::list_copy_recursively(values, contiguous_begin_unsafe()); } @@ -245,8 +231,8 @@ public: KFR_INTRINSIC tensor( const std::initializer_list<std::initializer_list<std::initializer_list<std::initializer_list<U>>>>& values) - : tensor(shape_type{ values.size(), values.begin()->size(), values.begin()->begin()->size(), - values.begin()->begin()->begin()->size() }) + : tensor(shape_type(values.size(), values.begin()->size(), values.begin()->begin()->size(), + values.begin()->begin()->begin()->size())) { internal_generic::list_copy_recursively(values, contiguous_begin_unsafe()); } @@ -297,7 +283,10 @@ public: KFR_INTRINSIC contiguous_iterator contiguous_begin_unsafe() const { return m_data; } KFR_INTRINSIC contiguous_iterator contiguous_end_unsafe() const { return m_data + m_size; } - KFR_MEM_INTRINSIC index_t calc_index(const shape_type& indices) const { return indices.dot(m_strides); } + KFR_MEM_INTRINSIC intptr_t calc_index(const shape_type& indices) const + { + return static_cast<intptr_t>(static_cast<signed_index_t>(indices.dot(m_strides))); + } KFR_MEM_INTRINSIC reference access(const shape_type& indices) const { @@ -767,44 +756,6 @@ public: return *this; } - // template <typename Input, KFR_ENABLE_IF(is_input_expression<Input>)> - // tensor(Input&& input) : tensor(make_vector<index_t>(input.size())) - // { - // this->assign_expr(std::forward<Input>(input)); - // } - - template <size_t N, bool only_last = false> - KFR_MEM_INTRINSIC kfr::shape<N> offsets(kfr::shape<dims> indices) const - { - kfr::shape<N> result; - if constexpr (only_last) - { - index_t base = calc_index(indices); - result = base + enumerate(vec_shape<index_t, N>{}, m_shape.back()); - } - else - { - for (index_t i = 0; i < N; ++i) - { - result[i] = calc_index(indices); - internal_generic::increment_indices(indices, kfr::shape<dims>(0), m_shape); - } - } - return result; - } - - template <size_t N, bool only_last = false> - KFR_MEM_INTRINSIC kfr::shape<N> offsets(size_t flat_index) const - { - kfr::shape<dims> indices; - for (index_t i = 0; i < dims; ++i) - { - indices[dims - 1 - i] = flat_index % m_shape[dims - 1 - i]; - flat_index /= m_shape[dims - 1 - i]; - } - return offsets<N, only_last>(indices); - } - bool operator==(const tensor& other) const { return shape() == other.shape() && std::equal(begin(), end(), other.begin()); @@ -869,7 +820,7 @@ KFR_INTRINSIC tensor<T, 1> tensor_from_container(Container container) Container* ptr = &static_cast<container_finalizer*>(mem.get())->data; - return tensor<T, 1>(ptr->data(), shape{ ptr->size() }, std::move(mem)); + return tensor<T, 1>(ptr->data(), shape<1>(ptr->size()), std::move(mem)); } template <typename T, index_t Dims> diff --git a/include/kfr/dsp/biquad.hpp b/include/kfr/dsp/biquad.hpp @@ -202,7 +202,7 @@ KFR_INTRINSIC void begin_pass(const expression_biquads<filters, T, E1>& self, sh { size_t size = stop.front(); self.block_end = size; - for (size_t i = 0; i < filters - 1; i++) + for (index_t i = 0; i < filters - 1; i++) { const vec<T, 1> in = i < size ? get_elements(self.first(), shape<1>{ i }, axis_params_v<0, 1>) : 0; self.state.out = biquad_process(self.bq, self.state, insertleft(in[0], self.state.out)); diff --git a/include/kfr/simd/vec.hpp b/include/kfr/simd/vec.hpp @@ -1448,15 +1448,34 @@ KFR_INTRINSIC vec<T, N> v(const portable_vec<T, N>& pv) } // namespace CMT_ARCH_NAME +template <typename T1, typename T2, size_t N1, size_t N2, typename = void> +struct common_type_helper +{ +}; +template <typename T1, typename T2, size_t N> +struct common_type_helper<T1, T2, N, N> + : construct_common_type<std::common_type<T1, T2>, vec_template<N>::template type> +{ +}; +template <typename T1, typename T2, size_t N1, size_t N2> +struct common_type_helper<vec<T1, N2>, T2, N1, N2, std::enable_if_t<N1 != N2>> + : construct_common_type<std::common_type<T1, T2>, vecvec_template<N2, N1>::template type> +{ +}; +template <typename T1, typename T2, size_t N1, size_t N2> +struct common_type_helper<T1, vec<T2, N2>, N1, N2, std::enable_if_t<N1 != N2>> + : construct_common_type<std::common_type<T1, T2>, vecvec_template<N2, N1>::template type> +{ +}; + } // namespace kfr namespace std { -// V x V (same N) -template <typename T1, typename T2, size_t N> -struct common_type<kfr::vec<T1, N>, kfr::vec<T2, N>> - : kfr::construct_common_type<std::common_type<T1, T2>, kfr::vec_template<N>::template type> +// V x V +template <typename T1, typename T2, size_t N1, size_t N2> +struct common_type<kfr::vec<T1, N1>, kfr::vec<T2, N2>> : kfr::common_type_helper<T1, T2, N1, N2> { }; // V x S @@ -1471,6 +1490,7 @@ struct common_type<T1, kfr::vec<T2, N>> : kfr::construct_common_type<std::common_type<T1, T2>, kfr::vec_template<N>::template type> { }; +#if 0 // VV x V template <typename T1, typename T2, size_t N1, size_t N2> struct common_type<kfr::vec<kfr::vec<T1, N1>, N2>, kfr::vec<T2, N1>> @@ -1489,6 +1509,7 @@ struct common_type<kfr::vec<kfr::vec<T1, N1>, N2>, kfr::vec<kfr::vec<T2, N1>, N2 : kfr::construct_common_type<std::common_type<T1, T2>, kfr::vecvec_template<N1, N2>::template type> { }; +#endif } // namespace std diff --git a/tests/unit/base/basic_expressions.cpp b/tests/unit/base/basic_expressions.cpp @@ -144,7 +144,9 @@ TEST(assign_expression) CHECK_EXPRESSION(a, { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90 }); CHECK_EXPRESSION(b, { 1000, 1010, 1020, 1030, 1040, 1050, 1060, 1070, 1080, 1090 }); - // static_assert(std::is_same_v<std::common_type_t<f32x2x2, f32x2x2>, f32x2x2>); + static_assert(std::is_same_v<std::common_type_t<f32x2x2, f32x2x2>, f32x2x2>); + static_assert( + std::is_same_v<std::common_type_t<vec<vec<double, 2>, 1>, vec<double, 2>>, vec<vec<double, 2>, 1>>); } TEST(trace) { render(trace(counter()), 44); } diff --git a/tests/unit/base/tensor.cpp b/tests/unit/base/tensor.cpp @@ -536,7 +536,7 @@ TEST(expression_reshape) } // namespace CMT_ARCH_NAME -#ifdef _MSC_VER +#if 0 shape<4> sh{ 2, 3, 4, 5 }; extern "C" __declspec(dllexport) bool assembly_test1(shape<4>& x)