commit 3345865911299eb4bd77b769210327dc4cb91035 parent 8bce4e966727f5d396ca9bc8e198129078124cdc Author: d.levin256@gmail.com <d.levin256@gmail.com> Date: Fri, 4 Nov 2022 17:46:40 +0000 Remove std aliases Diffstat:
38 files changed, 415 insertions(+), 330 deletions(-)
diff --git a/examples/ccv.cpp b/examples/ccv.cpp @@ -33,9 +33,9 @@ int main() // Create noise to filter. auto const size = 1024 * 100 + 33; // not a multiple of block_size univector<complex<fbase>> cnoise = - make_complex(truncate(gen_random_range(random_bit_generator{ 1, 2, 3, 4 }, -1.f, +1.f), size), - truncate(gen_random_range(random_bit_generator{ 3, 4, 9, 8 }, -1.f, +1.f), size)); - univector<fbase> noise = truncate(gen_random_range(random_bit_generator{ 3, 4, 9, 8 }, -1.f, +1.f), size); + make_complex(truncate(gen_random_range(random_init(1, 2, 3, 4), -1.f, +1.f), size), + truncate(gen_random_range(random_init(3, 4, 9, 8), -1.f, +1.f), size)); + univector<fbase> noise = truncate(gen_random_range(random_init(3, 4, 9, 8), -1.f, +1.f), size); // Filter results. univector<complex<fbase>> filtered_cnoise_ccv(size), filtered_cnoise_fir(size); diff --git a/include/kfr/base/basic_expressions.hpp b/include/kfr/base/basic_expressions.hpp @@ -137,6 +137,7 @@ template <typename Arg> struct expression_slice : public expression_with_arguments<Arg> { constexpr static index_t dims = expression_dims<Arg>; + static_assert(dims > 0); shape<dims> start; shape<dims> size; @@ -166,12 +167,14 @@ template <typename Arg, KFR_ACCEPT_EXPRESSIONS(Arg), index_t Dims = expression_d KFR_INTRINSIC expression_slice<Arg> slice(Arg&& arg, identity<shape<Dims>> start, identity<shape<Dims>> size = shape<Dims>(infinite_size)) { + static_assert(Dims > 0); return { std::forward<Arg>(arg), start, size }; } template <typename Arg, KFR_ACCEPT_EXPRESSIONS(Arg), index_t Dims = expression_dims<Arg>> KFR_INTRINSIC expression_slice<Arg> truncate(Arg&& arg, identity<shape<Dims>> size) { + static_assert(Dims > 0); return { std::forward<Arg>(arg), shape<Dims>{ 0 }, size }; } @@ -1007,7 +1010,7 @@ struct expression_trace : public expression_with_traits<E> }; /** - * @brief Returns template expression that returns the result of calling \f$ fn(x_i, x_{i-1}) \f$ + * @brief Returns template expression that prints all processed values for debug */ template <typename E1> KFR_INTRINSIC expression_trace<E1> trace(E1&& e1) @@ -1017,5 +1020,51 @@ KFR_INTRINSIC expression_trace<E1> trace(E1&& e1) // ---------------------------------------------------------------------------- +template <index_t Dims, typename E> +struct expression_dimensions : public expression_with_traits<E> +{ + using expression_with_traits<E>::expression_with_traits; + using value_type = typename expression_with_traits<E>::value_type; + constexpr static inline index_t in_dims = expression_with_traits<E>::dims; + constexpr static inline index_t dims = Dims; + using first_arg_traits = typename expression_with_traits<E>::first_arg_traits; + + constexpr static shape<dims> shapeof(const expression_dimensions& self) + { + return first_arg_traits::shapeof(self.first()).template extend<dims>(infinite_size); + } + constexpr static shape<dims> shapeof() + { + return first_arg_traits::shapeof().template extend<dims>(infinite_size); + } + + template <size_t N, index_t VecAxis> + KFR_INTRINSIC friend vec<value_type, N> get_elements(const expression_dimensions& self, shape<dims> index, + axis_params<VecAxis, N> sh) + { + shape<in_dims> inindex = index.template trim<in_dims>(); + if constexpr (VecAxis >= in_dims) + { + return repeat<N>(get_elements(self.first(), inindex, axis_params_v<0, 1>)); + } + else + { + return get_elements(self.first(), inindex, sh); + } + } +}; + +/** + * @brief Returns template expression with gien number of dimensions + */ +template <index_t Dims, typename E1> +KFR_INTRINSIC expression_dimensions<Dims, E1> dimensions(E1&& e1) +{ + static_assert(Dims >= expression_dims<E1>, "Number of dimensions must be greater or equal"); + return { std::forward<E1>(e1) }; +} + +// ---------------------------------------------------------------------------- + } // namespace CMT_ARCH_NAME } // namespace kfr diff --git a/include/kfr/base/expression.hpp b/include/kfr/base/expression.hpp @@ -210,6 +210,23 @@ struct anything inline namespace CMT_ARCH_NAME { +namespace internal +{ +template <size_t width, typename Fn> +KFR_INTRINSIC void block_process_impl(size_t& i, size_t size, Fn&& fn) +{ + CMT_LOOP_NOUNROLL + for (; i < size / width * width; i += width) + fn(i, csize_t<width>()); +} +} // namespace internal + +template <size_t... widths, typename Fn> +KFR_INTRINSIC void block_process(size_t size, csizes_t<widths...>, Fn&& fn) +{ + size_t i = 0; + swallow{ (internal::block_process_impl<widths>(i, size, std::forward<Fn>(fn)), 0)... }; +} template <index_t Dims> KFR_INTRINSIC void begin_pass(const internal_generic::anything&, shape<Dims> start, shape<Dims> stop) diff --git a/include/kfr/base/filter.hpp b/include/kfr/base/filter.hpp @@ -91,7 +91,8 @@ public: template <univector_tag Tag, typename Expr, KFR_ENABLE_IF(is_input_expression<Expr>)> void apply(univector<T, Tag>& dest, const Expr& src) { - process_expression(dest.data(), to_handle(src), size_min(dest.size(), src.size())); + static_assert(expression_dims<Expr> == 1); + process_expression(dest.data(), to_handle(src), size_min(dest.size(), shapeof(src))); } template <typename Expr, KFR_ENABLE_IF(is_input_expression<Expr>)> diff --git a/include/kfr/base/generators.hpp b/include/kfr/base/generators.hpp @@ -40,6 +40,15 @@ namespace kfr inline namespace CMT_ARCH_NAME { +namespace internal +{ +template <typename T> +constexpr size_t generator_width(size_t divisor) +{ + return const_max(1, vector_capacity<deep_subtype<T>> / 8 / divisor); +} +} // namespace internal + template <typename T, size_t VecWidth, typename Class, typename Twork = T> struct generator : public expression_traits_defaults { @@ -99,7 +108,7 @@ private: } }; -template <typename T, size_t VecWidth = vector_capacity<T> / 8> +template <typename T, size_t VecWidth = internal::generator_width<T>(1)> struct generator_linear : public generator<T, VecWidth, generator_linear<T, VecWidth>> { generator_linear(T start, T step) CMT_NOEXCEPT : vstep{ step * VecWidth } { sync(start); } @@ -114,7 +123,7 @@ struct generator_linear : public generator<T, VecWidth, generator_linear<T, VecW T vstep; }; -template <typename T, size_t VecWidth = vector_capacity<T> / 8> +template <typename T, size_t VecWidth = internal::generator_width<T>(1)> struct generator_exp : public generator<T, VecWidth, generator_exp<T, VecWidth>> { generator_exp(T start, T step) CMT_NOEXCEPT : step{ step }, @@ -135,7 +144,7 @@ protected: T vstep; }; -template <typename T, size_t VecWidth = vector_capacity<deep_subtype<T>> / 8 / 2> +template <typename T, size_t VecWidth = internal::generator_width<T>(2)> struct generator_expj : public generator<T, VecWidth, generator_expj<T, VecWidth>> { using ST = deep_subtype<T>; @@ -164,7 +173,7 @@ protected: } }; -template <typename T, size_t VecWidth = vector_capacity<T> / 8> +template <typename T, size_t VecWidth = internal::generator_width<T>(1)> struct generator_exp2 : public generator<T, VecWidth, generator_exp2<T, VecWidth>> { generator_exp2(T start, T step) CMT_NOEXCEPT : step{ step }, @@ -185,7 +194,7 @@ protected: T vstep; }; -template <typename T, size_t VecWidth = vector_capacity<T> / 8> +template <typename T, size_t VecWidth = internal::generator_width<T>(1)> struct generator_cossin : public generator<T, VecWidth, generator_cossin<T, VecWidth>> { static_assert(VecWidth % 2 == 0); @@ -211,7 +220,7 @@ protected: } }; -template <typename T, size_t VecWidth = vector_capacity<T> / 8 / 2> +template <typename T, size_t VecWidth = internal::generator_width<T>(2)> struct generator_sin : public generator<T, VecWidth, generator_sin<T, VecWidth>, vec<T, 2>> { generator_sin(T start, T step) @@ -255,7 +264,7 @@ protected: x_i = start + i \cdot step \f] */ -template <typename T1, typename T2, typename TF = ftype<common_type<T1, T2>>> +template <typename T1, typename T2, typename TF = ftype<std::common_type_t<T1, T2>>> KFR_FUNCTION generator_linear<TF> gen_linear(T1 start, T2 step) { return generator_linear<TF>(start, step); @@ -267,7 +276,7 @@ KFR_FUNCTION generator_linear<TF> gen_linear(T1 start, T2 step) x_i = e^{ start + i \cdot step } \f] */ -template <typename T1, typename T2, typename TF = ftype<common_type<T1, T2>>> +template <typename T1, typename T2, typename TF = ftype<std::common_type_t<T1, T2>>> KFR_FUNCTION generator_exp<TF> gen_exp(T1 start, T2 step) { return generator_exp<TF>(start, step); @@ -279,7 +288,7 @@ KFR_FUNCTION generator_exp<TF> gen_exp(T1 start, T2 step) x_i = e^{ j ( start + i \cdot step ) } \f] */ -template <typename T1, typename T2, typename TF = complex<ftype<common_type<T1, T2>>>> +template <typename T1, typename T2, typename TF = complex<ftype<std::common_type_t<T1, T2>>>> KFR_FUNCTION generator_expj<TF> gen_expj(T1 start, T2 step) { return generator_expj<TF>(start, step); @@ -291,7 +300,7 @@ KFR_FUNCTION generator_expj<TF> gen_expj(T1 start, T2 step) x_i = 2^{ start + i \cdot step } \f] */ -template <typename T1, typename T2, typename TF = ftype<common_type<T1, T2>>> +template <typename T1, typename T2, typename TF = ftype<std::common_type_t<T1, T2>>> KFR_FUNCTION generator_exp2<TF> gen_exp2(T1 start, T2 step) { return generator_exp2<TF>(start, step); @@ -307,7 +316,7 @@ KFR_FUNCTION generator_exp2<TF> gen_exp2(T1 start, T2 step) \end{cases} \f] */ -template <typename T1, typename T2, typename TF = ftype<common_type<T1, T2>>> +template <typename T1, typename T2, typename TF = ftype<std::common_type_t<T1, T2>>> KFR_FUNCTION generator_cossin<TF> gen_cossin(T1 start, T2 step) { return generator_cossin<TF>(start, step); @@ -319,7 +328,7 @@ KFR_FUNCTION generator_cossin<TF> gen_cossin(T1 start, T2 step) x_i = \sin( start + i \cdot step ) \f] */ -template <typename T1, typename T2, typename TF = ftype<common_type<T1, T2>>> +template <typename T1, typename T2, typename TF = ftype<std::common_type_t<T1, T2>>> KFR_FUNCTION generator_sin<TF> gen_sin(T1 start, T2 step) { return generator_sin<TF>(start, step); diff --git a/include/kfr/base/impl/static_array.hpp b/include/kfr/base/impl/static_array.hpp @@ -63,6 +63,33 @@ struct static_array_base<T, csizes_t<indices...>> (static_cast<void>(array[indices] = args), ...); } + template <typename U, typename otherindices_t> + friend struct static_array_base; + + template <size_t... idx1, size_t... idx2> + KFR_MEM_INTRINSIC constexpr static_array_base(const static_array_base<T, csizes_t<idx1...>>& first, + const static_array_base<T, csizes_t<idx2...>>& second) + { + constexpr size_t size1 = sizeof...(idx1); + constexpr size_t size2 = sizeof...(idx2); + static_assert(size1 + size2 == static_size); + (static_cast<void>(array[indices] = + indices >= size1 ? second.array[indices - size1] : first.array[indices]), + ...); + } + + template <size_t... idx> + constexpr static_array_base<T, csizeseq_t<sizeof...(idx)>> shuffle(csizes_t<idx...>) const + { + return static_array_base<T, csizeseq_t<sizeof...(idx)>>{ array[idx]... }; + } + + template <size_t start, size_t size> + constexpr static_array_base<T, csizeseq_t<size>> slice() const + { + return shuffle(csizeseq<size, start>); + } + constexpr static_array_base& operator=(const static_array_base&) = default; constexpr static_array_base& operator=(static_array_base&&) = default; diff --git a/include/kfr/base/shape.hpp b/include/kfr/base/shape.hpp @@ -66,6 +66,23 @@ constexpr inline index_t infinite_size = max_index_t; constexpr inline index_t undefined_size = 0; constexpr inline index_t maximum_dims = 8; +CMT_INTRINSIC constexpr size_t size_add(size_t x, size_t y) +{ + return (x == infinite_size || y == infinite_size) ? infinite_size : x + y; +} + +CMT_INTRINSIC constexpr size_t size_sub(size_t x, size_t y) +{ + return (x == infinite_size || y == infinite_size) ? infinite_size : (x > y ? x - y : 0); +} + +CMT_INTRINSIC constexpr size_t size_min(size_t x) CMT_NOEXCEPT { return x; } + +template <typename... Ts> +CMT_INTRINSIC constexpr size_t size_min(size_t x, size_t y, Ts... rest) CMT_NOEXCEPT +{ + return size_min(x < y ? x : y, rest...); +} using dimset = vec<i8, maximum_dims>; @@ -84,6 +101,11 @@ struct shape : static_array_base<index_t, csizeseq_t<dims>> { using static_array_base<index_t, csizeseq_t<dims>>::static_array_base; + constexpr shape(const static_array_base<index_t, csizeseq_t<dims>>& a) + : static_array_base<index_t, csizeseq_t<dims>>(a) + { + } + static_assert(dims < maximum_dims); template <int dummy = 0, KFR_ENABLE_IF(dummy == 0 && dims == 1)> @@ -293,22 +315,22 @@ struct shape : static_array_base<index_t, csizeseq_t<dims>> } template <index_t new_dims> - KFR_MEM_INTRINSIC shape<new_dims> extend(index_t value = infinite_size) const + constexpr KFR_MEM_INTRINSIC shape<new_dims> extend(index_t value = infinite_size) const { static_assert(new_dims >= dims); if constexpr (new_dims == dims) return *this; else - return concat(broadcast<new_dims - dims>(value), **this); + return shape<new_dims>{ shape<new_dims - dims>(value), *this }; } template <index_t odims> - shape<odims> trim() const + constexpr shape<odims> trim() const { static_assert(odims <= dims); if constexpr (odims > 0) { - return slice<dims - odims, odims>(**this); + return this->template slice<dims - odims, odims>(); } else { @@ -316,11 +338,11 @@ struct shape : static_array_base<index_t, csizeseq_t<dims>> } } - KFR_MEM_INTRINSIC shape<dims - 1> trunc() const + constexpr KFR_MEM_INTRINSIC shape<dims - 1> trunc() const { if constexpr (dims > 1) { - return slice<0, dims - 1>(**this); + return this->template slice<0, dims - 1>(); } else { @@ -369,7 +391,7 @@ struct shape<0> KFR_MEM_INTRINSIC dimset tomask() const { return -1; } template <index_t new_dims> - KFR_MEM_INTRINSIC shape<new_dims> extend(index_t value = infinite_size) const + constexpr KFR_MEM_INTRINSIC shape<new_dims> extend(index_t value = infinite_size) const { if constexpr (new_dims == 0) return *this; @@ -378,7 +400,7 @@ struct shape<0> } template <index_t new_dims> - shape<new_dims> trim() const + constexpr shape<new_dims> trim() const { static_assert(new_dims == 0); return {}; diff --git a/include/kfr/cometa/cstring.hpp b/include/kfr/cometa/cstring.hpp @@ -32,7 +32,7 @@ struct cstring constexpr size_type size() const CMT_NOEXCEPT { return N; } template <size_t start, size_t count> - constexpr cstring<count> slice(csize_t<start>, csize_t<count>) const CMT_NOEXCEPT + constexpr cstring<count + 1> slice(csize_t<start>, csize_t<count>) const CMT_NOEXCEPT { return slice_impl(csizeseq<count, start>); } diff --git a/include/kfr/dft/fft.hpp b/include/kfr/dft/fft.hpp @@ -75,7 +75,7 @@ struct dft_stage virtual void dump() const { - printf("%s: \n\t%5zu,%5zu,%5zu,%5zu,%5zu,%5zu,%5zu, %d, %d, %d, %d\n", name ? name : "unnamed", radix, + printf("%s: %zu, %zu, %zu, %zu, %zu, %zu, %zu, %d, %d, %d, %d\n", name ? name : "unnamed", radix, stage_size, data_size, temp_size, repeats, out_offset, blocks, recursion, can_inplace, inplace, to_scratch); } diff --git a/include/kfr/dft/impl/convolution-impl.cpp b/include/kfr/dft/impl/convolution-impl.cpp @@ -186,7 +186,7 @@ void convolve_filter<T>::process_buffer(T* output, const T* input, size_t size) // z_k = y_k + overlap process(make_univector(output + processed, processing), - scratch2.slice(input_position) + overlap.slice(input_position)); + scratch2.slice(input_position, processing) + overlap.slice(input_position, processing)); input_position += processing; processed += processing; diff --git a/include/kfr/dft/impl/dft-fft.hpp b/include/kfr/dft/impl/dft-fft.hpp @@ -36,6 +36,32 @@ namespace kfr { +inline namespace CMT_ARCH_NAME +{ +namespace intrinsics +{ +struct name_test_impl +{ +}; +} // namespace intrinsics +} // namespace CMT_ARCH_NAME + +template <typename T, cpu_t cpu> +struct dft_name_impl +{ +}; + +template <typename Class> +inline const char* dft_name(Class*) +{ + constexpr static size_t prefix_len = ctype_name<intrinsics::name_test_impl>().length() - 14; + static constexpr cstring full_name = ctype_name<std::decay_t<Class>>(); + static constexpr cstring name_arch = + concat_cstring(full_name.slice(csize<prefix_len>), make_cstring("("), + make_cstring(CMT_STRINGIFY(CMT_ARCH_NAME)), make_cstring(")")); + return name_arch.c_str(); +} + #define DFT_STAGE_FN \ KFR_MEM_INTRINSIC void do_execute(cdirect_t, complex<T>* out, const complex<T>* in, u8* temp) final \ { \ diff --git a/include/kfr/dft/impl/dft-impl.hpp b/include/kfr/dft/impl/dft-impl.hpp @@ -84,7 +84,7 @@ struct dft_stage_fixed_impl : dft_stage<T> { dft_stage_fixed_impl(size_t, size_t iterations, size_t blocks) { - this->name = type_name<decltype(*this)>(); + this->name = dft_name(this); this->radix = fixed_radix; this->blocks = blocks; this->repeats = iterations; @@ -124,7 +124,7 @@ struct dft_stage_fixed_final_impl : dft_stage<T> { dft_stage_fixed_final_impl(size_t, size_t iterations, size_t blocks) { - this->name = type_name<decltype(*this)>(); + this->name = dft_name(this); this->radix = fixed_radix; this->blocks = blocks; this->repeats = iterations; @@ -160,32 +160,30 @@ inline auto apply_conj(E& e, ctrue_t) /// [0, N - 1, N - 2, N - 3, ..., 3, 2, 1] template <typename E> -struct fft_inverse : internal::expression_with_arguments<E> +struct fft_inverse : expression_with_traits<E> { - using value_type = value_type_of<E>; + using value_type = typename expression_with_traits<E>::value_type; - KFR_MEM_INTRINSIC fft_inverse(E&& expr) CMT_NOEXCEPT - : internal::expression_with_arguments<E>(std::forward<E>(expr)) - { - } + KFR_MEM_INTRINSIC fft_inverse(E&& expr) CMT_NOEXCEPT : expression_with_traits<E>(std::forward<E>(expr)) {} - friend KFR_INTRINSIC vec<value_type, 1> get_elements(const fft_inverse& self, cinput_t input, - size_t index, vec_shape<value_type, 1>) + friend KFR_INTRINSIC vec<value_type, 1> get_elements(const fft_inverse& self, shape<1> index, + axis_params<0, 1>) { - return self.argument_first(input, index == 0 ? 0 : self.size() - index, vec_shape<value_type, 1>()); + const size_t size = shapeof(self).front(); + return get_elements(self.first(), index.front() == 0 ? 0 : size - index, axis_params<0, 1>()); } template <size_t N> - friend KFR_MEM_INTRINSIC vec<value_type, N> get_elements(const fft_inverse& self, cinput_t input, - size_t index, vec_shape<value_type, N>) + friend KFR_MEM_INTRINSIC vec<value_type, N> get_elements(const fft_inverse& self, shape<1> index, + axis_params<0, N>) { - if (index == 0) + const size_t size = shapeof(self).front(); + if (index.front() == 0) { - return concat( - self.argument_first(input, index, vec_shape<value_type, 1>()), - reverse(self.argument_first(input, self.size() - (N - 1), vec_shape<value_type, N - 1>()))); + return concat(get_elements(self.first(), index, axis_params<0, 1>()), + reverse(get_elements(self.first(), size - (N - 1), axis_params<0, N - 1>()))); } - return reverse(self.argument_first(input, self.size() - index - (N - 1), vec_shape<value_type, N>())); + return reverse(get_elements(self.first(), size - index - (N - 1), axis_params<0, N>())); } }; @@ -201,7 +199,7 @@ struct dft_arblen_stage_impl : dft_stage<T> dft_arblen_stage_impl(size_t size) : size(size), fftsize(next_poweroftwo(size) * 2), plan(fftsize, dft_order::internal) { - this->name = type_name<decltype(*this)>(); + this->name = dft_name(this); this->radix = size; this->blocks = 1; this->repeats = 1; @@ -210,7 +208,7 @@ struct dft_arblen_stage_impl : dft_stage<T> this->temp_size = plan.temp_size; this->stage_size = size; - chirp_ = render(cexp(sqr(linspace(T(1) - size, size - T(1), size * 2 - 1, true, true)) * + chirp_ = render(cexp(sqr(linspace(T(1) - size, size - T(1), size * 2 - 1, true, ctrue)) * complex<T>(0, -1) * c_pi<T> / size)); ichirpp_ = render(truncate(padded(1 / slice(chirp_, 0, 2 * size - 1)), fftsize)); @@ -240,7 +238,7 @@ struct dft_arblen_stage_impl : dft_stage<T> xp_fft = xp_fft * ichirpp_; plan.execute(xp_fft.data(), xp_fft.data(), temp, ctrue); - make_univector(out, n) = xp_fft.slice(n - 1) * slice(chirp, n - 1) * invN2; + make_univector(out, n) = xp_fft.slice(n - 1, n) * slice(chirp, n - 1, n) * invN2; } const size_t size; @@ -258,7 +256,7 @@ struct dft_special_stage_impl : dft_stage<T> { dft_special_stage_impl() : stage1(radix1, size / radix1, 1), stage2(radix2, 1, size / radix2) { - this->name = type_name<decltype(*this)>(); + this->name = dft_name(this); this->radix = size; this->blocks = 1; this->repeats = 1; @@ -300,7 +298,7 @@ struct dft_stage_generic_impl : dft_stage<T> { dft_stage_generic_impl(size_t radix, size_t iterations, size_t blocks) { - this->name = type_name<decltype(*this)>(); + this->name = dft_name(this); this->radix = radix; this->blocks = blocks; this->repeats = iterations; @@ -406,7 +404,7 @@ struct dft_reorder_stage_impl : dft_stage<T> { dft_reorder_stage_impl(const int* radices, size_t count) : count(count) { - this->name = type_name<decltype(*this)>(); + this->name = dft_name(this); this->can_inplace = false; this->data_size = 0; std::copy(radices, radices + count, this->radices); diff --git a/include/kfr/dft/impl/fft-impl.hpp b/include/kfr/dft/impl/fft-impl.hpp @@ -432,7 +432,7 @@ struct fft_stage_impl : dft_stage<T> { fft_stage_impl(size_t stage_size) { - this->name = type_name<decltype(*this)>(); + this->name = dft_name(this); this->radix = 4; this->stage_size = stage_size; this->repeats = 4; @@ -471,7 +471,7 @@ struct fft_final_stage_impl : dft_stage<T> { fft_final_stage_impl(size_t) { - this->name = type_name<decltype(*this)>(); + this->name = dft_name(this); this->radix = size; this->stage_size = size; this->out_offset = size; @@ -568,7 +568,7 @@ struct fft_reorder_stage_impl : dft_stage<T> { fft_reorder_stage_impl(size_t stage_size) { - this->name = type_name<decltype(*this)>(); + this->name = dft_name(this); this->stage_size = stage_size; this->user = ilog2(stage_size); this->data_size = 0; @@ -590,7 +590,7 @@ struct fft_specialization; template <typename T> struct fft_specialization<T, 1> : dft_stage<T> { - fft_specialization(size_t) { this->name = type_name<decltype(*this)>(); } + fft_specialization(size_t) { this->name = dft_name(this); } constexpr static bool aligned = false; DFT_STAGE_FN @@ -607,7 +607,7 @@ struct fft_specialization<T, 1> : dft_stage<T> template <typename T> struct fft_specialization<T, 2> : dft_stage<T> { - fft_specialization(size_t) { this->name = type_name<decltype(*this)>(); } + fft_specialization(size_t) { this->name = dft_name(this); } constexpr static bool aligned = false; DFT_STAGE_FN @@ -624,7 +624,7 @@ struct fft_specialization<T, 2> : dft_stage<T> template <typename T> struct fft_specialization<T, 3> : dft_stage<T> { - fft_specialization(size_t) { this->name = type_name<decltype(*this)>(); } + fft_specialization(size_t) { this->name = dft_name(this); } constexpr static bool aligned = false; DFT_STAGE_FN @@ -640,7 +640,7 @@ struct fft_specialization<T, 3> : dft_stage<T> template <typename T> struct fft_specialization<T, 4> : dft_stage<T> { - fft_specialization(size_t) { this->name = type_name<decltype(*this)>(); } + fft_specialization(size_t) { this->name = dft_name(this); } constexpr static bool aligned = false; DFT_STAGE_FN @@ -656,7 +656,7 @@ struct fft_specialization<T, 4> : dft_stage<T> template <typename T> struct fft_specialization<T, 5> : dft_stage<T> { - fft_specialization(size_t) { this->name = type_name<decltype(*this)>(); } + fft_specialization(size_t) { this->name = dft_name(this); } constexpr static bool aligned = false; DFT_STAGE_FN @@ -672,7 +672,7 @@ struct fft_specialization<T, 5> : dft_stage<T> template <typename T> struct fft_specialization<T, 6> : dft_stage<T> { - fft_specialization(size_t) { this->name = type_name<decltype(*this)>(); } + fft_specialization(size_t) { this->name = dft_name(this); } constexpr static bool aligned = false; DFT_STAGE_FN @@ -689,7 +689,7 @@ struct fft_specialization<double, 7> : dft_stage<double> using T = double; fft_specialization(size_t) { - this->name = type_name<decltype(*this)>(); + this->name = dft_name(this); this->stage_size = 128; this->data_size = align_up(sizeof(complex<T>) * 128 * 3 / 2, platform<>::native_cache_alignment); } @@ -730,7 +730,7 @@ struct fft_specialization<float, 7> : dft_stage<float> using T = float; fft_specialization(size_t) { - this->name = type_name<decltype(*this)>(); + this->name = dft_name(this); this->stage_size = 128; this->data_size = align_up(sizeof(complex<T>) * 128 * 3 / 2, platform<>::native_cache_alignment); } @@ -769,7 +769,7 @@ struct fft_specialization<float, 8> : dft_stage<float> { fft_specialization(size_t) { - this->name = type_name<decltype(*this)>(); + this->name = dft_name(this); this->temp_size = sizeof(complex<float>) * 256; } @@ -812,7 +812,7 @@ struct fft_specialization<double, 8> : fft_final_stage_impl<double, false, 256> using T = double; fft_specialization(size_t stage_size) : fft_final_stage_impl<double, false, 256>(stage_size) { - this->name = type_name<decltype(*this)>(); + this->name = dft_name(this); } DFT_STAGE_FN @@ -830,7 +830,7 @@ struct fft_specialization<T, 9> : fft_final_stage_impl<T, false, 512> { fft_specialization(size_t stage_size) : fft_final_stage_impl<T, false, 512>(stage_size) { - this->name = type_name<decltype(*this)>(); + this->name = dft_name(this); } DFT_STAGE_FN @@ -848,7 +848,7 @@ struct fft_specialization<T, 10> : fft_final_stage_impl<T, false, 1024> { fft_specialization(size_t stage_size) : fft_final_stage_impl<T, false, 1024>(stage_size) { - this->name = type_name<decltype(*this)>(); + this->name = dft_name(this); } DFT_STAGE_FN diff --git a/include/kfr/dsp/units.hpp b/include/kfr/dsp/units.hpp @@ -40,7 +40,7 @@ using sample_rate_t = double; namespace intrinsics { template <typename T1, typename T2> -KFR_INTRINSIC common_type<T1, T2> fix_nans(const T1& val, const T2& replacement) +KFR_INTRINSIC std::common_type_t<T1, T2> fix_nans(const T1& val, const T2& replacement) { return select(val != val, replacement, val); } @@ -108,7 +108,7 @@ KFR_INTRINSIC TF hertz_to_note(const T& hertz) return intrinsics::log_fmadd(hertz, subtype<TF>(17.312340490667560888319096172023), offset); } -template <typename T1, typename T2, typename T3, typename Tc = flt_type<common_type<T1, T2, T3, f32>>> +template <typename T1, typename T2, typename T3, typename Tc = flt_type<std::common_type_t<T1, T2, T3, f32>>> KFR_INTRINSIC Tc note_to_hertz(const T1& note, const T2& tunenote, const T3& tunehertz) { const Tc offset = log(tunehertz) - tunenote * subtype<Tc>(0.05776226504666210911810267678818); @@ -116,7 +116,7 @@ KFR_INTRINSIC Tc note_to_hertz(const T1& note, const T2& tunenote, const T3& tun return intrinsics::exp_fmadd(note, subtype<Tc>(0.05776226504666210911810267678818), offset); } -template <typename T1, typename T2, typename T3, typename Tc = flt_type<common_type<T1, T2, T3, f32>>> +template <typename T1, typename T2, typename T3, typename Tc = flt_type<std::common_type_t<T1, T2, T3, f32>>> KFR_INTRINSIC Tc hertz_to_note(const T1& hertz, const T2& tunenote, const T3& tunehertz) { const Tc offset = tunenote - log(tunehertz) * subtype<Tc>(17.312340490667560888319096172023); diff --git a/include/kfr/graphics/impl/scaled.hpp b/include/kfr/graphics/impl/scaled.hpp @@ -36,7 +36,7 @@ template <typename Tout, int Mout, int Min, typename Tin, size_t N, (std::is_floating_point<Tin>::value || std::is_floating_point<Tout>::value))> KFR_INTRINSIC vec<Tout, N> convert_scaled(const vec<Tin, N>& value) { - using Tcommon = common_type<Tin, Tout>; + using Tcommon = std::common_type_t<Tin, Tout>; return static_cast<vec<Tout, N>>(static_cast<vec<Tcommon, N>>(value) * Mout / Min); } diff --git a/include/kfr/math/atan.hpp b/include/kfr/math/atan.hpp @@ -56,7 +56,7 @@ KFR_FUNCTION flt_type<T1> atandeg(const T1& x) * @brief Returns the arc tangent of y/x using the signs of arguments to determine the correct quadrant. */ template <typename T1, typename T2, KFR_ENABLE_IF(is_numeric_args<T1, T2>)> -KFR_FUNCTION common_type<T1, T2> atan2(const T1& x, const T2& y) +KFR_FUNCTION std::common_type_t<T1, T2> atan2(const T1& x, const T2& y) { return intrinsics::atan2(x, y); } @@ -66,7 +66,7 @@ KFR_FUNCTION common_type<T1, T2> atan2(const T1& x, const T2& y) * correct quadrant. */ template <typename T1, typename T2, KFR_ENABLE_IF(is_numeric_args<T1, T2>)> -KFR_FUNCTION common_type<T1, T2> atan2deg(const T1& x, const T2& y) +KFR_FUNCTION std::common_type_t<T1, T2> atan2deg(const T1& x, const T2& y) { return intrinsics::atan2deg(x, y); } diff --git a/include/kfr/math/impl/log_exp.hpp b/include/kfr/math/impl/log_exp.hpp @@ -289,25 +289,25 @@ KFR_HANDLE_NOT_F_1(root) KFR_HANDLE_NOT_F_1(cbrt) template <typename T1, typename T2> -KFR_INTRINSIC flt_type<common_type<T1, T2>> logn(const T1& a, const T2& b) +KFR_INTRINSIC flt_type<std::common_type_t<T1, T2>> logn(const T1& a, const T2& b) { return log(a) / log(b); } template <typename T1, typename T2> -KFR_INTRINSIC flt_type<common_type<T1, T2>> logm(const T1& a, const T2& b) +KFR_INTRINSIC flt_type<std::common_type_t<T1, T2>> logm(const T1& a, const T2& b) { return log(a) * b; } template <typename T1, typename T2, typename T3> -KFR_INTRINSIC flt_type<common_type<T1, T2, T3>> exp_fmadd(const T1& x, const T2& m, const T3& a) +KFR_INTRINSIC flt_type<std::common_type_t<T1, T2, T3>> exp_fmadd(const T1& x, const T2& m, const T3& a) { return exp(fmadd(x, m, a)); } template <typename T1, typename T2, typename T3> -KFR_INTRINSIC flt_type<common_type<T1, T2, T3>> log_fmadd(const T1& x, const T2& m, const T3& a) +KFR_INTRINSIC flt_type<std::common_type_t<T1, T2, T3>> log_fmadd(const T1& x, const T2& m, const T3& a) { return fmadd(log(x), m, a); } diff --git a/include/kfr/math/log_exp.hpp b/include/kfr/math/log_exp.hpp @@ -83,42 +83,42 @@ KFR_FUNCTION flt_type<T1> logb(const T1& x) /// @brief Returns the logarithm of the x with base y. template <typename T1, typename T2, KFR_ENABLE_IF(is_numeric_args<T1, T2>)> -KFR_FUNCTION flt_type<common_type<T1, T2>> logn(const T1& x, const T2& y) +KFR_FUNCTION flt_type<std::common_type_t<T1, T2>> logn(const T1& x, const T2& y) { return intrinsics::logn(x, y); } /// @brief Returns log(x) * y. template <typename T1, typename T2, KFR_ENABLE_IF(is_numeric_args<T1, T2>)> -KFR_FUNCTION flt_type<common_type<T1, T2>> logm(const T1& x, const T2& y) +KFR_FUNCTION flt_type<std::common_type_t<T1, T2>> logm(const T1& x, const T2& y) { return intrinsics::logm(x, y); } /// @brief Returns exp(x * m + a). template <typename T1, typename T2, typename T3, KFR_ENABLE_IF(is_numeric_args<T1, T2, T3>)> -KFR_FUNCTION flt_type<common_type<T1, T2, T3>> exp_fmadd(const T1& x, const T2& y, const T3& z) +KFR_FUNCTION flt_type<std::common_type_t<T1, T2, T3>> exp_fmadd(const T1& x, const T2& y, const T3& z) { return intrinsics::exp_fmadd(x, y, z); } /// @brief Returns log(x) * m + a. template <typename T1, typename T2, typename T3, KFR_ENABLE_IF(is_numeric_args<T1, T2, T3>)> -KFR_FUNCTION flt_type<common_type<T1, T2, T3>> log_fmadd(const T1& x, const T2& y, const T3& z) +KFR_FUNCTION flt_type<std::common_type_t<T1, T2, T3>> log_fmadd(const T1& x, const T2& y, const T3& z) { return intrinsics::log_fmadd(x, y, z); } /// @brief Returns the x raised to the given power y. template <typename T1, typename T2, KFR_ENABLE_IF(is_numeric_args<T1, T2>)> -KFR_FUNCTION flt_type<common_type<T1, T2>> pow(const T1& x, const T2& y) +KFR_FUNCTION flt_type<std::common_type_t<T1, T2>> pow(const T1& x, const T2& y) { return intrinsics::pow(x, y); } /// @brief Returns the real nth root of the x. template <typename T1, typename T2, KFR_ENABLE_IF(is_numeric_args<T1, T2>)> -KFR_FUNCTION flt_type<common_type<T1, T2>> root(const T1& x, const T2& y) +KFR_FUNCTION flt_type<std::common_type_t<T1, T2>> root(const T1& x, const T2& y) { return intrinsics::root(x, y); } diff --git a/include/kfr/simd/clamp.hpp b/include/kfr/simd/clamp.hpp @@ -34,7 +34,7 @@ inline namespace CMT_ARCH_NAME /// @brief Returns the first argument clamped to a range [lo, hi] template <typename T1, typename T2, typename T3, KFR_ENABLE_IF(is_numeric_args<T1, T2, T3>), - typename Tout = common_type<T1, T2, T3>> + typename Tout = std::common_type_t<T1, T2, T3>> KFR_INTRINSIC Tout clamp(const T1& x, const T2& lo, const T3& hi) { return intrinsics::clamp(static_cast<Tout>(x), static_cast<Tout>(lo), static_cast<Tout>(hi)); @@ -42,7 +42,7 @@ KFR_INTRINSIC Tout clamp(const T1& x, const T2& lo, const T3& hi) /// @brief Returns the first argument clamped to a range [0, hi] template <typename T1, typename T2, KFR_ENABLE_IF(is_numeric_args<T1, T2>), - typename Tout = common_type<T1, T2>> + typename Tout = std::common_type_t<T1, T2>> KFR_INTRINSIC Tout clamp(const T1& x, const T2& hi) { return intrinsics::clamp(static_cast<Tout>(x), static_cast<Tout>(hi)); diff --git a/include/kfr/simd/comparison.hpp b/include/kfr/simd/comparison.hpp @@ -35,32 +35,32 @@ inline namespace CMT_ARCH_NAME { template <typename T1, typename T2> -inline maskfor<common_type<T1, T2>> equal(const T1& x, const T2& y) +inline maskfor<std::common_type_t<T1, T2>> equal(const T1& x, const T2& y) { return x == y; } template <typename T1, typename T2> -inline maskfor<common_type<T1, T2>> notequal(const T1& x, const T2& y) +inline maskfor<std::common_type_t<T1, T2>> notequal(const T1& x, const T2& y) { return x != y; } template <typename T1, typename T2> -inline maskfor<common_type<T1, T2>> less(const T1& x, const T2& y) +inline maskfor<std::common_type_t<T1, T2>> less(const T1& x, const T2& y) { return x < y; } template <typename T1, typename T2> -inline maskfor<common_type<T1, T2>> greater(const T1& x, const T2& y) +inline maskfor<std::common_type_t<T1, T2>> greater(const T1& x, const T2& y) { return x > y; } template <typename T1, typename T2> -inline maskfor<common_type<T1, T2>> lessorequal(const T1& x, const T2& y) +inline maskfor<std::common_type_t<T1, T2>> lessorequal(const T1& x, const T2& y) { return x <= y; } template <typename T1, typename T2> -inline maskfor<common_type<T1, T2>> greaterorequal(const T1& x, const T2& y) +inline maskfor<std::common_type_t<T1, T2>> greaterorequal(const T1& x, const T2& y) { return x >= y; } @@ -108,7 +108,7 @@ KFR_INTRINSIC mask<T, N> iszero(const vec<T, N>& x) } template <typename T1, typename T2, typename T3> -KFR_INTRINSIC maskfor<common_type<T1, T2, T3>> inrange(const T1& x, const T2& min, const T3& max) +KFR_INTRINSIC maskfor<std::common_type_t<T1, T2, T3>> inrange(const T1& x, const T2& min, const T3& max) { return x >= min && x <= max; } diff --git a/include/kfr/simd/complex.hpp b/include/kfr/simd/complex.hpp @@ -82,22 +82,22 @@ KFR_INTRINSIC complex<T>& operator/=(complex<T>& x, const complex<T>& y) return x; } -template <typename T, typename U, KFR_ENABLE_IF(is_number<U>), typename C = common_type<complex<T>, U>> +template <typename T, typename U, KFR_ENABLE_IF(is_number<U>), typename C = std::common_type_t<complex<T>, U>> KFR_INTRINSIC C operator+(const complex<T>& x, const U& y) { return static_cast<C>(x) + static_cast<C>(y); } -template <typename T, typename U, KFR_ENABLE_IF(is_number<U>), typename C = common_type<complex<T>, U>> +template <typename T, typename U, KFR_ENABLE_IF(is_number<U>), typename C = std::common_type_t<complex<T>, U>> KFR_INTRINSIC C operator-(const complex<T>& x, const U& y) { return static_cast<C>(x) - static_cast<C>(y); } -template <typename T, typename U, KFR_ENABLE_IF(is_number<U>), typename C = common_type<complex<T>, U>> +template <typename T, typename U, KFR_ENABLE_IF(is_number<U>), typename C = std::common_type_t<complex<T>, U>> KFR_INTRINSIC C operator*(const complex<T>& x, const U& y) { return static_cast<C>(x) * static_cast<C>(y); } -template <typename T, typename U, KFR_ENABLE_IF(is_number<U>), typename C = common_type<complex<T>, U>> +template <typename T, typename U, KFR_ENABLE_IF(is_number<U>), typename C = std::common_type_t<complex<T>, U>> KFR_INTRINSIC C operator/(const complex<T>& x, const U& y) { return static_cast<C>(x) / static_cast<C>(y); @@ -127,22 +127,22 @@ KFR_INTRINSIC complex<T>& operator/=(complex<T>& x, const U& y) return x; } -template <typename T, typename U, KFR_ENABLE_IF(is_number<U>), typename C = common_type<complex<T>, U>> +template <typename T, typename U, KFR_ENABLE_IF(is_number<U>), typename C = std::common_type_t<complex<T>, U>> KFR_INTRINSIC C operator+(const U& x, const complex<T>& y) { return static_cast<C>(x) + static_cast<C>(y); } -template <typename T, typename U, KFR_ENABLE_IF(is_number<U>), typename C = common_type<complex<T>, U>> +template <typename T, typename U, KFR_ENABLE_IF(is_number<U>), typename C = std::common_type_t<complex<T>, U>> KFR_INTRINSIC C operator-(const U& x, const complex<T>& y) { return static_cast<C>(x) - static_cast<C>(y); } -template <typename T, typename U, KFR_ENABLE_IF(is_number<U>), typename C = common_type<complex<T>, U>> +template <typename T, typename U, KFR_ENABLE_IF(is_number<U>), typename C = std::common_type_t<complex<T>, U>> KFR_INTRINSIC C operator*(const U& x, const complex<T>& y) { return static_cast<C>(x) * static_cast<C>(y); } -template <typename T, typename U, KFR_ENABLE_IF(is_number<U>), typename C = common_type<complex<T>, U>> +template <typename T, typename U, KFR_ENABLE_IF(is_number<U>), typename C = std::common_type_t<complex<T>, U>> KFR_INTRINSIC C operator/(const U& x, const complex<T>& y) { return static_cast<C>(x) / static_cast<C>(y); @@ -393,7 +393,7 @@ constexpr KFR_INTRINSIC vec<T, N> imag(const vec<complex<T>, N>& value) KFR_FN(imag) /// @brief Constructs complex value from real and imaginary parts -template <typename T1, typename T2 = T1, size_t N, typename T = common_type<T1, T2>> +template <typename T1, typename T2 = T1, size_t N, typename T = std::common_type_t<T1, T2>> constexpr KFR_INTRINSIC vec<complex<T>, N> make_complex(const vec<T1, N>& real, const vec<T2, N>& imag = T2(0)) { @@ -401,7 +401,7 @@ constexpr KFR_INTRINSIC vec<complex<T>, N> make_complex(const vec<T1, N>& real, } /// @brief Constructs complex value from real and imaginary parts -template <typename T1, typename T2 = T1, typename T = common_type<T1, T2>, +template <typename T1, typename T2 = T1, typename T = std::common_type_t<T1, T2>, KFR_ENABLE_IF(is_numeric_args<T1, T2>)> constexpr KFR_INTRINSIC complex<T> make_complex(T1 real, T2 imag = T2(0)) { @@ -435,44 +435,24 @@ struct vec_of_complex using type = vec<complex<T>, N>; }; } // namespace CMT_ARCH_NAME +} // namespace kfr -template <typename T1, typename T2> -struct common_type_impl<kfr::complex<T1>, kfr::complex<T2>> : common_type_from_subtypes<T1, T2, kfr::complex> +namespace std { -}; + template <typename T1, typename T2> -struct common_type_impl<kfr::complex<T1>, T2> : common_type_from_subtypes<T1, T2, kfr::complex> +struct common_type<kfr::complex<T1>, kfr::complex<T2>> + : kfr::construct_common_type<std::common_type<T1, T2>, kfr::complex> { }; template <typename T1, typename T2> -struct common_type_impl<T1, kfr::complex<T2>> : common_type_from_subtypes<T1, T2, kfr::complex> -{ -}; -template <typename T1, typename T2, size_t N> -struct common_type_impl<kfr::complex<T1>, kfr::vec<kfr::complex<T2>, N>> - : common_type_from_subtypes<T1, T2, kfr::vec_of_complex<N>::template type> -{ -}; -template <typename T1, typename T2, size_t N> -struct common_type_impl<kfr::vec<kfr::complex<T1>, N>, kfr::vec<kfr::complex<T2>, N>> - : common_type_from_subtypes<T1, T2, kfr::vec_of_complex<N>::template type> -{ -}; -template <typename T1, typename T2, size_t N> -struct common_type_impl<kfr::vec<kfr::complex<T1>, N>, kfr::complex<T2>> - : common_type_from_subtypes<T1, T2, kfr::vec_of_complex<N>::template type> +struct common_type<kfr::complex<T1>, T2> : kfr::construct_common_type<std::common_type<T1, T2>, kfr::complex> { }; -template <typename T1, typename T2, size_t N> -struct common_type_impl<kfr::complex<T1>, kfr::vec<T2, N>> - : common_type_from_subtypes<T1, T2, kfr::vec_of_complex<N>::template type> -{ -}; -template <typename T1, typename T2, size_t N> -struct common_type_impl<kfr::vec<T1, N>, kfr::complex<T2>> - : common_type_from_subtypes<T1, T2, kfr::vec_of_complex<N>::template type> +template <typename T1, typename T2> +struct common_type<T1, kfr::complex<T2>> : kfr::construct_common_type<std::common_type<T1, T2>, kfr::complex> { }; -} // namespace kfr +} // namespace std CMT_PRAGMA_MSVC(warning(pop)) diff --git a/include/kfr/simd/impl/backend_generic.hpp b/include/kfr/simd/impl/backend_generic.hpp @@ -94,7 +94,7 @@ struct simd_small_array constexpr static size_t size = N; using packed_type = U; -#ifdef _MSC_VER +#ifdef CMT_COMPILER_IS_MSVC KFR_INTRINSIC constexpr simd_small_array() CMT_NOEXCEPT = default; #else KFR_INTRINSIC simd_small_array() CMT_NOEXCEPT {} @@ -120,13 +120,13 @@ struct simd_small_array<f32, 2, f64> constexpr static size_t size = 2; using packed_type = f64; -#ifdef _MSC_VER +#ifdef CMT_COMPILER_IS_MSVC KFR_MEM_INTRINSIC constexpr simd_small_array() CMT_NOEXCEPT = default; #else KFR_MEM_INTRINSIC simd_small_array() CMT_NOEXCEPT {} #endif -#ifdef _MSC_VER +#ifdef CMT_COMPILER_IS_MSVC // MSVC Internal Compiler Error workaround KFR_MEM_INTRINSIC constexpr simd_small_array(const simd_small_array& v) CMT_NOEXCEPT : whole(v.whole) {} KFR_MEM_INTRINSIC constexpr simd_small_array(simd_small_array&& v) CMT_NOEXCEPT : whole(v.whole) {} @@ -146,7 +146,7 @@ struct simd_small_array<f32, 2, f64> KFR_MEM_INTRINSIC simd_small_array(f32 x, f32 y) CMT_NOEXCEPT { -#ifdef _MSC_VER +#ifdef CMT_COMPILER_IS_MSVC #ifdef CMT_ARCH_SSE2 // whole = _mm_cvtsd_f64(_mm_castps_pd(_mm_setr_ps(x, y, x, y))); whole = _mm_cvtsd_f64(_mm_castps_pd(_mm_unpacklo_ps(_mm_set_ss(x), _mm_set_ss(y)))); @@ -289,7 +289,7 @@ KFR_SIMD_TYPE(f64, 2, float64x2_t); #endif // CMT_ARCH_NEON64 #endif // CMT_ARCH_NEON -#if defined CMT_COMPILER_MSVC +#if defined CMT_COMPILER_IS_MSVC #define KFR_i8sse_INDEX(x, i) x.m128i_i8[i] #define KFR_i16sse_INDEX(x, i) x.m128i_i16[i] #define KFR_i32sse_INDEX(x, i) x.m128i_i32[i] @@ -459,7 +459,7 @@ KFR_INTRIN_SHUFFLE_CONCAT(f32, 2, _mm_setr_ps(x.low, x.high, y.low, y.high)) KFR_INTRIN_SHUFFLE_SWAP(f32, 2, simd<f32, 2>(x.high, x.low)) #endif -#if defined CMT_COMPILER_MSVC && !defined CMT_COMPILER_CLANG && defined CMT_ARCH_X32 +#if defined CMT_COMPILER_IS_MSVC && defined CMT_ARCH_X32 KFR_INTRINSIC __m128i _mm_cvtsi64_si128(int64_t u) { __m128i r = _mm_setzero_si128(); @@ -1058,7 +1058,7 @@ KFR_INTRINSIC simd_array<T, N> to_simd_array(const simd<T, N>& x) CMT_NOEXCEPT return bitcast_anything<simd_array<T, N>>(x); } -#if defined CMT_COMPILER_MSVC +#if defined CMT_COMPILER_IS_MSVC template <typename T, size_t N, KFR_ENABLE_IF(!is_simd_small_array<simd<T, N>>)> KFR_INTRINSIC simd<T, N> from_simd_array(const simd_array<T, N>& x) CMT_NOEXCEPT @@ -1110,7 +1110,7 @@ template <typename T, size_t... indices, typename... Args, size_t N> KFR_INTRINSIC simd<T, N> simd_make_helper(csizes_t<indices...>, const Args&... args) CMT_NOEXCEPT { const T temp[] = { static_cast<T>(args)... }; - return simd_make(ctype<T>, temp[indices]...); + return simd_make(cometa::ctype<T>, temp[indices]...); } /// @brief Returns vector with undefined value @@ -1142,7 +1142,7 @@ KFR_INTRINSIC simd<Tout, N> simd_allones() CMT_NOEXCEPT /// @brief Converts input vector to vector with subtype Tout template <typename Tout, typename Tin, size_t N, size_t Nout = (sizeof(Tin) * N / sizeof(Tout)) -#ifdef _MSC_VER +#ifdef CMT_COMPILER_IS_MSVC , KFR_ENABLE_IF((Nout == 1 || N == 1) && !std::is_same_v<Tout, Tin>) #else @@ -1158,7 +1158,7 @@ KFR_INTRINSIC simd<Tout, Nout> simd_bitcast(simd_cvt_t<Tout, Tin, N>, const simd /// @brief Converts input vector to vector with subtype Tout template <typename Tout, typename Tin, size_t N, size_t Nout = (sizeof(Tin) * N / sizeof(Tout)) -#ifdef _MSC_VER +#ifdef CMT_COMPILER_IS_MSVC , KFR_ENABLE_IF(Nout > 1 && N > 1 && !std::is_same_v<Tout, Tin>) #else @@ -1296,7 +1296,7 @@ KFR_INTRINSIC simd<T, Nout> simd_shuffle(simd_t<T, N>, const simd<T, N>& x, csiz overload_generic) CMT_NOEXCEPT { not_optimized(CMT_FUNC_SIGNATURE); -#ifdef CMT_COMPILER_MSVC +#ifdef CMT_COMPILER_IS_MSVC const simd_array<T, N> xx = to_simd_array<T, N>(x); constexpr static unsigned indices_array[] = { static_cast<unsigned>(indices)... }; return from_simd_array<T, Nout>(simd_shuffle_generic<T, Nout, N>(xx, indices_array)); @@ -1312,7 +1312,7 @@ KFR_INTRINSIC simd<T, Nout> simd_shuffle(simd2_t<T, N, N>, const simd<T, N>& x, { static_assert(N == N2, ""); not_optimized(CMT_FUNC_SIGNATURE); -#ifdef CMT_COMPILER_MSVC +#ifdef CMT_COMPILER_IS_MSVC const simd_array<T, N> xx = to_simd_array<T, N>(x); const simd_array<T, N> yy = to_simd_array<T, N>(y); constexpr static unsigned indices_array[] = { static_cast<unsigned>(indices)... }; @@ -1332,7 +1332,7 @@ KFR_INTRINSIC simd<T, Nout> simd_shuffle(simd2_t<T, N1, N2>, const simd<T, N1>& { not_optimized(CMT_FUNC_SIGNATURE); -#ifdef CMT_COMPILER_MSVC +#ifdef CMT_COMPILER_IS_MSVC const simd_array<T, N1> xx = to_simd_array<T, N1>(x); const simd_array<T, N2> yy = to_simd_array<T, N2>(y); constexpr static unsigned indices_array[] = { static_cast<unsigned>(indices)... }; @@ -1388,7 +1388,7 @@ KFR_INTRINSIC simd<Tout, N> simd_convert__(const simd<Tin, N>& x, csizes_t<indic template <typename Tout, typename Tin, KFR_ENABLE_IF(!std::is_same<Tout, Tin>::value)> KFR_INTRINSIC simd<Tout, 1> simd_convert(simd_cvt_t<Tout, Tin, 1>, const simd<Tin, 1>& x) CMT_NOEXCEPT { - return simd_make(ctype<Tout>, static_cast<Tout>(x)); + return simd_make(cometa::ctype<Tout>, static_cast<Tout>(x)); } /// @brief Converts input vector to vector with subtype Tout @@ -1452,7 +1452,7 @@ KFR_INTRINSIC simd<T, N> simd_set_element(const simd<T, N>& value, size_t index, template <typename T, size_t Nout, size_t Nin> KFR_INTRINSIC simd<T, Nout> simd_from_partial(simd2_t<T, Nout, Nin>, const simd<T, Nin>& x) { -#ifdef _MSC_VER +#ifdef CMT_COMPILER_IS_MSVC union { simd<T, Nin> in; diff --git a/include/kfr/simd/impl/function.hpp b/include/kfr/simd/impl/function.hpp @@ -42,7 +42,7 @@ inline namespace CMT_ARCH_NAME } #define KFR_HANDLE_SCALAR(fn) \ - template <typename T1, typename... Args, typename Tout = ::kfr::common_type<T1, Args...>, \ + template <typename T1, typename... Args, typename Tout = std::common_type_t<T1, Args...>, \ KFR_ENABLE_IF(!(is_vec<T1> || (is_vec<Args> || ...)))> \ KFR_INTRINSIC Tout fn(const T1& a, const Args&... b) CMT_NOEXCEPT \ { \ @@ -51,7 +51,7 @@ inline namespace CMT_ARCH_NAME } #define KFR_HANDLE_SCALAR_1_T(fn, Tout) \ - template <typename T1, typename... Args, typename T = ::kfr::common_type<T1, Args...>, \ + template <typename T1, typename... Args, typename T = std::common_type_t<T1, Args...>, \ KFR_ENABLE_IF(!(is_vec<T1> || (is_vec<Args> || ...)))> \ KFR_INTRINSIC Tout fn(const T1& a, const Args&... b) CMT_NOEXCEPT \ { \ @@ -60,7 +60,7 @@ inline namespace CMT_ARCH_NAME } #define KFR_HANDLE_ARGS_T(fn, Tout) \ - template <typename T1, typename... Args, typename T = ::kfr::common_type<T1, Args...>, \ + template <typename T1, typename... Args, typename T = std::common_type_t<T1, Args...>, \ KFR_ENABLE_IF((is_vec<T1> || (is_vec<Args> || ...)))> \ KFR_INTRINSIC Tout fn(const T1& a, const Args&... b) CMT_NOEXCEPT \ { \ diff --git a/include/kfr/simd/impl/operators.hpp b/include/kfr/simd/impl/operators.hpp @@ -50,31 +50,31 @@ namespace intrinsics } #define KFR_VECVEC_OP2(fn) \ - template <typename T1, typename T2, size_t N1, size_t N2, typename C = common_type<T1, T2>, \ + template <typename T1, typename T2, size_t N1, size_t N2, typename C = std::common_type_t<T1, T2>, \ KFR_ENABLE_IF(is_simd_type<C>)> \ KFR_INTRINSIC vec<vec<C, N1>, N2> fn(const vec<vec<T1, N1>, N2>& x, const vec<vec<T2, N1>, N2>& y) \ { \ return fn(broadcastto<C>(x.flatten()), broadcastto<C>(y.flatten())).v; \ } \ - template <typename T1, typename T2, size_t N1, size_t N2, typename C = common_type<T1, T2>, \ + template <typename T1, typename T2, size_t N1, size_t N2, typename C = std::common_type_t<T1, T2>, \ KFR_ENABLE_IF(is_simd_type<C>)> \ KFR_INTRINSIC vec<vec<C, N1>, N2> fn(const vec<vec<T1, N1>, N2>& x, const T2& y) \ { \ return fn(broadcastto<C>(x.flatten()), broadcastto<C>(y)).v; \ } \ - template <typename T1, typename T2, size_t N1, size_t N2, typename C = common_type<T1, T2>, \ + template <typename T1, typename T2, size_t N1, size_t N2, typename C = std::common_type_t<T1, T2>, \ KFR_ENABLE_IF(is_simd_type<C>)> \ KFR_INTRINSIC vec<vec<C, N1>, N2> fn(const vec<vec<T1, N1>, N2>& x, const vec<T2, N1>& y) \ { \ return fn(broadcastto<C>(x.flatten()), repeat<N2>(broadcastto<C>(y.flatten()))).v; \ } \ - template <typename T1, typename T2, size_t N1, size_t N2, typename C = common_type<T1, T2>, \ + template <typename T1, typename T2, size_t N1, size_t N2, typename C = std::common_type_t<T1, T2>, \ KFR_ENABLE_IF(is_simd_type<C>)> \ KFR_INTRINSIC vec<vec<C, N1>, N2> fn(const T1& x, const vec<vec<T2, N1>, N2>& y) \ { \ return fn(broadcastto<C>(x), broadcastto<C>(y.flatten())).v; \ } \ - template <typename T1, typename T2, size_t N1, size_t N2, typename C = common_type<T1, T2>, \ + template <typename T1, typename T2, size_t N1, size_t N2, typename C = std::common_type_t<T1, T2>, \ KFR_ENABLE_IF(is_simd_type<C>)> \ KFR_INTRINSIC vec<vec<C, N1>, N2> fn(const vec<T1, N1>& x, const vec<vec<T2, N1>, N2>& y) \ { \ diff --git a/include/kfr/simd/impl/saturation.hpp b/include/kfr/simd/impl/saturation.hpp @@ -175,7 +175,7 @@ KFR_HANDLE_ALL_SIZES_2(satsub) #else // fallback -template <typename T, size_t N, KFR_ENABLE_IF(is_signed<T>)> +template <typename T, size_t N, KFR_ENABLE_IF(std::is_signed_v<T>)> KFR_INTRINSIC vec<T, N> satadd(const vec<T, N>& a, const vec<T, N>& b) { return saturated_signed_add(a, b); @@ -185,7 +185,7 @@ KFR_INTRINSIC vec<T, N> satadd(const vec<T, N>& a, const vec<T, N>& b) { return saturated_unsigned_add(a, b); } -template <typename T, size_t N, KFR_ENABLE_IF(is_signed<T>)> +template <typename T, size_t N, KFR_ENABLE_IF(std::is_signed_v<T>)> KFR_INTRINSIC vec<T, N> satsub(const vec<T, N>& a, const vec<T, N>& b) { return saturated_signed_sub(a, b); diff --git a/include/kfr/simd/impl/select.hpp b/include/kfr/simd/impl/select.hpp @@ -320,7 +320,7 @@ KFR_INTRINSIC vec<T, N> select(const vec<bit<T>, N>& m, const T& x, const vec<T, } #endif template <typename T1, typename T2> -KFR_INTRINSIC common_type<T1, T2> select(bool m, const T1& x, const T2& y) +KFR_INTRINSIC std::common_type_t<T1, T2> select(bool m, const T1& x, const T2& y) { return m ? x : y; } diff --git a/include/kfr/simd/min_max.hpp b/include/kfr/simd/min_max.hpp @@ -36,7 +36,7 @@ inline namespace CMT_ARCH_NAME * @brief Returns the smaller of two values. */ template <typename T1, typename T2, KFR_ENABLE_IF(is_numeric_args<T1, T2>), - typename Tout = common_type<T1, T2>> + typename Tout = std::common_type_t<T1, T2>> KFR_INTRINSIC Tout min(const T1& x, const T2& y) { return intrinsics::min(x, y); @@ -46,7 +46,7 @@ KFR_INTRINSIC Tout min(const T1& x, const T2& y) * @brief Returns the greater of two values. */ template <typename T1, typename T2, KFR_ENABLE_IF(is_numeric_args<T1, T2>), - typename Tout = common_type<T1, T2>> + typename Tout = std::common_type_t<T1, T2>> KFR_INTRINSIC Tout max(const T1& x, const T2& y) { return intrinsics::max(x, y); @@ -56,7 +56,7 @@ KFR_INTRINSIC Tout max(const T1& x, const T2& y) * @brief Returns the smaller in magnitude of two values. */ template <typename T1, typename T2, KFR_ENABLE_IF(is_numeric_args<T1, T2>), - typename Tout = common_type<T1, T2>> + typename Tout = std::common_type_t<T1, T2>> KFR_INTRINSIC Tout absmin(const T1& x, const T2& y) { return intrinsics::absmin(x, y); @@ -66,7 +66,7 @@ KFR_INTRINSIC Tout absmin(const T1& x, const T2& y) * @brief Returns the greater in magnitude of two values. */ template <typename T1, typename T2, KFR_ENABLE_IF(is_numeric_args<T1, T2>), - typename Tout = common_type<T1, T2>> + typename Tout = std::common_type_t<T1, T2>> KFR_INTRINSIC Tout absmax(const T1& x, const T2& y) { return intrinsics::absmax(x, y); diff --git a/include/kfr/simd/operators.hpp b/include/kfr/simd/operators.hpp @@ -55,19 +55,19 @@ inline namespace CMT_ARCH_NAME x = intrinsics::fn(x, T1(y)); \ return x; \ } \ - template <typename T1, typename T2, size_t N, typename C = common_type<T1, T2>, \ + template <typename T1, typename T2, size_t N, typename C = std::common_type_t<T1, T2>, \ KFR_ENABLE_IF(1 + vec_rank<T1> > vec_rank<T2>)> \ constexpr KFR_INTRINSIC vec<C, N> operator op(const vec<T1, N>& x, const T2& y) \ { \ return intrinsics::fn(promoteto<C>(x), C(y)); \ } \ - template <typename T1, typename T2, size_t N, typename C = common_type<T1, T2>, \ + template <typename T1, typename T2, size_t N, typename C = std::common_type_t<T1, T2>, \ KFR_ENABLE_IF(vec_rank<T1> < 1 + vec_rank<T2>)> \ constexpr KFR_INTRINSIC vec<C, N> operator op(const T1& x, const vec<T2, N>& y) \ { \ return intrinsics::fn(C(x), promoteto<C>(y)); \ } \ - template <typename T1, typename T2, size_t N, typename C = common_type<T1, T2>, \ + template <typename T1, typename T2, size_t N, typename C = std::common_type_t<T1, T2>, \ KFR_ENABLE_IF(vec_rank<T1> == vec_rank<T2>)> \ constexpr KFR_INTRINSIC vec<C, N> operator op(const vec<T1, N>& x, const vec<T2, N>& y) \ { \ @@ -104,19 +104,19 @@ inline namespace CMT_ARCH_NAME } #define KFR_VEC_CMP_OPERATOR(op, fn) \ - template <typename T1, typename T2, size_t N, typename C = common_type<T1, T2>, \ + template <typename T1, typename T2, size_t N, typename C = std::common_type_t<T1, T2>, \ KFR_ENABLE_IF(1 + vec_rank<T1> > vec_rank<T2>)> \ constexpr KFR_INTRINSIC mask<C, N> operator op(const vec<T1, N>& x, const T2& y) \ { \ return intrinsics::fn(promoteto<C>(x), vec<C, N>(y)).asmask(); \ } \ - template <typename T1, typename T2, size_t N, typename C = common_type<T1, T2>, \ + template <typename T1, typename T2, size_t N, typename C = std::common_type_t<T1, T2>, \ KFR_ENABLE_IF(vec_rank<T1> < 1 + vec_rank<T2>)> \ constexpr KFR_INTRINSIC mask<C, N> operator op(const T1& x, const vec<T2, N>& y) \ { \ return intrinsics::fn(vec<C, N>(x), promoteto<C>(y)).asmask(); \ } \ - template <typename T1, typename T2, size_t N, typename C = common_type<T1, T2>, \ + template <typename T1, typename T2, size_t N, typename C = std::common_type_t<T1, T2>, \ KFR_ENABLE_IF(vec_rank<T1> == vec_rank<T2>)> \ constexpr KFR_INTRINSIC mask<C, N> operator op(const vec<T1, N>& x, const vec<T2, N>& y) \ { \ @@ -145,31 +145,31 @@ KFR_VEC_CMP_OPERATOR(<=, le) KFR_VEC_CMP_OPERATOR(>, gt) KFR_VEC_CMP_OPERATOR(<, lt) -template <typename T1, typename T2, size_t N, typename C = common_type<T1, T2>, +template <typename T1, typename T2, size_t N, typename C = std::common_type_t<T1, T2>, KFR_ENABLE_IF(sizeof(T1) == sizeof(T2))> KFR_INTRINSIC mask<C, N> operator&(const mask<T1, N>& x, const mask<T2, N>& y) CMT_NOEXCEPT { return mask<C, N>((bitcast<C>(vec<T1, N>(x.v)) & bitcast<C>(vec<T2, N>(y.v))).v); } -template <typename T1, typename T2, size_t N, typename C = common_type<T1, T2>, +template <typename T1, typename T2, size_t N, typename C = std::common_type_t<T1, T2>, KFR_ENABLE_IF(sizeof(T1) == sizeof(T2))> KFR_INTRINSIC mask<C, N> operator|(const mask<T1, N>& x, const mask<T2, N>& y) CMT_NOEXCEPT { return mask<C, N>((bitcast<C>(vec<T1, N>(x.v)) | bitcast<C>(vec<T2, N>(y.v))).v); } -template <typename T1, typename T2, size_t N, typename C = common_type<T1, T2>, +template <typename T1, typename T2, size_t N, typename C = std::common_type_t<T1, T2>, KFR_ENABLE_IF(sizeof(T1) == sizeof(T2))> KFR_INTRINSIC mask<C, N> operator&&(const mask<T1, N>& x, const mask<T2, N>& y) CMT_NOEXCEPT { return mask<C, N>((bitcast<C>(vec<T1, N>(x.v)) & bitcast<C>(vec<T2, N>(y.v))).v); } -template <typename T1, typename T2, size_t N, typename C = common_type<T1, T2>, +template <typename T1, typename T2, size_t N, typename C = std::common_type_t<T1, T2>, KFR_ENABLE_IF(sizeof(T1) == sizeof(T2))> KFR_INTRINSIC mask<C, N> operator||(const mask<T1, N>& x, const mask<T2, N>& y) CMT_NOEXCEPT { return mask<C, N>((bitcast<C>(vec<T1, N>(x.v)) | bitcast<C>(vec<T2, N>(y.v))).v); } -template <typename T1, typename T2, size_t N, typename C = common_type<T1, T2>, +template <typename T1, typename T2, size_t N, typename C = std::common_type_t<T1, T2>, KFR_ENABLE_IF(sizeof(T1) == sizeof(T2))> KFR_INTRINSIC mask<C, N> operator^(const mask<T1, N>& x, const mask<T2, N>& y) CMT_NOEXCEPT { @@ -208,7 +208,7 @@ KFR_FN(bitwisenot) /// @brief Bitwise And template <typename T1, typename T2> -KFR_INTRINSIC common_type<T1, T2> bitwiseand(const T1& x, const T2& y) +KFR_INTRINSIC std::common_type_t<T1, T2> bitwiseand(const T1& x, const T2& y) { return x & y; } @@ -221,7 +221,7 @@ KFR_FN(bitwiseand) /// @brief Bitwise And-Not template <typename T1, typename T2> -KFR_INTRINSIC common_type<T1, T2> bitwiseandnot(const T1& x, const T2& y) +KFR_INTRINSIC std::common_type_t<T1, T2> bitwiseandnot(const T1& x, const T2& y) { return x & ~y; } @@ -234,7 +234,7 @@ KFR_FN(bitwiseandnot) /// @brief Bitwise Or template <typename T1, typename T2> -KFR_INTRINSIC common_type<T1, T2> bitwiseor(const T1& x, const T2& y) +KFR_INTRINSIC std::common_type_t<T1, T2> bitwiseor(const T1& x, const T2& y) { return x | y; } @@ -247,7 +247,7 @@ KFR_FN(bitwiseor) /// @brief Bitwise Xor (Exclusive Or) template <typename T1, typename T2> -KFR_INTRINSIC common_type<T1, T2> bitwisexor(const T1& x, const T2& y) +KFR_INTRINSIC std::common_type_t<T1, T2> bitwisexor(const T1& x, const T2& y) { return x ^ y; } @@ -300,7 +300,7 @@ constexpr KFR_INTRINSIC T add(const T& x) * @brief Returns sum of all the arguments passed to a function. */ template <typename T1, typename T2, typename... Ts, KFR_ENABLE_IF(is_numeric_args<T1, T2, Ts...>)> -constexpr KFR_INTRINSIC common_type<T1, T2, Ts...> add(const T1& x, const T2& y, const Ts&... rest) +constexpr KFR_INTRINSIC std::common_type_t<T1, T2, Ts...> add(const T1& x, const T2& y, const Ts&... rest) { return x + add(y, rest...); } @@ -312,7 +312,7 @@ constexpr KFR_INTRINSIC T add(initialvalue<T>) KFR_FN(add) template <typename T1, typename T2> -constexpr KFR_INTRINSIC common_type<T1, T2> sub(const T1& x, const T2& y) +constexpr KFR_INTRINSIC std::common_type_t<T1, T2> sub(const T1& x, const T2& y) { return x - y; } @@ -333,7 +333,7 @@ constexpr KFR_INTRINSIC T1 mul(const T1& x) * @brief Returns product of all the arguments passed to a function. */ template <typename T1, typename T2, typename... Ts> -constexpr KFR_INTRINSIC common_type<T1, T2, Ts...> mul(const T1& x, const T2& y, const Ts&... rest) +constexpr KFR_INTRINSIC std::common_type_t<T1, T2, Ts...> mul(const T1& x, const T2& y, const Ts&... rest) { return x * mul(y, rest...); } @@ -419,13 +419,13 @@ KFR_FN(ipow) /// CHECK(sqrsum(1,2,3) == 36); /// @endcode template <typename T1, typename... Ts> -constexpr inline common_type<T1, Ts...> sqrsum(const T1& x, const Ts&... rest) +constexpr inline std::common_type_t<T1, Ts...> sqrsum(const T1& x, const Ts&... rest) { return sqr(add(x, rest...)); } template <typename T1, typename T2> -constexpr inline common_type<T1, T2> sqrdiff(const T1& x, const T2& y) +constexpr inline std::common_type_t<T1, T2> sqrdiff(const T1& x, const T2& y) { return sqr(x - y); } @@ -433,7 +433,7 @@ KFR_FN(sqrsum) KFR_FN(sqrdiff) /// Division -template <typename T1, typename T2, typename Tout = common_type<T1, T2>> +template <typename T1, typename T2, typename Tout = std::common_type_t<T1, T2>> KFR_INTRINSIC Tout div(const T1& x, const T2& y) { return static_cast<Tout>(x) / static_cast<Tout>(y); @@ -441,14 +441,14 @@ KFR_INTRINSIC Tout div(const T1& x, const T2& y) KFR_FN(div) /// Modulo -template <typename T1, typename T2, typename Tout = common_type<T1, T2>> +template <typename T1, typename T2, typename Tout = std::common_type_t<T1, T2>> KFR_INTRINSIC Tout mod(const T1& x, const T2& y) { return static_cast<Tout>(x) % static_cast<Tout>(y); } KFR_FN(mod) /// Remainder -template <typename T1, typename T2, typename Tout = common_type<T1, T2>> +template <typename T1, typename T2, typename Tout = std::common_type_t<T1, T2>> KFR_INTRINSIC Tout rem(const T1& x, const T2& y) { return static_cast<Tout>(x) % static_cast<Tout>(y); @@ -465,13 +465,13 @@ KFR_FN(neg) /// @brief Fused Multiply-Add template <typename T1, typename T2, typename T3> -KFR_INTRINSIC constexpr common_type<T1, T2, T3> fmadd(const T1& x, const T2& y, const T3& z) +KFR_INTRINSIC constexpr std::common_type_t<T1, T2, T3> fmadd(const T1& x, const T2& y, const T3& z) { return x * y + z; } /// @brief Fused Multiply-Sub template <typename T1, typename T2, typename T3> -KFR_INTRINSIC constexpr common_type<T1, T2, T3> fmsub(const T1& x, const T2& y, const T3& z) +KFR_INTRINSIC constexpr std::common_type_t<T1, T2, T3> fmsub(const T1& x, const T2& y, const T3& z) { return x * y - z; } @@ -481,14 +481,14 @@ KFR_FN(fmsub) /// @brief Linear blend of `x` and `y` (`c` must be in the range 0...+1) /// Returns `x + ( y - x ) * c` template <typename T1, typename T2, typename T3, KFR_ENABLE_IF(is_numeric_args<T1, T2, T3>)> -KFR_INTRINSIC constexpr common_type<T1, T2, T3> mix(const T1& c, const T2& x, const T3& y) +KFR_INTRINSIC constexpr std::common_type_t<T1, T2, T3> mix(const T1& c, const T2& x, const T3& y) { return fmadd(c, y - x, x); } /// @brief Linear blend of `x` and `y` (`c` must be in the range -1...+1) template <typename T1, typename T2, typename T3, KFR_ENABLE_IF(is_numeric_args<T1, T2, T3>)> -KFR_INTRINSIC constexpr common_type<T1, T2, T3> mixs(const T1& c, const T2& x, const T3& y) +KFR_INTRINSIC constexpr std::common_type_t<T1, T2, T3> mixs(const T1& c, const T2& x, const T3& y) { return mix(fmadd(c, 0.5, 0.5), x, y); } @@ -499,41 +499,41 @@ namespace intrinsics { template <typename T1, typename T2> -constexpr KFR_INTRINSIC common_type<T1, T2> horner(const T1&, const T2& c0) +constexpr KFR_INTRINSIC std::common_type_t<T1, T2> horner(const T1&, const T2& c0) { return c0; } template <typename T1, typename T2, typename T3, typename... Ts> -constexpr KFR_INTRINSIC common_type<T1, T2, T3, Ts...> horner(const T1& x, const T2& c0, const T3& c1, - const Ts&... values) +constexpr KFR_INTRINSIC std::common_type_t<T1, T2, T3, Ts...> horner(const T1& x, const T2& c0, const T3& c1, + const Ts&... values) { return fmadd(horner(x, c1, values...), x, c0); } template <typename T1, typename T2> -constexpr KFR_INTRINSIC common_type<T1, T2> horner_even(const T1&, const T2& c0) +constexpr KFR_INTRINSIC std::common_type_t<T1, T2> horner_even(const T1&, const T2& c0) { return c0; } template <typename T1, typename T2, typename T3, typename... Ts> -constexpr KFR_INTRINSIC common_type<T1, T2, T3, Ts...> horner_even(const T1& x, const T2& c0, const T3& c2, - const Ts&... values) +constexpr KFR_INTRINSIC std::common_type_t<T1, T2, T3, Ts...> horner_even(const T1& x, const T2& c0, + const T3& c2, const Ts&... values) { const T1 x2 = x * x; return fmadd(horner(x2, c2, values...), x2, c0); } template <typename T1, typename T2> -constexpr KFR_INTRINSIC common_type<T1, T2> horner_odd(const T1& x, const T2& c1) +constexpr KFR_INTRINSIC std::common_type_t<T1, T2> horner_odd(const T1& x, const T2& c1) { return c1 * x; } template <typename T1, typename T2, typename T3, typename... Ts> -constexpr KFR_INTRINSIC common_type<T1, T2, T3, Ts...> horner_odd(const T1& x, const T2& c1, const T3& c3, - const Ts&... values) +constexpr KFR_INTRINSIC std::common_type_t<T1, T2, T3, Ts...> horner_odd(const T1& x, const T2& c1, + const T3& c3, const Ts&... values) { const T1 x2 = x * x; return fmadd(horner(x2, c3, values...), x2, c1) * x; @@ -544,7 +544,7 @@ constexpr KFR_INTRINSIC common_type<T1, T2, T3, Ts...> horner_odd(const T1& x, c /// /// ``horner(x, 1, 2, 3)`` is equivalent to \(3x^2 + 2x + 1\) template <typename T1, typename... Ts, KFR_ENABLE_IF(is_numeric_args<T1, Ts...>)> -constexpr KFR_INTRINSIC common_type<T1, Ts...> horner(const T1& x, const Ts&... c) +constexpr KFR_INTRINSIC std::common_type_t<T1, Ts...> horner(const T1& x, const Ts&... c) { return intrinsics::horner(x, c...); } @@ -554,7 +554,7 @@ KFR_FN(horner) /// /// ``horner_even(x, 1, 2, 3)`` is equivalent to \(3x^4 + 2x^2 + 1\) template <typename T1, typename... Ts, KFR_ENABLE_IF(is_numeric_args<T1, Ts...>)> -constexpr KFR_INTRINSIC common_type<T1, Ts...> horner_even(const T1& x, const Ts&... c) +constexpr KFR_INTRINSIC std::common_type_t<T1, Ts...> horner_even(const T1& x, const Ts&... c) { return intrinsics::horner_even(x, c...); } @@ -564,7 +564,7 @@ KFR_FN(horner_even) /// /// ``horner_odd(x, 1, 2, 3)`` is equivalent to \(3x^5 + 2x^3 + 1x\) template <typename T1, typename... Ts, KFR_ENABLE_IF(is_numeric_args<T1, Ts...>)> -constexpr KFR_INTRINSIC common_type<T1, Ts...> horner_odd(const T1& x, const Ts&... c) +constexpr KFR_INTRINSIC std::common_type_t<T1, Ts...> horner_odd(const T1& x, const Ts&... c) { return intrinsics::horner_odd(x, c...); } @@ -581,7 +581,7 @@ constexpr KFR_INTRINSIC T reciprocal(const T& x) KFR_FN(reciprocal) template <typename T1, typename T2> -KFR_INTRINSIC common_type<T1, T2> mulsign(const T1& x, const T2& y) +KFR_INTRINSIC std::common_type_t<T1, T2> mulsign(const T1& x, const T2& y) { return bitwisexor(x, bitwiseand(y, special_constants<T2>::highbitmask())); } diff --git a/include/kfr/simd/saturation.hpp b/include/kfr/simd/saturation.hpp @@ -34,7 +34,7 @@ inline namespace CMT_ARCH_NAME /// @brief Adds two arguments using saturation template <typename T1, typename T2, KFR_ENABLE_IF(is_numeric_args<T1, T2>), - typename Tout = common_type<T1, T2>> + typename Tout = std::common_type_t<T1, T2>> KFR_INTRINSIC Tout satadd(const T1& x, const T2& y) { return intrinsics::satadd(x, y); @@ -42,7 +42,7 @@ KFR_INTRINSIC Tout satadd(const T1& x, const T2& y) /// @brief Subtracts two arguments using saturation template <typename T1, typename T2, KFR_ENABLE_IF(is_numeric_args<T1, T2>), - typename Tout = common_type<T1, T2>> + typename Tout = std::common_type_t<T1, T2>> KFR_INTRINSIC Tout satsub(const T1& x, const T2& y) { return intrinsics::satsub(x, y); diff --git a/include/kfr/simd/select.hpp b/include/kfr/simd/select.hpp @@ -39,7 +39,7 @@ inline namespace CMT_ARCH_NAME * @endcode */ template <typename T1, size_t N, typename T2, typename T3, KFR_ENABLE_IF(is_numeric_args<T1, T2, T3>), - typename Tout = subtype<common_type<T2, T3>>> + typename Tout = subtype<std::common_type_t<T2, T3>>> KFR_INTRINSIC vec<Tout, N> select(const mask<T1, N>& m, const T2& x, const T3& y) { static_assert(sizeof(T1) == sizeof(Tout), "select: incompatible types"); diff --git a/include/kfr/simd/types.hpp b/include/kfr/simd/types.hpp @@ -57,80 +57,19 @@ using namespace cometa; using cometa::fbase; using cometa::fmax; -// primary template (used for zero types) template <typename... T> -struct common_type_impl -{ -}; - -template <typename... T> -using decay_common = std::decay_t<common_type_impl<T...>>; - -template <typename T1, typename T2, template <typename TT> class result_type, typename = void> -struct common_type_from_subtypes -{ -}; - -template <typename T1, typename T2, template <typename TT> class result_type> -struct common_type_from_subtypes<T1, T2, result_type, std::void_t<typename common_type_impl<T1, T2>::type>> -{ - using type = result_type<typename common_type_impl<T1, T2>::type>; -}; - -template <typename T> -struct common_type_impl<T> -{ - using type = std::decay_t<T>; -}; - -template <typename T1, typename T2> -using common_for_two = decltype(false ? std::declval<T1>() : std::declval<T2>()); - -template <typename T1, typename T2, typename = void> -struct common_type_2_default -{ -}; +using decay_common = std::decay_t<std::common_type_t<T...>>; -template <typename T1, typename T2> -struct common_type_2_default<T1, T2, std::void_t<common_for_two<T1, T2>>> +template <typename CT, template <typename T> typename Tpl, typename = void> +struct construct_common_type { - using type = std::decay_t<common_for_two<T1, T2>>; }; - -template <typename T1, typename T2, typename D1 = std::decay_t<T1>, typename D2 = std::decay_t<T2>> -struct common_type_2_impl : common_type_impl<D1, D2> -{ -}; - -template <typename D1, typename D2> -struct common_type_2_impl<D1, D2, D1, D2> : common_type_2_default<D1, D2> -{ -}; - -template <typename T1, typename T2> -struct common_type_impl<T1, T2> : common_type_2_impl<T1, T2> -{ -}; - -template <typename AlwaysVoid, typename T1, typename T2, typename... R> -struct common_type_multi_impl +template <typename CT, template <typename T> typename Tpl> +struct construct_common_type<CT, Tpl, std::void_t<typename CT::type>> { + using type = Tpl<typename CT::type>; }; -template <typename T1, typename T2, typename... R> -struct common_type_multi_impl<std::void_t<typename common_type_impl<T1, T2>::type>, T1, T2, R...> - : common_type_impl<typename common_type_impl<T1, T2>::type, R...> -{ -}; - -template <typename T1, typename T2, typename... R> -struct common_type_impl<T1, T2, R...> : common_type_multi_impl<void, T1, T2, R...> -{ -}; - -template <typename... T> -using common_type = typename common_type_impl<T...>::type; - constexpr ctypes_t<i8, i16, i32, i64> signed_types{}; constexpr ctypes_t<u8, u16, u32, u64> unsigned_types{}; constexpr ctypes_t<i8, i16, i32, i64, u8, u16, u32, u64> integer_types{}; diff --git a/include/kfr/simd/vec.hpp b/include/kfr/simd/vec.hpp @@ -883,7 +883,7 @@ struct conditional_common; template <typename Tfallback, typename... Args> struct conditional_common<true, Tfallback, Args...> { - using type = common_type<Args...>; + using type = std::common_type_t<Args...>; }; template <typename Tfallback, typename... Args> @@ -919,10 +919,10 @@ constexpr KFR_INTRINSIC vec<T, N> make_vector(cvals_t<T, Values...>) return make_vector<T>(Values...); } -template < - typename Type = void, typename Arg, typename... Args, size_t N = (sizeof...(Args) + 1), - typename SubType = fix_type<std::conditional_t<std::is_void_v<Type>, common_type<Arg, Args...>, Type>>, - KFR_ENABLE_IF(is_number<subtype<SubType>>)> +template <typename Type = void, typename Arg, typename... Args, size_t N = (sizeof...(Args) + 1), + typename SubType = + fix_type<std::conditional_t<std::is_void_v<Type>, std::common_type_t<Arg, Args...>, Type>>, + KFR_ENABLE_IF(is_number<subtype<SubType>>)> constexpr KFR_INTRINSIC vec<SubType, N> pack(const Arg& x, const Args&... rest) { return internal::make_vector_impl<SubType>(csizeseq<N>, static_cast<SubType>(x), @@ -1441,39 +1441,32 @@ KFR_INTRINSIC vec<T, N> v(const portable_vec<T, N>& pv) } } // namespace CMT_ARCH_NAME -template <typename T1, typename T2, size_t N> -struct common_type_impl<kfr::vec<T1, N>, kfr::vec<T2, N>> - : common_type_from_subtypes<T1, T2, kfr::vec_template<N>::template type> -{ -}; -template <typename T1, typename T2, size_t N1, size_t N2> -struct common_type_impl<kfr::vec<T1, N1>, kfr::vec<T2, N2>> + +} // namespace kfr + +namespace std { -}; + +// V x V (same N) template <typename T1, typename T2, size_t N> -struct common_type_impl<kfr::vec<T1, N>, T2> - : common_type_from_subtypes<T1, T2, kfr::vec_template<N>::template type> +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 S template <typename T1, typename T2, size_t N> -struct common_type_impl<T1, kfr::vec<T2, N>> - : common_type_from_subtypes<T1, T2, kfr::vec_template<N>::template type> -{ -}; - -template <typename T1, typename T2, size_t N1, size_t N2> -struct common_type_impl<kfr::vec<T1, N1>, kfr::vec<kfr::vec<T2, N1>, N2>> - : common_type_from_subtypes<T1, T2, kfr::vec_vec_template<N1, N2>::template type> +struct common_type<kfr::vec<T1, N>, T2> + : kfr::construct_common_type<std::common_type<T1, T2>, kfr::vec_template<N>::template type> { - using type = kfr::vec<kfr::vec<typename common_type_impl<T1, T2>::type, N1>, N2>; }; -template <typename T1, typename T2, size_t N1, size_t N2> -struct common_type_impl<kfr::vec<kfr::vec<T1, N1>, N2>, kfr::vec<T2, N1>> - : common_type_from_subtypes<T1, T2, kfr::vec_vec_template<N1, N2>::template type> +// S x V +template <typename T1, typename T2, size_t N> +struct common_type<T1, kfr::vec<T2, N>> + : kfr::construct_common_type<std::common_type<T1, T2>, kfr::vec_template<N>::template type> { }; -} // namespace kfr +} // namespace std namespace cometa { diff --git a/tests/complex_test.cpp b/tests/complex_test.cpp @@ -219,7 +219,7 @@ TEST(static_tests) testo::assert_is_same<ftype<vec<complex<i32>, 4>>, vec<complex<f32>, 4>>(); testo::assert_is_same<ftype<vec<complex<i64>, 8>>, vec<complex<f64>, 8>>(); - testo::assert_is_same<kfr::common_type<complex<int>, double>, complex<double>>(); + testo::assert_is_same<std::common_type_t<complex<int>, double>, complex<double>>(); } } // namespace CMT_ARCH_NAME diff --git a/tests/dft_test.cpp b/tests/dft_test.cpp @@ -33,8 +33,8 @@ template <typename T> static void perf_test_t(int size) { print("[PERFORMANCE] DFT ", fmt<'s', 6>(type_name<T>()), " ", fmt<'d', 6>(size), "..."); - random_bit_generator gen1(2247448713, 915890490, 864203735, 2982561); - random_bit_generator gen2(2982561, 2247448713, 915890490, 864203735); + random_state gen1 = random_init(2247448713, 915890490, 864203735, 2982561); + random_state gen2 = random_init(2982561, 2247448713, 915890490, 864203735); std::chrono::high_resolution_clock::duration duration(0); dft_plan<T> dft(size); univector<u8> tmp(dft.temp_size); @@ -149,7 +149,7 @@ constexpr size_t dft_stopsize = 257; TEST(fft_real) { using float_type = double; - random_bit_generator gen(2247448713, 915890490, 864203735, 2982561); + random_state gen = random_init(2247448713, 915890490, 864203735, 2982561); constexpr size_t size = 64; @@ -161,8 +161,10 @@ TEST(fft_real) TEST(fft_accuracy) { +#ifdef DEBUG_DFT_PROGRESS testo::active_test()->show_progress = true; - random_bit_generator gen(2247448713, 915890490, 864203735, 2982561); +#endif + random_state gen = random_init(2247448713, 915890490, 864203735, 2982561); std::set<size_t> size_set; univector<size_t> sizes = truncate(1 + counter(), fft_stopsize - 1); sizes = round(pow(2.0, sizes)); @@ -175,7 +177,9 @@ TEST(fft_accuracy) sizes.push_back(s); } #endif +#ifdef DEBUG_DFT_PROGRESS println(sizes); +#endif testo::matrix(named("type") = dft_float_types, // named("size") = sizes, // @@ -195,7 +199,9 @@ TEST(fft_accuracy) const dft_plan<float_type> dft(size); if (!inverse) { +#if DEBUG_DFT_PROGRESS dft.dump(); +#endif } univector<u8> temp(dft.temp_size); @@ -214,8 +220,8 @@ TEST(fft_accuracy) univector<float_type> in = truncate(gen_random_range<float_type>(gen, -1.0, +1.0), size); - univector<complex<float_type>> out = truncate(scalar(qnan), size); - univector<complex<float_type>> refout = truncate(scalar(qnan), size); + univector<complex<float_type>> out = truncate(dimensions<1>(scalar(qnan)), size); + univector<complex<float_type>> refout = truncate(dimensions<1>(scalar(qnan)), size); const dft_plan_real<float_type> dft(size); univector<u8> temp(dft.temp_size); diff --git a/tests/unit/base/basic_expressions.cpp b/tests/unit/base/basic_expressions.cpp @@ -55,6 +55,18 @@ TEST(adjacent) [](size_t i) { return i > 0 ? i * (i - 1) : 0; }); } +TEST(dimensions) +{ + static_assert(expression_dims<decltype(scalar(0))> == 0); + static_assert(expression_dims<decltype(dimensions<1>(scalar(0)))> == 1); + + static_assert(shapeof<decltype(scalar(0))>() == shape{}); + static_assert(shapeof<decltype(dimensions<1>(scalar(0)))>() == shape{ infinite_size }); + static_assert(shapeof<decltype(dimensions<2>(dimensions<1>(scalar(0))))>() == + shape{ infinite_size, infinite_size }); + CHECK_EXPRESSION(truncate(dimensions<1>(scalar(1)), 10), { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }); +} + TEST(padded) { static_assert(is_infinite<decltype(padded(counter()))>, ""); @@ -131,6 +143,8 @@ TEST(assign_expression) pack(a, b) *= broadcast<2>(10.f); 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>); } TEST(trace) { render(trace(counter()), 44); } diff --git a/tests/unit/simd/min_max.cpp b/tests/unit/simd/min_max.cpp @@ -16,14 +16,14 @@ TEST(min) { test_function2( test_catogories::all, [](auto x, auto y) { return kfr::min(x, y); }, - [](auto x, auto y) -> common_type<decltype(x), decltype(y)> { return x <= y ? x : y; }); + [](auto x, auto y) -> std::common_type_t<decltype(x), decltype(y)> { return x <= y ? x : y; }); } TEST(max) { test_function2( test_catogories::all, [](auto x, auto y) { return kfr::max(x, y); }, - [](auto x, auto y) -> common_type<decltype(x), decltype(y)> { return x >= y ? x : y; }); + [](auto x, auto y) -> std::common_type_t<decltype(x), decltype(y)> { return x >= y ? x : y; }); } struct IsNotMinInt @@ -45,7 +45,7 @@ TEST(absmin) { test_function2( test_catogories::all, [](auto x, auto y) { return kfr::absmin(x, y); }, - [](auto x, auto y) -> common_type<decltype(x), decltype(y)> + [](auto x, auto y) -> std::common_type_t<decltype(x), decltype(y)> { x = x >= 0 ? x : -x; y = y >= 0 ? y : -y; @@ -58,7 +58,7 @@ TEST(absmax) { test_function2( test_catogories::all, [](auto x, auto y) { return kfr::absmax(x, y); }, - [](auto x, auto y) -> common_type<decltype(x), decltype(y)> + [](auto x, auto y) -> std::common_type_t<decltype(x), decltype(y)> { x = x >= 0 ? x : -x; y = y >= 0 ? y : -y; diff --git a/tests/unit/simd/operators.cpp b/tests/unit/simd/operators.cpp @@ -34,21 +34,21 @@ TEST(add) { test_function2( test_catogories::vectors, [](auto x, auto y) { return x + y; }, - [](auto x, auto y) -> common_type<decltype(x), decltype(y)> { return x + y; }); + [](auto x, auto y) -> std::common_type_t<decltype(x), decltype(y)> { return x + y; }); } TEST(sub) { test_function2( test_catogories::vectors, [](auto x, auto y) { return x - y; }, - [](auto x, auto y) -> common_type<decltype(x), decltype(y)> { return x - y; }); + [](auto x, auto y) -> std::common_type_t<decltype(x), decltype(y)> { return x - y; }); } TEST(mul) { test_function2( test_catogories::vectors, [](auto x, auto y) { return x * y; }, - [](auto x, auto y) -> common_type<decltype(x), decltype(y)> { return x * y; }); + [](auto x, auto y) -> std::common_type_t<decltype(x), decltype(y)> { return x * y; }); } template <typename T> @@ -63,7 +63,7 @@ TEST(div) test_catogories::vectors, [](auto x, auto y) { return is_safe_division<subtype<decltype(x)>>(x.front(), y.front()) ? x / y : 0; }, - [](auto x, auto y) -> common_type<decltype(x), decltype(y)> { + [](auto x, auto y) -> std::common_type_t<decltype(x), decltype(y)> { return is_safe_division(x, y) ? x / y : 0; }); } @@ -81,7 +81,7 @@ TEST(mod) test_catogories::vectors, [](auto x, auto y) { return is_safe_division<subtype<decltype(x)>>(x.front(), y.front()) ? x % y : 0; }, - [](auto x, auto y) -> common_type<decltype(x), decltype(y)> { + [](auto x, auto y) -> std::common_type_t<decltype(x), decltype(y)> { return is_safe_division(x, y) ? x % y : 0; }, fn_return_constant<bool, true>{}, not_f{}); @@ -91,9 +91,9 @@ TEST(bor) { test_function2( test_catogories::vectors, [](auto x, auto y) { return x | y; }, - [](auto x, auto y) -> common_type<decltype(x), decltype(y)> + [](auto x, auto y) -> std::common_type_t<decltype(x), decltype(y)> { - using T = common_type<decltype(x), decltype(y)>; + using T = std::common_type_t<decltype(x), decltype(y)>; return bitcast<T>(static_cast<utype<T>>(ubitcast(T(x)) | ubitcast(T(y)))); }); } @@ -102,9 +102,9 @@ TEST(bxor) { test_function2( test_catogories::vectors, [](auto x, auto y) { return x ^ y; }, - [](auto x, auto y) -> common_type<decltype(x), decltype(y)> + [](auto x, auto y) -> std::common_type_t<decltype(x), decltype(y)> { - using T = common_type<decltype(x), decltype(y)>; + using T = std::common_type_t<decltype(x), decltype(y)>; return bitcast<T>(static_cast<utype<T>>(ubitcast(T(x)) ^ ubitcast(T(y)))); }); } @@ -113,9 +113,9 @@ TEST(band) { test_function2( test_catogories::vectors, [](auto x, auto y) { return x & y; }, - [](auto x, auto y) -> common_type<decltype(x), decltype(y)> + [](auto x, auto y) -> std::common_type_t<decltype(x), decltype(y)> { - using T = common_type<decltype(x), decltype(y)>; + using T = std::common_type_t<decltype(x), decltype(y)>; return bitcast<T>(static_cast<utype<T>>(ubitcast(T(x)) & ubitcast(T(y)))); }); } @@ -182,7 +182,7 @@ TEST(eq) { test_function2( test_catogories::vectors, [](auto x, auto y) { return (x == y).asvec(); }, - [](auto x, auto y) -> common_type<decltype(x), decltype(y)> { + [](auto x, auto y) -> std::common_type_t<decltype(x), decltype(y)> { return maskbits<subtype<decltype(x)>>(x == y); }); } @@ -191,7 +191,7 @@ TEST(ne) { test_function2( test_catogories::vectors, [](auto x, auto y) { return (x != y).asvec(); }, - [](auto x, auto y) -> common_type<decltype(x), decltype(y)> { + [](auto x, auto y) -> std::common_type_t<decltype(x), decltype(y)> { return maskbits<subtype<decltype(x)>>(x != y); }); } @@ -200,7 +200,7 @@ TEST(ge) { test_function2( test_catogories::vectors, [](auto x, auto y) { return (x >= y).asvec(); }, - [](auto x, auto y) -> common_type<decltype(x), decltype(y)> { + [](auto x, auto y) -> std::common_type_t<decltype(x), decltype(y)> { return maskbits<subtype<decltype(x)>>(x >= y); }); } @@ -209,7 +209,7 @@ TEST(le) { test_function2( test_catogories::vectors, [](auto x, auto y) { return (x <= y).asvec(); }, - [](auto x, auto y) -> common_type<decltype(x), decltype(y)> { + [](auto x, auto y) -> std::common_type_t<decltype(x), decltype(y)> { return maskbits<subtype<decltype(x)>>(x <= y); }); } @@ -218,7 +218,7 @@ TEST(gt) { test_function2( test_catogories::vectors, [](auto x, auto y) { return (x > y).asvec(); }, - [](auto x, auto y) -> common_type<decltype(x), decltype(y)> { + [](auto x, auto y) -> std::common_type_t<decltype(x), decltype(y)> { return maskbits<subtype<decltype(x)>>(x > y); }); } @@ -227,7 +227,7 @@ TEST(lt) { test_function2( test_catogories::vectors, [](auto x, auto y) { return (x < y).asvec(); }, - [](auto x, auto y) -> common_type<decltype(x), decltype(y)> { + [](auto x, auto y) -> std::common_type_t<decltype(x), decltype(y)> { return maskbits<subtype<decltype(x)>>(x < y); }); } diff --git a/tests/unit/simd/vec.cpp b/tests/unit/simd/vec.cpp @@ -10,8 +10,15 @@ namespace kfr { + +static_assert(std::is_same_v<i32x4, std::common_type_t<i32x4, i32x4>>); +static_assert(std::is_same_v<i32x4, std::common_type_t<i32x4>>); +static_assert(std::is_same_v<u32x4, std::common_type_t<i32x4, u32x4>>); +static_assert(std::is_same_v<f64x4, std::common_type_t<i32x4, u32x4, f64x4>>); + inline namespace CMT_ARCH_NAME { + TEST(mask_op) { mask<float, 4> m = make_mask<float>(true, false, true, false); @@ -53,9 +60,6 @@ bool is_in_range_of(Tin x) TEST(cast) { - testo::assert_is_same<i32x4, kfr::common_type<i32x4>>(); - testo::assert_is_same<u32x4, kfr::common_type<i32x4, u32x4>>(); - testo::assert_is_same<f64x4, kfr::common_type<i32x4, u32x4, f64x4>>(); CHECK(static_cast<i32x4>(u16x4{ 1, 2, 3, 4 }) == i32x4{ 1, 2, 3, 4 });