commit 65554fb390eb8649466fc23014030c6839e1c77d
parent ecd88210a52c5485c4745a04dd23ad7843c8b669
Author: d.levin256@gmail.com <d.levin256@gmail.com>
Date: Mon, 29 Aug 2016 04:17:31 +0300
Specify value_type for all expressions
Diffstat:
10 files changed, 140 insertions(+), 139 deletions(-)
diff --git a/include/kfr/base/basic_expressions.hpp b/include/kfr/base/basic_expressions.hpp
@@ -75,30 +75,34 @@ CMT_INLINE auto sequence(T x, Ts... rest)
constexpr size_t N = arraysize(seq);
return typed<T>(lambda([=](size_t index) { return seq[index % N]; }));
}
+
+template <typename T = int>
CMT_INLINE auto zeros()
{
- return lambda([](cinput_t, size_t, auto x) { return zerovector(x); });
+ return lambda<T>([](cinput_t, size_t, auto x) { return zerovector(x); });
}
+
+template <typename T = int>
CMT_INLINE auto ones()
{
- return lambda([](cinput_t, size_t, auto x) {
- using U = subtype<decltype(x)>;
- return U(1);
- });
+ return lambda<T>([](cinput_t, size_t, auto x) { return 1; });
}
+
+template <typename T = int>
CMT_INLINE auto counter()
{
- return lambda([](cinput_t, size_t index, auto x) { return enumerate(x) + index; });
+ return lambda<T>([](cinput_t, size_t index, auto x) { return enumerate(x) + index; });
}
+
template <typename T1>
CMT_INLINE auto counter(T1 start)
{
- return lambda([start](cinput_t, size_t index, auto x) { return enumerate(x) + index + start; });
+ return lambda<T1>([start](cinput_t, size_t index, auto x) { return enumerate(x) + index + start; });
}
template <typename T1, typename T2>
CMT_INLINE auto counter(T1 start, T2 step)
{
- return lambda(
+ return lambda<common_type<T1, T2>>(
[start, step](cinput_t, size_t index, auto x) { return (enumerate(x) + index) * step + start; });
}
@@ -220,6 +224,8 @@ struct expression_linspace<T, false> : input_expression
template <typename T>
struct expression_linspace<T, true> : input_expression
{
+ using value_type = T;
+
expression_linspace(T start, T stop, size_t size, bool endpoint = false)
: start(start), stop(stop), invsize(1.0 / T(endpoint ? size - 1 : size))
{
diff --git a/include/kfr/base/expression.hpp b/include/kfr/base/expression.hpp
@@ -34,25 +34,45 @@
namespace kfr
{
-template <typename T>
-using is_generic = is_same<generic, typename decay<T>::value_type>;
+namespace internal
+{
+template <typename T, typename = void>
+struct is_fixed_size_impl : std::false_type
+{
+};
template <typename T>
-using is_infinite = not_t<is_same<size_t, typename decay<T>::size_type>>;
+struct is_fixed_size_impl<T, void_t<decltype(T::size())>> : std::true_type
+{
+};
-namespace internal
+template <typename T, typename = void>
+struct is_infinite_impl : std::false_type
{
+};
-template <typename T1>
-constexpr inline T1 minsize(T1 x) noexcept
+template <typename T>
+struct is_infinite_impl<T, void_t<decltype(T::size())>>
+ : std::integral_constant<bool, T::size() == infinite_size>
{
- return x;
+};
}
-template <typename T1, typename T2, typename... Ts>
-constexpr inline common_type<T1, T2, Ts...> minsize(T1 x, T2 y, Ts... rest) noexcept
+template <typename T>
+using is_fixed_size = typename internal::is_fixed_size_impl<T>::type;
+
+template <typename T>
+using is_infinite = typename internal::is_infinite_impl<T>::type;
+
+namespace internal
+{
+
+constexpr inline size_t minsize(size_t x) noexcept { return x; }
+
+template <typename... Ts>
+constexpr inline size_t minsize(size_t x, size_t y, Ts... rest) noexcept
{
- return x < y ? minsize(x, rest...) : minsize(y, rest...);
+ return minsize(x < y ? x : y, rest...);
}
template <typename... Args>
@@ -60,9 +80,7 @@ struct expression : input_expression
{
using value_type = common_type<typename decay<Args>::value_type...>;
- using size_type = common_type<typename decay<Args>::size_type...>;
-
- constexpr size_type size() const noexcept { return size_impl(indicesfor_t<Args...>()); }
+ constexpr size_t size() const noexcept { return size_impl(indicesfor_t<Args...>()); }
constexpr static size_t count = sizeof...(Args);
expression() = delete;
@@ -78,7 +96,7 @@ struct expression : input_expression
protected:
template <size_t... indices>
- constexpr size_type size_impl(csizes_t<indices...>) const noexcept
+ constexpr size_t size_impl(csizes_t<indices...>) const noexcept
{
return minsize(std::get<indices>(this->args).size()...);
}
@@ -88,21 +106,22 @@ protected:
{
return call_impl(std::forward<Fn>(fn), indicesfor_t<Args...>(), index, x);
}
- template <size_t ArgIndex, typename T, size_t N>
- CMT_INLINE vec<T, N> argument(csize_t<ArgIndex>, size_t index, vec_t<T, N> x) const
+ template <size_t ArgIndex, typename U, size_t N,
+ typename T = value_type_of<typename details::get_nth_type<ArgIndex, Args...>::type>>
+ CMT_INLINE vec<U, N> argument(csize_t<ArgIndex>, size_t index, vec_t<U, N>) const
{
static_assert(ArgIndex < count, "Incorrect ArgIndex");
- return std::get<ArgIndex>(this->args)(cinput, index, x);
+ return static_cast<vec<U, N>>(std::get<ArgIndex>(this->args)(cinput, index, vec_t<T, N>()));
}
- template <typename T, size_t N>
- CMT_INLINE vec<T, N> argument_first(size_t index, vec_t<T, N> x) const
+ template <typename U, size_t N,
+ typename T = value_type_of<typename details::get_nth_type<0, Args...>::type>>
+ CMT_INLINE vec<U, N> argument_first(size_t index, vec_t<U, N>) const
{
- return std::get<0>(this->args)(cinput, index, x);
+ return static_cast<vec<U, N>>(std::get<0>(this->args)(cinput, index, vec_t<T, N>()));
}
private:
- template <typename Arg, size_t N, typename Tin,
- typename Tout = conditional<is_generic<Arg>::value, Tin, value_type_of<Arg>>>
+ template <typename Arg, size_t N, typename Tout = value_type_of<Arg>>
CMT_INLINE vec_t<Tout, N> vec_t_for() const
{
return {};
@@ -112,10 +131,9 @@ private:
{
using ratio = func_ratio<Fn>;
constexpr size_t Nin = N * ratio::input / ratio::output;
- using Tout = conditional<is_same<generic, value_type>::value, T, common_type<T, value_type>>;
return fn(std::get<indices>(this->args)(cinput, index * ratio::input / ratio::output,
- vec_t_for<Args, Nin, Tout>())...);
+ vec_t_for<Args, Nin>())...);
}
template <size_t... indices>
CMT_INLINE void begin_block_impl(size_t size, csizes_t<indices...>)
@@ -148,10 +166,10 @@ struct expression_scalar : input_expression
constexpr expression_scalar(const vec<T, width>& val) noexcept : val(val) {}
vec<T, width> val;
- template <typename U, size_t N>
- CMT_INLINE vec<U, N> operator()(cinput_t, size_t, vec_t<U, N>) const
+ template <size_t N>
+ CMT_INLINE vec<T, N> operator()(cinput_t, size_t, vec_t<T, N>) const
{
- return resize<N>(static_cast<vec<U, width>>(val));
+ return resize<N>(val);
}
};
@@ -162,24 +180,13 @@ using arg_impl = conditional<is_number<T>::value || is_vec<T>::value,
template <typename T>
using arg = internal::arg_impl<T>;
-template <typename Fn, typename Args, typename Enable = void>
-struct generic_result
-{
- using type = generic;
-};
-
-template <typename Fn, typename... Args>
-struct generic_result<Fn, ctypes_t<Args...>, void_t<enable_if<!or_t<is_same<generic, Args>...>::value>>>
-{
- using type = subtype<decltype(std::declval<Fn>()(std::declval<vec<decay<Args>, 1>>()...))>;
-};
-
template <typename Fn, typename... Args>
struct expression_function : expression<arg<Args>...>
{
using ratio = func_ratio<Fn>;
- using value_type = typename generic_result<Fn, ctypes_t<value_type_of<arg<Args>>...>>::type;
+ using value_type =
+ subtype<decltype(std::declval<Fn>()(std::declval<vec<value_type_of<arg<Args>>, 1>>()...))>;
expression_function(Fn&& fn, arg<Args>&&... args) noexcept
: expression<arg<Args>...>(std::forward<arg<Args>>(args)...),
@@ -194,8 +201,7 @@ struct expression_function : expression<arg<Args>...>
template <typename T, size_t N>
CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> x) const
{
- static_assert(is_same<T, value_type_of<expression_function>>::value ||
- is_generic<expression_function>::value,
+ static_assert(is_same<T, value_type_of<expression_function>>::value,
"Can't cast from value_type to T");
return this->call(fn, index, x);
}
@@ -255,25 +261,30 @@ CMT_INLINE internal::expression_function<Fn, NewArgs...> rebind(
return internal::expression_function<Fn, NewArgs...>(e.get_fn(), std::forward<NewArgs>(args)...);
}
-template <typename Tout, cpu_t c = cpu_t::native, size_t width = 0, typename OutFn, typename Fn>
-CMT_INLINE void process(OutFn&& outfn, const Fn& fn, size_t size)
+template <typename Tout, cpu_t c = cpu_t::native, size_t width = 0, typename OutputExpr, typename InputExpr>
+CMT_INLINE void process(OutputExpr&& out, const InputExpr& in, size_t size)
{
- static_assert(is_output_expression<OutFn>::value, "OutFn must be an expression");
- static_assert(is_input_expression<Fn>::value, "Fn must be an expression");
- constexpr size_t comp = lcm(func_ratio<OutFn>::input, func_ratio<Fn>::output);
+ static_assert(is_output_expression<OutputExpr>::value, "OutFn must be an expression");
+ static_assert(is_input_expression<InputExpr>::value, "Fn must be an expression");
+ constexpr size_t comp = lcm(func_ratio<OutputExpr>::input, func_ratio<InputExpr>::output);
size *= comp;
- outfn.output_begin_block(size);
- fn.begin_block(size);
+ out.output_begin_block(size);
+ in.begin_block(size);
+
+ using Tin = value_type_of<InputExpr>;
- using Tin = conditional<is_generic<Fn>::value, Tout, value_type_of<Fn>>;
+#ifdef NDEBUG
+ constexpr size_t w = width == 0 ? internal::get_vector_width<Tout, c>(2, 4) : width;
+#else
+ constexpr size_t w = width == 0 ? internal::get_vector_width<Tout, c>(1, 1) : width;
+#endif
size_t i = 0;
- internal::process_cycle<Tout, Tin, width == 0 ? internal::get_vector_width<Tout, c>(2, 4) : width>(
- std::forward<OutFn>(outfn), fn, i, size);
- internal::process_cycle<Tout, Tin, comp>(std::forward<OutFn>(outfn), fn, i, size);
+ internal::process_cycle<Tout, Tin, w>(std::forward<OutputExpr>(out), in, i, size);
+ internal::process_cycle<Tout, Tin, comp>(std::forward<OutputExpr>(out), in, i, size);
- fn.end_block(size);
- outfn.output_end_block(size);
+ in.end_block(size);
+ out.output_end_block(size);
}
namespace internal
diff --git a/include/kfr/base/operators.hpp b/include/kfr/base/operators.hpp
@@ -434,13 +434,13 @@ KFR_FN(greaterorequal)
/// @brief Fused Multiply-Add
template <typename T1, typename T2, typename T3>
-constexpr inline common_type<T1, T2, T3> fmadd(T1 x, T2 y, T3 z)
+KFR_INTRIN constexpr common_type<T1, T2, T3> fmadd(T1 x, T2 y, T3 z)
{
return x * y + z;
}
/// @brief Fused Multiply-Sub
template <typename T1, typename T2, typename T3>
-constexpr inline common_type<T1, T2, T3> fmsub(T1 x, T2 y, T3 z)
+KFR_INTRIN constexpr common_type<T1, T2, T3> fmsub(T1 x, T2 y, T3 z)
{
return x * y - z;
}
@@ -450,14 +450,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>
-constexpr inline common_type<T1, T2, T3> mix(T1 c, T2 x, T3 y)
+KFR_INTRIN constexpr common_type<T1, T2, T3> mix(T1 c, T2 x, 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>
-constexpr inline common_type<T1, T2, T3> mixs(T1 c, T2 x, T3 y)
+KFR_INTRIN constexpr common_type<T1, T2, T3> mixs(T1 c, T2 x, T3 y)
{
return mix(fmadd(c, 0.5, 0.5), x, y);
}
@@ -711,8 +711,8 @@ struct expression_pack : expression<E...>, output_expression
expression_pack(E&&... e) : expression<E...>(std::forward<E>(e)...) {}
using value_type = vec<common_type<value_type_of<E>...>, count>;
- using size_type = typename expression<E...>::size_type;
- constexpr size_type size() const noexcept { return expression<E...>::size(); }
+
+ using expression<E...>::size;
template <typename U, size_t N>
CMT_INLINE vec<U, N> operator()(cinput_t, size_t index, vec_t<U, N> x) const
diff --git a/include/kfr/base/random.hpp b/include/kfr/base/random.hpp
@@ -43,7 +43,8 @@ constexpr seed_from_rdtsc_t seed_from_rdtsc{};
struct random_bit_generator
{
random_bit_generator(seed_from_rdtsc_t) noexcept
- : state(bitcast<u32>(make_vector(__builtin_readcyclecounter(), (__builtin_readcyclecounter() << 11) ^ 0x710686d615e2257bull)))
+ : state(bitcast<u32>(make_vector(__builtin_readcyclecounter(),
+ (__builtin_readcyclecounter() << 11) ^ 0x710686d615e2257bull)))
{
(void)operator()();
}
diff --git a/include/kfr/base/reduce.hpp b/include/kfr/base/reduce.hpp
@@ -110,7 +110,6 @@ template <typename ReduceFn, typename TransformFn = fn_pass_through, typename Fi
KFR_SINTRIN T reduce(E1&& e1, ReduceFn&& reducefn, TransformFn&& transformfn = fn_pass_through(),
FinalFn&& finalfn = fn_pass_through())
{
- static_assert(!is_generic<E1>::value, "e1 must be a typed expression (use typed<T>())");
static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use typed<T>())");
const size_t size = e1.size();
using reducer_t = expression_reduce<T, decay<ReduceFn>, decay<TransformFn>, decay<FinalFn>>;
@@ -135,7 +134,6 @@ KFR_FN(reduce)
template <typename E1, typename T = value_type_of<E1>, KFR_ENABLE_IF(is_input_expression<E1>::value)>
KFR_SINTRIN T sum(E1&& x)
{
- static_assert(!is_generic<E1>::value, "e1 must be a typed expression (use typed<T>())");
static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use typed<T>())");
return internal::reduce(std::forward<E1>(x), fn_add());
}
@@ -151,7 +149,6 @@ KFR_SINTRIN T sum(E1&& x)
template <typename E1, typename T = value_type_of<E1>, KFR_ENABLE_IF(is_input_expression<E1>::value)>
KFR_SINTRIN T mean(E1&& x)
{
- static_assert(!is_generic<E1>::value, "e1 must be a typed expression (use typed<T>())");
static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use typed<T>())");
return internal::reduce(std::forward<E1>(x), fn_add(), fn_pass_through(), fn_final_mean());
}
@@ -164,7 +161,6 @@ KFR_SINTRIN T mean(E1&& x)
template <typename E1, typename T = value_type_of<E1>, KFR_ENABLE_IF(is_input_expression<E1>::value)>
KFR_SINTRIN T minof(E1&& x)
{
- static_assert(!is_generic<E1>::value, "e1 must be a typed expression (use typed<T>())");
static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use typed<T>())");
return internal::reduce(std::forward<E1>(x), fn::min());
}
@@ -177,7 +173,6 @@ KFR_SINTRIN T minof(E1&& x)
template <typename E1, typename T = value_type_of<E1>, KFR_ENABLE_IF(is_input_expression<E1>::value)>
KFR_SINTRIN T maxof(E1&& x)
{
- static_assert(!is_generic<E1>::value, "e1 must be a typed expression (use typed<T>())");
static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use typed<T>())");
return internal::reduce(std::forward<E1>(x), fn::max());
}
@@ -190,7 +185,6 @@ KFR_SINTRIN T maxof(E1&& x)
template <typename E1, typename T = value_type_of<E1>, KFR_ENABLE_IF(is_input_expression<E1>::value)>
KFR_SINTRIN T absminof(E1&& x)
{
- static_assert(!is_generic<E1>::value, "e1 must be a typed expression (use typed<T>())");
static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use typed<T>())");
return internal::reduce(std::forward<E1>(x), fn::absmin());
}
@@ -203,7 +197,6 @@ KFR_SINTRIN T absminof(E1&& x)
template <typename E1, typename T = value_type_of<E1>, KFR_ENABLE_IF(is_input_expression<E1>::value)>
KFR_SINTRIN T absmaxof(E1&& x)
{
- static_assert(!is_generic<E1>::value, "e1 must be a typed expression (use typed<T>())");
static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use typed<T>())");
return internal::reduce(std::forward<E1>(x), fn::absmax());
}
@@ -222,7 +215,6 @@ KFR_SINTRIN T dotproduct(E1&& x, E2&& y)
{
auto m = std::forward<E1>(x) * std::forward<E2>(y);
using E12 = decltype(m);
- static_assert(!is_generic<E12>::value, "e1 must be a typed expression (use typed<T>())");
static_assert(!is_infinite<E12>::value, "e1 must be a sized expression (use typed<T>())");
return internal::reduce(std::move(m), fn_add());
}
@@ -238,7 +230,6 @@ KFR_SINTRIN T dotproduct(E1&& x, E2&& y)
template <typename E1, typename T = value_type_of<E1>, KFR_ENABLE_IF(is_input_expression<E1>::value)>
KFR_SINTRIN T rms(E1&& x)
{
- static_assert(!is_generic<E1>::value, "e1 must be a typed expression (use typed<T>())");
static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use typed<T>())");
return internal::reduce(std::forward<E1>(x), fn_add(), fn_sqr(), fn_final_rootmean());
}
@@ -254,7 +245,6 @@ KFR_SINTRIN T rms(E1&& x)
template <typename E1, typename T = value_type_of<E1>, KFR_ENABLE_IF(is_input_expression<E1>::value)>
KFR_SINTRIN T sumsqr(E1&& x)
{
- static_assert(!is_generic<E1>::value, "e1 must be a typed expression (use typed<T>())");
static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use typed<T>())");
return internal::reduce(std::forward<E1>(x), fn_add(), fn_sqr());
}
@@ -270,7 +260,6 @@ KFR_SINTRIN T sumsqr(E1&& x)
template <typename E1, typename T = value_type_of<E1>, KFR_ENABLE_IF(is_input_expression<E1>::value)>
KFR_SINTRIN T product(E1&& x)
{
- static_assert(!is_generic<E1>::value, "e1 must be a typed expression (use typed<T>())");
static_assert(!is_infinite<E1>::value, "e1 must be a sized expression (use typed<T>())");
return internal::reduce(std::forward<E1>(x), fn_mul());
}
diff --git a/include/kfr/base/simd.hpp b/include/kfr/base/simd.hpp
@@ -87,75 +87,75 @@ struct vec_op
using utype = kfr::utype<type>;
constexpr static size_t w = compound_type_traits<T>::width * N;
- constexpr static simd<type, w> add(const simd<type, w>& x, const simd<type, w>& y) noexcept
+ CMT_INLINE constexpr static simd<type, w> add(const simd<type, w>& x, const simd<type, w>& y) noexcept
{
return x + y;
}
- constexpr static simd<type, w> sub(const simd<type, w>& x, const simd<type, w>& y) noexcept
+ CMT_INLINE constexpr static simd<type, w> sub(const simd<type, w>& x, const simd<type, w>& y) noexcept
{
return x - y;
}
- constexpr static simd<type, w> mul(const simd<type, w>& x, const simd<type, w>& y) noexcept
+ CMT_INLINE constexpr static simd<type, w> mul(const simd<type, w>& x, const simd<type, w>& y) noexcept
{
return x * y;
}
- constexpr static simd<type, w> div(const simd<type, w>& x, const simd<type, w>& y) noexcept
+ CMT_INLINE constexpr static simd<type, w> div(const simd<type, w>& x, const simd<type, w>& y) noexcept
{
return x / y;
}
- constexpr static simd<type, w> rem(const simd<type, w>& x, const simd<type, w>& y) noexcept
+ CMT_INLINE constexpr static simd<type, w> rem(const simd<type, w>& x, const simd<type, w>& y) noexcept
{
return x % y;
}
- constexpr static simd<type, w> shl(const simd<type, w>& x, const simd<type, w>& y) noexcept
+ CMT_INLINE constexpr static simd<type, w> shl(const simd<type, w>& x, const simd<type, w>& y) noexcept
{
return x << y;
}
- constexpr static simd<type, w> shr(const simd<type, w>& x, const simd<type, w>& y) noexcept
+ CMT_INLINE constexpr static simd<type, w> shr(const simd<type, w>& x, const simd<type, w>& y) noexcept
{
return x >> y;
}
- constexpr static simd<type, w> neg(const simd<type, w>& x) noexcept { return -x; }
- constexpr static simd<type, w> band(const simd<type, w>& x, const simd<type, w>& y) noexcept
+ CMT_INLINE constexpr static simd<type, w> neg(const simd<type, w>& x) noexcept { return -x; }
+ CMT_INLINE constexpr static simd<type, w> band(const simd<type, w>& x, const simd<type, w>& y) noexcept
{
return reinterpret_cast<simd<type, w>>(reinterpret_cast<simd<utype, w>>(x) &
reinterpret_cast<simd<utype, w>>(y));
}
- constexpr static simd<type, w> bor(const simd<type, w>& x, const simd<type, w>& y) noexcept
+ CMT_INLINE constexpr static simd<type, w> bor(const simd<type, w>& x, const simd<type, w>& y) noexcept
{
return reinterpret_cast<simd<type, w>>(reinterpret_cast<simd<utype, w>>(x) |
reinterpret_cast<simd<utype, w>>(y));
}
- constexpr static simd<type, w> bxor(const simd<type, w>& x, const simd<type, w>& y) noexcept
+ CMT_INLINE constexpr static simd<type, w> bxor(const simd<type, w>& x, const simd<type, w>& y) noexcept
{
return reinterpret_cast<simd<type, w>>(reinterpret_cast<simd<utype, w>>(x) ^
reinterpret_cast<simd<utype, w>>(y));
}
- constexpr static simd<type, w> bnot(const simd<type, w>& x) noexcept
+ CMT_INLINE constexpr static simd<type, w> bnot(const simd<type, w>& x) noexcept
{
return reinterpret_cast<simd<type, w>>(~reinterpret_cast<simd<utype, w>>(x));
}
- constexpr static simd<type, w> eq(const simd<type, w>& x, const simd<type, w>& y) noexcept
+ CMT_INLINE constexpr static simd<type, w> eq(const simd<type, w>& x, const simd<type, w>& y) noexcept
{
return reinterpret_cast<simd<type, w>>(x == y);
}
- constexpr static simd<type, w> ne(const simd<type, w>& x, const simd<type, w>& y) noexcept
+ CMT_INLINE constexpr static simd<type, w> ne(const simd<type, w>& x, const simd<type, w>& y) noexcept
{
return reinterpret_cast<simd<type, w>>(x != y);
}
- constexpr static simd<type, w> lt(const simd<type, w>& x, const simd<type, w>& y) noexcept
+ CMT_INLINE constexpr static simd<type, w> lt(const simd<type, w>& x, const simd<type, w>& y) noexcept
{
return reinterpret_cast<simd<type, w>>(x < y);
}
- constexpr static simd<type, w> gt(const simd<type, w>& x, const simd<type, w>& y) noexcept
+ CMT_INLINE constexpr static simd<type, w> gt(const simd<type, w>& x, const simd<type, w>& y) noexcept
{
return reinterpret_cast<simd<type, w>>(x > y);
}
- constexpr static simd<type, w> le(const simd<type, w>& x, const simd<type, w>& y) noexcept
+ CMT_INLINE constexpr static simd<type, w> le(const simd<type, w>& x, const simd<type, w>& y) noexcept
{
return reinterpret_cast<simd<type, w>>(x <= y);
}
- constexpr static simd<type, w> ge(const simd<type, w>& x, const simd<type, w>& y) noexcept
+ CMT_INLINE constexpr static simd<type, w> ge(const simd<type, w>& x, const simd<type, w>& y) noexcept
{
return reinterpret_cast<simd<type, w>>(x >= y);
}
diff --git a/include/kfr/base/types.hpp b/include/kfr/base/types.hpp
@@ -201,15 +201,6 @@ inline datatype operator&(datatype x, datatype y)
return static_cast<datatype>(static_cast<type>(x) | static_cast<type>(y));
}
-struct generic
-{
- template <typename T>
- CMT_INLINE constexpr operator T() const noexcept
- {
- return T();
- }
-};
-
struct infinite
{
template <typename T>
@@ -546,49 +537,49 @@ CMT_INLINE void zeroize(T1& value)
#endif
template <typename T, typename U>
-constexpr inline static T& ref_cast(U& ptr)
+CMT_INLINE constexpr static T& ref_cast(U& ptr)
{
return reinterpret_cast<T&>(ptr);
}
template <typename T, typename U>
-constexpr inline static const T& ref_cast(const U& ptr)
+CMT_INLINE constexpr static const T& ref_cast(const U& ptr)
{
return reinterpret_cast<const T&>(ptr);
}
template <typename T, typename U>
-constexpr inline static T* ptr_cast(U* ptr)
+CMT_INLINE constexpr static T* ptr_cast(U* ptr)
{
return reinterpret_cast<T*>(ptr);
}
template <typename T, typename U>
-constexpr inline static const T* ptr_cast(const U* ptr)
+CMT_INLINE constexpr static const T* ptr_cast(const U* ptr)
{
return reinterpret_cast<const T*>(ptr);
}
template <typename T, typename U>
-constexpr inline static T* ptr_cast(U* ptr, ptrdiff_t offset)
+CMT_INLINE constexpr static T* ptr_cast(U* ptr, ptrdiff_t offset)
{
return ptr_cast<T>(ptr_cast<u8>(ptr) + offset);
}
template <typename T, typename U>
-constexpr inline static T* derived_cast(U* ptr)
+CMT_INLINE constexpr static T* derived_cast(U* ptr)
{
return static_cast<T*>(ptr);
}
template <typename T, typename U>
-constexpr inline static const T* derived_cast(const U* ptr)
+CMT_INLINE constexpr static const T* derived_cast(const U* ptr)
{
return static_cast<const T*>(ptr);
}
template <typename T, typename U>
-constexpr inline static T implicit_cast(U&& value)
+CMT_INLINE constexpr static T implicit_cast(U&& value)
{
return std::forward<T>(value);
}
@@ -711,12 +702,12 @@ constexpr size_t native_int_vector_size =
c == cpu_t::neon ? 16 : common_int_vector_size;
#endif
+constexpr size_t infinite_size = static_cast<size_t>(-1);
+
/// @brief Base class of all input expressoins
struct input_expression
{
- using value_type = generic;
- using size_type = infinite;
- constexpr size_type size() const noexcept { return {}; }
+ constexpr static size_t size() noexcept { return infinite_size; }
CMT_INLINE void begin_block(size_t) const {}
CMT_INLINE void end_block(size_t) const {}
@@ -725,9 +716,7 @@ struct input_expression
/// @brief Base class of all output expressoins
struct output_expression
{
- using value_type = generic;
- using size_type = infinite;
- constexpr size_type size() const noexcept { return {}; }
+ constexpr static size_t size() noexcept { return infinite_size; }
CMT_INLINE void output_begin_block(size_t) const {}
CMT_INLINE void output_end_block(size_t) const {}
diff --git a/include/kfr/base/vec.hpp b/include/kfr/base/vec.hpp
@@ -699,7 +699,7 @@ struct vec : vec_t<T, N>, operators::empty
CMT_INLINE array_t arr() { return ref_cast<array_t>(v); }
template <typename U, KFR_ENABLE_IF(std::is_convertible<T, U>::value && !std::is_same<U, vec>::value)>
- constexpr operator vec<U, N>() const noexcept
+ CMT_INLINE constexpr operator vec<U, N>() const noexcept
{
return internal::conversion<vec<U, N>, vec<T, N>>::cast(*this);
}
@@ -708,8 +708,8 @@ private:
struct getter_setter;
public:
- getter_setter operator()(size_t index) { return { v, index }; }
- scalar_type operator()(size_t index) const { return v[index]; }
+ CMT_INLINE getter_setter operator()(size_t index) { return { v, index }; }
+ CMT_INLINE scalar_type operator()(size_t index) const { return v[index]; }
protected:
template <typename U, size_t M>
@@ -1332,18 +1332,19 @@ KFR_FN(high)
namespace internal
{
-template <typename Fn>
+template <typename T, typename Fn>
struct expression_lambda : input_expression
{
+ using value_type = T;
CMT_INLINE expression_lambda(Fn&& fn) : fn(std::move(fn)) {}
- template <typename T, size_t N, KFR_ENABLE_IF(N&& is_callable<Fn, cinput_t, size_t, vec_t<T, N>>::value)>
+ template <size_t N, KFR_ENABLE_IF(N&& is_callable<Fn, cinput_t, size_t, vec_t<T, N>>::value)>
CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const
{
return fn(cinput, index, y);
}
- template <typename T, size_t N, KFR_ENABLE_IF(N&& is_callable<Fn, size_t>::value)>
+ template <size_t N, KFR_ENABLE_IF(N&& is_callable<Fn, size_t>::value)>
CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const
{
vec<T, N> result;
@@ -1353,7 +1354,7 @@ struct expression_lambda : input_expression
}
return result;
}
- template <typename T, size_t N, KFR_ENABLE_IF(N&& is_callable<Fn>::value)>
+ template <size_t N, KFR_ENABLE_IF(N&& is_callable<Fn>::value)>
CMT_INLINE vec<T, N> operator()(cinput_t, size_t, vec_t<T, N>) const
{
vec<T, N> result;
@@ -1368,10 +1369,10 @@ struct expression_lambda : input_expression
};
}
-template <typename Fn>
-internal::expression_lambda<decay<Fn>> lambda(Fn&& fn)
+template <typename T, typename Fn>
+internal::expression_lambda<T, decay<Fn>> lambda(Fn&& fn)
{
- return internal::expression_lambda<Fn>(std::move(fn));
+ return internal::expression_lambda<T, decay<Fn>>(std::move(fn));
}
}
@@ -1394,7 +1395,10 @@ struct compound_type_traits<kfr::simd<T, N>>
template <typename U>
using deep_rebind = kfr::simd<cometa::deep_rebind<subtype, U>, N>;
- static constexpr const subtype& at(const kfr::simd<T, N>& value, size_t index) { return value[index]; }
+ CMT_INLINE static constexpr const subtype& at(const kfr::simd<T, N>& value, size_t index)
+ {
+ return value[index];
+ }
};
#endif
@@ -1412,7 +1416,7 @@ struct compound_type_traits<kfr::vec<T, N>>
template <typename U>
using deep_rebind = kfr::vec<cometa::deep_rebind<subtype, U>, N>;
- static constexpr subtype at(const kfr::vec<T, N>& value, size_t index) { return value[index]; }
+ CMT_INLINE static constexpr subtype at(const kfr::vec<T, N>& value, size_t index) { return value[index]; }
};
template <typename T, size_t N>
@@ -1429,7 +1433,10 @@ struct compound_type_traits<kfr::mask<T, N>>
template <typename U>
using deep_rebind = kfr::mask<cometa::deep_rebind<subtype, U>, N>;
- static constexpr subtype at(const kfr::mask<T, N>& value, size_t index) { return value[index]; }
+ CMT_INLINE static constexpr subtype at(const kfr::mask<T, N>& value, size_t index)
+ {
+ return value[index];
+ }
};
}
namespace std
diff --git a/include/kfr/dsp/impulse.hpp b/include/kfr/dsp/impulse.hpp
@@ -33,9 +33,10 @@ namespace kfr
/**
* @brief Returns expression template that generates unit impulse
*/
+template <typename T = int>
inline auto simpleimpulse()
{
- return lambda([](cinput_t, size_t index, auto x) {
+ return lambda<T>([](cinput_t, size_t index, auto x) {
if (index == 0)
return onoff(x);
else
diff --git a/tests/complex_test.cpp b/tests/complex_test.cpp
@@ -147,9 +147,6 @@ TEST(complex_basic_expressions)
TEST(complex_function_expressions)
{
- static_assert(is_generic<decltype(counter())>::value, "");
- static_assert(is_generic<decltype(sqr(counter()))>::value, "");
-
const univector<c32, 4> uv1 = sqr(counter());
CHECK(uv1[0] == c32{ 0, 0 });
CHECK(uv1[1] == c32{ 1, 0 });