commit 51d4e60bd55b1a68556ac5ca2d443c970769adb1
parent 02cbb79df47c516954dee8e4dfd7f5b6988e415f
Author: d.levin256@gmail.com <d.levin256@gmail.com>
Date: Tue, 4 Oct 2022 08:11:14 +0100
Rename files
Diffstat:
8 files changed, 502 insertions(+), 1216 deletions(-)
diff --git a/include/kfr/base/basic_expressions.hpp b/include/kfr/base/basic_expressions.hpp
@@ -25,684 +25,651 @@
*/
#pragma once
-#include "../simd/operators.hpp"
-#include "../simd/vec.hpp"
-#include "univector.hpp"
-#include <algorithm>
+#include "expression.hpp"
namespace kfr
{
-inline namespace CMT_ARCH_NAME
+// ----------------------------------------------------------------------------
+
+template <typename T>
+struct xscalar
{
+ T value;
+};
-namespace internal
+template <typename T>
+struct expression_traits<xscalar<T>> : expression_traits_defaults
{
-template <size_t width, typename Fn>
-KFR_INTRINSIC void block_process_impl(size_t& i, size_t size, Fn&& fn)
+ using value_type = T;
+ constexpr static size_t dims = 0;
+
+ constexpr static shape<0> shapeof(const xscalar<T>& self) { return {}; }
+ constexpr static shape<0> shapeof() { return {}; }
+};
+
+template <typename T>
+KFR_INTRINSIC xscalar<T> scalar(T value)
{
- CMT_LOOP_NOUNROLL
- for (; i < size / width * width; i += width)
- fn(i, csize_t<width>());
+ return { std::move(value) };
}
-} // namespace internal
-template <size_t... widths, typename Fn>
-KFR_INTRINSIC void block_process(size_t size, csizes_t<widths...>, Fn&& fn)
+template <typename T = fbase>
+KFR_INTRINSIC xscalar<T> zeros()
{
- size_t i = 0;
- swallow{ (internal::block_process_impl<widths>(i, size, std::forward<Fn>(fn)), 0)... };
+ return { static_cast<T>(0) };
}
-namespace internal
+template <typename T = fbase>
+KFR_INTRINSIC xscalar<T> ones()
{
+ return { static_cast<T>(1) };
+}
-template <typename To, typename E>
-struct expression_cast : expression_with_arguments<E>
+inline namespace CMT_ARCH_NAME
{
- using value_type = To;
- KFR_MEM_INTRINSIC expression_cast(E&& expr) CMT_NOEXCEPT
- : expression_with_arguments<E>(std::forward<E>(expr))
- {
- }
+template <typename T, index_t Axis, size_t N>
+KFR_INTRINSIC vec<T, N> get_elements(const xscalar<T>& self, const shape<0>& index,
+ const axis_params<Axis, N>&)
+{
+ return self.value;
+}
+} // namespace CMT_ARCH_NAME
- template <size_t N>
- friend KFR_INTRINSIC vec<To, N> get_elements(const expression_cast& self, cinput_t input, size_t index,
- vec_shape<To, N>)
- {
- return self.argument_first(input, index, vec_shape<To, N>());
- }
+// ----------------------------------------------------------------------------
+
+template <typename T, index_t Dims = 1>
+struct xcounter
+{
+ T start;
+ T steps[Dims];
+
+ T back() const { return steps[Dims - 1]; }
+ T front() const { return steps[0]; }
};
-template <typename T, typename E1>
-struct expression_iterator
+template <typename T, index_t Dims>
+struct expression_traits<xcounter<T, Dims>> : expression_traits_defaults
{
- constexpr expression_iterator(E1&& e1) : e1(std::forward<E1>(e1)) {}
- struct iterator
- {
- T operator*() const { return get(); }
- T get() const { return get_elements(expr.e1, cinput, position, vec_shape<T, 1>()).front(); }
- iterator& operator++()
- {
- ++position;
- return *this;
- }
- iterator operator++(int)
- {
- iterator copy = *this;
- ++(*this);
- return copy;
- }
- bool operator!=(const iterator& other) const { return position != other.position; }
- const expression_iterator& expr;
- size_t position;
- };
- iterator begin() const { return { *this, 0 }; }
- iterator end() const { return { *this, e1.size() }; }
- E1 e1;
+ using value_type = T;
+ constexpr static size_t dims = Dims;
+
+ constexpr static shape<dims> shapeof(const xcounter<T, Dims>& self) { return shape<dims>(max_index_t); }
+ constexpr static shape<dims> shapeof() { return shape<dims>(max_index_t); }
};
-} // namespace internal
-template <typename To, typename E, KFR_ENABLE_IF(is_input_expression<E>)>
-KFR_INTRINSIC internal::expression_cast<To, E> cast(E&& expr)
+template <typename T, typename... Args, typename Tout = std::common_type_t<T, Args...>>
+KFR_INTRINSIC xcounter<Tout, sizeof...(Args)> counter(T start, Args... steps)
{
- return internal::expression_cast<To, E>(std::forward<E>(expr));
+ return { static_cast<Tout>(std::move(start)), { static_cast<Tout>(std::move(steps))... } };
}
-template <typename E1, typename T = value_type_of<E1>>
-KFR_INTRINSIC internal::expression_iterator<T, E1> to_iterator(E1&& e1)
+inline namespace CMT_ARCH_NAME
{
- return internal::expression_iterator<T, E1>(std::forward<E1>(e1));
-}
-template <typename... Ts, typename T = common_type<Ts...>>
-inline auto sequence(const Ts&... list)
+template <typename T, index_t Axis, size_t N>
+KFR_INTRINSIC vec<T, N> get_elements(const xcounter<T, 1>& self, const shape<1>& index,
+ const axis_params<Axis, N>&)
{
- return lambda<T>([seq = std::array<T, sizeof...(Ts)>{ { static_cast<T>(list)... } }](size_t index)
- { return seq[index % seq.size()]; });
+ T acc = self.start;
+ acc += static_cast<T>(index.back()) * self.back();
+ return acc + enumerate(vec_shape<T, N>(), self.back());
}
+template <typename T, index_t dims, index_t Axis, size_t N>
+KFR_INTRINSIC vec<T, N> get_elements(const xcounter<T, dims>& self, const shape<dims>& index,
+ const axis_params<Axis, N>&)
+{
+ T acc = self.start;
+ vec<T, dims> tindices = cast<T>(*index);
+ cfor(csize<0>, csize<dims>, [&](auto i) CMT_INLINE_LAMBDA { acc += tindices[i] * self.steps[i]; });
+ return acc + enumerate(vec_shape<T, N>(), self.steps[Axis]);
+}
+} // namespace CMT_ARCH_NAME
-template <typename T = int>
-KFR_INTRINSIC auto zeros()
+// ----------------------------------------------------------------------------
+
+template <typename Arg>
+struct xslice : public xwitharguments<Arg>
{
- return lambda<T>([](cinput_t, size_t, auto x) { return zerovector(x); });
-}
+ constexpr static index_t dims = expression_dims<Arg>;
+ shape<dims> start;
+ shape<dims> size;
-template <typename T = int>
-KFR_INTRINSIC auto ones()
+ KFR_MEM_INTRINSIC xslice(Arg&& arg, shape<dims> start, shape<dims> size)
+ : xwitharguments<Arg>{ std::forward<Arg>(arg) }, start(start), size(size)
+ {
+ }
+};
+
+template <typename Arg>
+struct expression_traits<xslice<Arg>> : expression_traits_defaults
{
- return lambda<T>([](cinput_t, size_t, auto) { return 1; });
-}
+ using ArgTraits = expression_traits<Arg>;
+
+ using value_type = typename ArgTraits::value_type;
+ constexpr static size_t dims = ArgTraits::dims;
+ constexpr static bool random_access = ArgTraits::random_access;
-template <typename T = int>
-KFR_INTRINSIC auto counter()
+ KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof(const xslice<Arg>& self)
+ {
+ return min(ArgTraits::shapeof(self.first()).sub_inf(self.start), self.size);
+ }
+ KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof() { return shape<dims>(0); }
+};
+
+template <typename Arg, KFR_ACCEPT_EXPRESSIONS(Arg), index_t Dims = expression_dims<Arg>>
+KFR_INTRINSIC xslice<Arg> slice(Arg&& arg, shape<Dims> start, shape<Dims> size)
{
- return lambda<T>([](cinput_t, size_t index, auto x) { return enumerate(x) + index; });
+ return { std::forward<Arg>(arg), start, size };
}
-template <typename T1>
-KFR_INTRINSIC auto counter(T1 start)
+template <typename Arg, KFR_ACCEPT_EXPRESSIONS(Arg), index_t Dims = expression_dims<Arg>>
+KFR_INTRINSIC xslice<Arg> truncate(Arg&& arg, shape<Dims> size)
{
- return lambda<T1>([start](cinput_t, size_t index, auto x) { return enumerate(x) + index + start; });
+ return { std::forward<Arg>(arg), shape<Dims>{ 0 }, size };
}
-template <typename T1, typename T2>
-KFR_INTRINSIC auto counter(T1 start, T2 step)
+
+inline namespace CMT_ARCH_NAME
{
- return lambda<common_type<T1, T2>>([start, step](cinput_t, size_t index, auto x)
- { return (enumerate(x) + index) * step + start; });
+
+template <typename Arg, index_t NDims, index_t Axis, size_t N,
+ typename T = typename expression_traits<xslice<Arg>>::value_type>
+KFR_INTRINSIC vec<T, N> get_elements(const xslice<Arg>& self, const shape<NDims>& index,
+ const axis_params<Axis, N>& sh)
+{
+ return static_cast<vec<T, N>>(get_elements(self.first(), index.add(self.start), sh));
}
-template <typename Gen>
-struct segment
+template <typename Arg, index_t NDims, index_t Axis, size_t N,
+ typename T = typename expression_traits<xslice<Arg>>::value_type>
+KFR_INTRINSIC void set_elements(const xslice<Arg>& self, const shape<NDims>& index,
+ const axis_params<Axis, N>& sh, const identity<vec<T, N>>& value)
{
- template <typename Gen_>
- constexpr segment(size_t start, Gen_&& gen) : start(start), gen(std::forward<Gen_>(gen))
- {
- }
- size_t start;
- Gen gen;
-};
+ set_elements(self.first(), index.add(self.start), sh, value);
+}
+} // namespace CMT_ARCH_NAME
+
+// ----------------------------------------------------------------------------
-enum symmetric_linspace_t
+template <typename T, typename Arg>
+struct xcast : public xwitharguments<Arg>
{
- symmetric_linspace
+ using xwitharguments<Arg>::xwitharguments;
};
-namespace internal
+template <typename T, typename Arg>
+struct expression_traits<xcast<T, Arg>> : expression_traits_defaults
{
-template <typename T, typename E1>
-struct expression_reader
-{
- constexpr expression_reader(E1&& e1) CMT_NOEXCEPT : e1(std::forward<E1>(e1)) {}
- T read() const
+ using ArgTraits = expression_traits<Arg>;
+
+ using value_type = T;
+ constexpr static size_t dims = ArgTraits::dims;
+ constexpr static bool random_access = ArgTraits::random_access;
+
+ KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof(const xcast<T, Arg>& self)
{
- const T result = get_elements(e1, cinput, m_position, vec_shape<T, 1>());
- m_position++;
- return result;
+ return ArgTraits::shapeof(self.first());
}
- mutable size_t m_position = 0;
- E1 e1;
+ KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof() { return ArgTraits::shapeof(); }
};
-template <typename T, typename E1>
-struct expression_writer
+
+template <typename T, typename Arg, KFR_ACCEPT_EXPRESSIONS(Arg)>
+KFR_INTRINSIC xcast<T, Arg> cast(Arg&& arg)
{
- constexpr expression_writer(E1&& e1) CMT_NOEXCEPT : e1(std::forward<E1>(e1)) {}
- template <typename U>
- void write(U value)
- {
- e1(coutput, m_position, vec<U, 1>(value));
- m_position++;
- }
- size_t m_position = 0;
- E1 e1;
-};
-} // namespace internal
+ return { std::forward<Arg>(arg) };
+}
-template <typename T, typename E1>
-internal::expression_reader<T, E1> reader(E1&& e1)
+template <typename T, typename Arg, KFR_ACCEPT_EXPRESSIONS(Arg)>
+KFR_INTRINSIC xcast<T, Arg> cast(Arg&& arg, ctype_t<T>)
{
- static_assert(is_input_expression<E1>, "E1 must be an expression");
- return internal::expression_reader<T, E1>(std::forward<E1>(e1));
+ return { std::forward<Arg>(arg) };
}
-template <typename T, typename E1>
-internal::expression_writer<T, E1> writer(E1&& e1)
+inline namespace CMT_ARCH_NAME
{
- static_assert(is_output_expression<E1>, "E1 must be an output expression");
- return internal::expression_writer<T, E1>(std::forward<E1>(e1));
+
+template <typename T, typename Arg, index_t NDims, index_t Axis, size_t N>
+KFR_INTRINSIC vec<T, N> get_elements(const xcast<T, Arg>& self, const shape<NDims>& index,
+ const axis_params<Axis, N>& sh)
+{
+ return static_cast<vec<T, N>>(get_elements(self.first(), index, sh));
}
-namespace internal
+template <typename T, typename Arg, index_t NDims, index_t Axis, size_t N>
+KFR_INTRINSIC void set_elements(const xcast<T, Arg>& self, const shape<NDims>& index,
+ const axis_params<Axis, N>& sh, const identity<vec<T, N>>& value)
{
+ set_elements(self.first(), index, sh, value);
+}
+} // namespace CMT_ARCH_NAME
+
+// ----------------------------------------------------------------------------
-template <typename E1>
-struct expression_slice : expression_with_arguments<E1>
+template <typename T, index_t Dims, typename Fn, bool Rnd>
+struct xlambda
{
- using value_type = value_type_of<E1>;
- using T = value_type;
- expression_slice(E1&& e1, size_t start, size_t size)
- : expression_with_arguments<E1>(std::forward<E1>(e1)), start(start),
- new_size(size_min(size, size_sub(std::get<0>(this->args).size(), start)))
- {
- }
- template <size_t N>
- friend KFR_INTRINSIC vec<T, N> get_elements(const expression_slice& self, cinput_t cinput, size_t index,
- vec_shape<T, N> y)
- {
- return self.argument_first(cinput, index + self.start, y);
- }
- size_t size() const { return new_size; }
- size_t start;
- size_t new_size;
+ Fn&& fn;
};
-template <typename E1>
-struct expression_reverse : expression_with_arguments<E1>
+template <typename T, index_t Dims, typename Fn, bool Rnd>
+struct expression_traits<xlambda<T, Dims, Fn, Rnd>> : expression_traits_defaults
{
- using value_type = value_type_of<E1>;
- using T = value_type;
- expression_reverse(E1&& e1) : expression_with_arguments<E1>(std::forward<E1>(e1)), expr_size(e1.size()) {}
- template <size_t N>
- friend KFR_INTRINSIC vec<T, N> get_elements(const expression_reverse& self, cinput_t cinput, size_t index,
- vec_shape<T, N> y)
+ using value_type = T;
+ constexpr static size_t dims = Dims;
+ constexpr static inline bool random_access = Rnd;
+
+ KFR_MEM_INTRINSIC constexpr static shape<Dims> shapeof(const xlambda<T, Dims, Fn, Rnd>& self)
{
- return reverse(self.argument_first(cinput, self.expr_size - index - N, y));
+ return shape<Dims>(infinite_size);
}
- size_t size() const { return expr_size; }
- size_t expr_size;
+ KFR_MEM_INTRINSIC constexpr static shape<Dims> shapeof() { return shape<Dims>(infinite_size); }
};
-template <typename T, bool precise = false>
-struct expression_linspace;
-
-template <typename T>
-struct expression_linspace<T, false> : input_expression
+template <typename T, index_t Dims = 1, typename Fn, bool RandomAccess = true>
+KFR_INTRINSIC xlambda<T, Dims, Fn, RandomAccess> lambda(Fn&& fn, cbool_t<RandomAccess> = {})
{
- using value_type = T;
+ return { std::forward<Fn>(fn) };
+}
+template <typename T, index_t Dims = 1, typename Fn>
+KFR_INTRINSIC xlambda<T, Dims, Fn, false> lambda_generator(Fn&& fn)
+{
+ return { std::forward<Fn>(fn) };
+}
- KFR_MEM_INTRINSIC constexpr size_t size() const CMT_NOEXCEPT { return truncate_size; }
+template <typename... Ts, typename T = std::common_type_t<Ts...>>
+KFR_INTRINSIC auto sequence(const Ts&... list)
+{
+ return lambda<T>([seq = std::array<T, sizeof...(Ts)>{ { static_cast<T>(list)... } }](size_t index)
+ { return seq[index % seq.size()]; });
+}
- expression_linspace(T start, T stop, size_t size, bool endpoint = false, bool truncate = false)
- : start(start), offset((stop - start) / T(endpoint ? size - 1 : size)),
- truncate_size(truncate ? size : infinite_size)
- {
- }
+inline namespace CMT_ARCH_NAME
+{
- expression_linspace(symmetric_linspace_t, T symsize, size_t size, bool endpoint = false)
- : expression_linspace(-symsize, +symsize, size, endpoint)
- {
- }
+template <typename T, index_t Dims, typename Fn, bool Rnd, index_t Axis, size_t N>
+KFR_INTRINSIC vec<T, N> get_elements(const xlambda<T, Dims, Fn, Rnd>& self, const shape<Dims>& index,
+ const axis_params<Axis, N>& sh)
+{
+ if constexpr (std::is_invocable_v<Fn, shape<Dims>, csize_t<N>>)
+ return self.fn(index, sh);
+ else if constexpr (std::is_invocable_v<Fn, shape<Dims>>)
+ return vec<T, N>{ [&](size_t idx) { return self.fn(index.add(idx)); } };
+ else if constexpr (std::is_invocable_v<Fn>)
+ return apply<N>(self.fn);
+ else
+ return czeros;
+}
- template <size_t N>
- friend KFR_INTRINSIC vec<T, N> get_elements(const expression_linspace& self, cinput_t, size_t index,
- vec_shape<T, N> x)
- {
- using TI = itype<T>;
- return T(self.start) + (enumerate(x) + static_cast<T>(static_cast<TI>(index))) * T(self.offset);
- }
+} // namespace CMT_ARCH_NAME
- T start;
- T offset;
- size_t truncate_size;
-};
+// ----------------------------------------------------------------------------
-template <typename T>
-struct expression_linspace<T, true> : input_expression
+template <typename Arg>
+struct xpadded : public xwitharguments<Arg>
{
- using value_type = T;
+ using ArgTraits = typename xwitharguments<Arg>::first_arg_trait;
+ typename ArgTraits::value_type fill_value;
+ shape<ArgTraits::dims> input_shape;
- KFR_MEM_INTRINSIC constexpr size_t size() const CMT_NOEXCEPT { return truncate_size; }
-
- expression_linspace(T start, T stop, size_t size, bool endpoint = false, bool truncate = false)
- : start(start), stop(stop), invsize(1.0 / T(endpoint ? size - 1 : size)),
- truncate_size(truncate ? size : infinite_size)
+ KFR_MEM_INTRINSIC xpadded(Arg&& arg, typename ArgTraits::value_type fill_value)
+ : xwitharguments<Arg>{ std::forward<Arg>(arg) }, fill_value(std::move(fill_value)),
+ input_shape(ArgTraits::shapeof(this->first()))
{
}
+};
- expression_linspace(symmetric_linspace_t, T symsize, size_t size, bool endpoint = false)
- : expression_linspace(-symsize, +symsize, size, endpoint)
- {
- }
+template <typename Arg, typename T = expression_value_type<Arg>>
+KFR_INTRINSIC xpadded<Arg> padded(Arg&& arg, T fill_value = T{})
+{
+ static_assert(expression_dims<Arg> >= 1);
+ return { std::forward<Arg>(arg), std::move(fill_value) };
+}
- template <size_t N>
- friend KFR_INTRINSIC vec<T, N> get_elements(const expression_linspace& self, cinput_t, size_t index,
- vec_shape<T, N> x)
- {
- using TI = itype<T>;
- return mix((enumerate(x) + static_cast<T>(static_cast<TI>(index))) * self.invsize, self.start,
- self.stop);
- }
- template <typename U, size_t N>
- KFR_MEM_INTRINSIC static vec<U, N> mix(const vec<U, N>& t, U x, U y)
- {
- return (U(1.0) - t) * x + t * y;
- }
+template <typename Arg>
+struct expression_traits<xpadded<Arg>> : expression_traits_defaults
+{
+ using ArgTraits = expression_traits<Arg>;
- T start;
- T stop;
- T invsize;
- size_t truncate_size;
+ using value_type = typename ArgTraits::value_type;
+ constexpr static size_t dims = ArgTraits::dims;
+ constexpr static bool random_access = ArgTraits::random_access;
+
+ KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof(const xpadded<Arg>& self) { return infinite_size; }
+ KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof() { return infinite_size; }
};
-template <typename... E>
-struct expression_sequence : expression_with_arguments<E...>
+inline namespace CMT_ARCH_NAME
{
-public:
- using base = expression_with_arguments<E...>;
-
- using value_type = common_type<value_type_of<E>...>;
- using T = value_type;
- template <typename... Expr_>
- KFR_MEM_INTRINSIC expression_sequence(const size_t (&segments)[base::count], Expr_&&... expr) CMT_NOEXCEPT
- : base(std::forward<Expr_>(expr)...)
+template <typename Arg, index_t Axis, size_t N, typename Traits = expression_traits<xpadded<Arg>>,
+ typename T = typename Traits::value_type>
+KFR_INTRINSIC vec<T, N> get_elements(const xpadded<Arg>& self, const shape<Traits::dims>& index,
+ const axis_params<Axis, N>& sh)
+{
+ if (index.ge(self.input_size))
{
- std::copy(std::begin(segments), std::end(segments), this->segments.begin() + 1);
- this->segments[0] = 0;
- this->segments[base::count + 1] = size_t(-1);
+ return self.fill_value;
}
-
- template <size_t N>
- KFR_INTRINSIC friend vec<T, N> get_elements(const expression_sequence& self, cinput_t cinput,
- size_t index, vec_shape<T, N> y)
+ else if (CMT_LIKELY(index.add(N).le(self.input_size)))
{
- std::size_t sindex =
- size_t(std::upper_bound(std::begin(self.segments), std::end(self.segments), index) - 1 -
- std::begin(self.segments));
- if (CMT_LIKELY(self.segments[sindex + 1] - index >= N))
- return get_elements(self, cinput, index, sindex - 1, y);
- else
+ return get_elements(self.first(), index, sh);
+ }
+ else
+ {
+ vec<T, N> x = self.fill_value;
+ for (size_t i = 0; i < N; i++)
{
- vec<T, N> result;
- CMT_PRAGMA_CLANG(clang loop unroll_count(4))
- for (size_t i = 0; i < N; i++)
- {
- sindex = self.segments[sindex + 1] == index ? sindex + 1 : sindex;
- result.data()[i] = get_elements(self, cinput, index, sindex - 1, vec_shape<T, 1>()).front();
- index++;
- }
- return result;
+ shape ish = index.add(i);
+ if (ish.back() < self.input_size.back())
+ x[i] = get_elements(self.first(), ish, csize_t<1>()).front();
}
+ return x;
}
+}
-protected:
- template <size_t N>
- KFR_INTRINSIC friend vec<T, N> get_elements(const expression_sequence& self, cinput_t cinput,
- size_t index, size_t expr_index, vec_shape<T, N> y)
- {
- return cswitch(
- indicesfor_t<E...>(), expr_index, [&](auto val) { return self.argument(cinput, val, index, y); },
- [&]() { return zerovector(y); });
- }
+} // namespace CMT_ARCH_NAME
- std::array<size_t, base::count + 2> segments;
-};
+// ----------------------------------------------------------------------------
-template <typename Fn, typename E>
-struct expression_adjacent : expression_with_arguments<E>
+template <typename Arg>
+struct xreverse : public xwitharguments<Arg>
{
- using value_type = value_type_of<E>;
- using T = value_type;
+ using ArgTraits = typename xwitharguments<Arg>::first_arg_trait;
+ shape<ArgTraits::dims> input_shape;
- expression_adjacent(Fn&& fn, E&& e)
- : expression_with_arguments<E>(std::forward<E>(e)), fn(std::forward<Fn>(fn))
+ KFR_MEM_INTRINSIC xreverse(Arg&& arg)
+ : xwitharguments<Arg>{ std::forward<Arg>(arg) }, input_shape(ArgTraits::shapeof(this->first()))
{
}
-
- template <size_t N>
- KFR_INTRINSIC friend vec<T, N> get_elements(const expression_adjacent& self, cinput_t cinput,
- size_t index, vec_shape<T, N>)
- {
- const vec<T, N> in = self.argument_first(cinput, index, vec_shape<T, N>());
- const vec<T, N> delayed = insertleft(self.data, in);
- self.data = in[N - 1];
- return self.fn(in, delayed);
- }
- Fn fn;
- mutable value_type data = value_type(0);
};
-} // namespace internal
-/** @brief Returns the subrange of the given expression
- */
-template <typename E1>
-KFR_INTRINSIC internal::expression_slice<E1> slice(E1&& e1, size_t start, size_t size = infinite_size)
+template <typename Arg>
+KFR_INTRINSIC xreverse<Arg> x_reverse(Arg&& arg)
{
- return internal::expression_slice<E1>(std::forward<E1>(e1), start, size);
+ static_assert(expression_dims<Arg> >= 1);
+ return { std::forward<Arg>(arg) };
}
-/** @brief Returns the expression truncated to the given size
- */
-template <typename E1>
-KFR_INTRINSIC internal::expression_slice<E1> truncate(E1&& e1, size_t size)
+template <typename Arg>
+struct expression_traits<xreverse<Arg>> : expression_traits_defaults
{
- return internal::expression_slice<E1>(std::forward<E1>(e1), 0, size);
-}
+ using ArgTraits = expression_traits<Arg>;
-/** @brief Returns the reversed expression
- */
-template <typename E1, KFR_ENABLE_IF(is_input_expression<E1>)>
-KFR_INTRINSIC internal::expression_reverse<E1> reverse(E1&& e1)
+ using value_type = typename ArgTraits::value_type;
+ constexpr static size_t dims = ArgTraits::dims;
+ static_assert(ArgTraits::random_access, "xreverse requires an expression with random access");
+
+ KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof(const xreverse<Arg>& self)
+ {
+ return ArgTraits::shapeof(self.first());
+ }
+ KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof() { return ArgTraits::shapeof(); }
+};
+
+inline namespace CMT_ARCH_NAME
{
- static_assert(!is_infinite<E1>, "e1 must be a sized expression (use slice())");
- return internal::expression_reverse<E1>(std::forward<E1>(e1));
-}
-/** @brief Returns evenly spaced numbers over a specified interval.
- *
- * @param start The starting value of the sequence
- * @param stop The end value of the sequence. if ``endpoint`` is ``false``, the last value is excluded
- * @param size Number of samples to generate
- * @param endpoint If ``true``, ``stop`` is the last sample. Otherwise, it is not included
- * @param truncate If ``true``, linspace returns exactly size elements, otherwise, returns infinite sequence
- */
-template <typename T1, typename T2, bool precise = false, typename TF = ftype<common_type<T1, T2>>>
-KFR_INTRINSIC internal::expression_linspace<TF, precise> linspace(T1 start, T2 stop, size_t size,
- bool endpoint = false,
- bool truncate = false)
+template <typename Arg, index_t Axis, size_t N, typename Traits = expression_traits<xreverse<Arg>>,
+ typename T = typename Traits::value_type>
+KFR_INTRINSIC vec<T, N> get_elements(const xreverse<Arg>& self, const shape<Traits::dims>& index,
+ const axis_params<Axis, N>& sh)
{
- return internal::expression_linspace<TF, precise>(start, stop, size, endpoint, truncate);
+ return reverse(get_elements(self.first(), self.input_shape.sub(index).sub(shape<Traits::dims>(N)), sh));
}
-KFR_FN(linspace)
-template <typename T, bool precise = false, typename TF = ftype<T>>
-KFR_INTRINSIC internal::expression_linspace<TF, precise> symmlinspace(T symsize, size_t size,
- bool endpoint = false)
+} // namespace CMT_ARCH_NAME
+
+// ----------------------------------------------------------------------------
+
+template <index_t... Values>
+struct fixed_shape
{
- return internal::expression_linspace<TF, precise>(symmetric_linspace, symsize, size, endpoint);
-}
-KFR_FN(symmlinspace)
+ constexpr static shape<sizeof...(Values)> get() { return { Values... }; }
+};
-template <size_t size, typename... E>
-KFR_INTRINSIC internal::expression_sequence<decay<E>...> gen_sequence(const size_t (&list)[size], E&&... gens)
+template <typename Arg, typename Shape>
+struct xfixshape : public xwitharguments<Arg>
{
- static_assert(size == sizeof...(E), "Lists must be of equal length");
- return internal::expression_sequence<decay<E>...>(list, std::forward<E>(gens)...);
-}
-KFR_FN(gen_sequence)
+ using ArgTraits = typename xwitharguments<Arg>::first_arg_trait;
-/**
- * @brief Returns template expression that returns the result of calling \f$ fn(x_i, x_{i-1}) \f$
- */
-template <typename Fn, typename E1>
-KFR_INTRINSIC internal::expression_adjacent<Fn, E1> adjacent(Fn&& fn, E1&& e1)
+ KFR_MEM_INTRINSIC xfixshape(Arg&& arg) : xwitharguments<Arg>{ std::forward<Arg>(arg) } {}
+};
+
+template <typename Arg, index_t... ShapeValues>
+KFR_INTRINSIC xfixshape<Arg, fixed_shape<ShapeValues...>> fixshape(Arg&& arg,
+ const fixed_shape<ShapeValues...>&)
{
- return internal::expression_adjacent<Fn, E1>(std::forward<Fn>(fn), std::forward<E1>(e1));
+ return { std::forward<Arg>(arg) };
}
-namespace internal
+template <typename Arg, index_t... ShapeValues>
+struct expression_traits<xfixshape<Arg, fixed_shape<ShapeValues...>>> : expression_traits_defaults
{
-template <typename E>
-struct expression_padded : expression_with_arguments<E>
-{
- using value_type = value_type_of<E>;
+ using ArgTraits = expression_traits<Arg>;
- KFR_MEM_INTRINSIC constexpr static size_t size() CMT_NOEXCEPT { return infinite_size; }
+ using value_type = typename ArgTraits::value_type;
+ constexpr static size_t dims = ArgTraits::dims;
+ constexpr static bool random_access = ArgTraits::random_access;
- expression_padded(value_type fill_value, E&& e)
- : expression_with_arguments<E>(std::forward<E>(e)), fill_value(fill_value), input_size(e.size())
+ KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof(
+ const xfixshape<Arg, fixed_shape<ShapeValues...>>& self)
{
+ return fixed_shape<ShapeValues...>::get();
}
-
- template <size_t N>
- KFR_INTRINSIC friend vec<value_type, N> get_elements(const expression_padded& self, cinput_t cinput,
- size_t index, vec_shape<value_type, N> y)
- {
- if (CMT_UNLIKELY(index >= self.input_size))
- {
- return self.fill_value;
- }
- else if (CMT_LIKELY(index + N <= self.input_size))
- {
- return self.argument_first(cinput, index, y);
- }
- else
- {
- vec<value_type, N> x{};
- for (size_t i = 0; i < N; i++)
- {
- if (CMT_LIKELY(index + i < self.input_size))
- x[i] = self.argument_first(cinput, index + i, vec_shape<value_type, 1>()).front();
- else
- x[i] = self.fill_value;
- }
- return x;
- }
- }
- value_type fill_value;
- const size_t input_size;
+ KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof() { return fixed_shape<ShapeValues...>::get(); }
};
-} // namespace internal
-/**
- * @brief Returns infinite template expression that pads e with fill_value (default value = 0)
- */
-template <typename E, typename T = value_type_of<E>>
-internal::expression_padded<E> padded(E&& e, const T& fill_value = T(0))
+inline namespace CMT_ARCH_NAME
+{
+
+template <typename Arg, typename Shape, index_t Axis, size_t N,
+ typename Traits = expression_traits<xfixshape<Arg, Shape>>,
+ typename T = typename Traits::value_type>
+KFR_INTRINSIC vec<T, N> get_elements(const xfixshape<Arg, Shape>& self, const shape<Traits::dims>& index,
+ const axis_params<Axis, N>& sh)
{
- static_assert(is_input_expression<E>, "E must be an input expression");
- return internal::expression_padded<E>(fill_value, std::forward<E>(e));
+ return get_elements(self.first(), index, sh);
}
-namespace internal
+template <typename Arg, typename Shape, index_t Axis, size_t N,
+ typename Traits = expression_traits<xfixshape<Arg, Shape>>,
+ typename T = typename Traits::value_type>
+KFR_INTRINSIC void set_elements(xfixshape<Arg, Shape>& self, const shape<Traits::dims>& index,
+ const axis_params<Axis, N>& sh, const identity<vec<T, N>>& value)
{
-template <typename... E>
-struct multioutput : output_expression
+ set_elements(self.first(), index, sh, value);
+}
+
+} // namespace CMT_ARCH_NAME
+
+// ----------------------------------------------------------------------------
+
+template <typename Arg, index_t OutDims>
+struct xreshape : public xwitharguments<Arg>
{
- template <typename... E_>
- multioutput(E_&&... e) : outputs(std::forward<E_>(e)...)
- {
- }
- template <typename T, size_t N>
- KFR_INTRINSIC friend void set_elements(multioutput& self, coutput_t coutput, size_t index,
- const vec<T, N>& x)
+ using ArgTraits = typename xwitharguments<Arg>::first_arg_trait;
+ shape<ArgTraits::dims> in_shape;
+ shape<OutDims> out_shape;
+
+ KFR_MEM_INTRINSIC xreshape(Arg&& arg, const shape<OutDims>& out_shape)
+ : xwitharguments<Arg>{ std::forward<Arg>(arg) }, in_shape(ArgTraits::shapeof(arg)),
+ out_shape(out_shape)
{
- cfor(csize_t<0>(), csize_t<sizeof...(E)>(),
- [&](auto n) { set_elements(std::get<val_of(decltype(n)())>(self.outputs), coutput, index, x); });
}
- std::tuple<E...> outputs;
-
-private:
};
-template <typename... E>
-struct expression_pack : expression_with_arguments<E...>
+template <typename Arg, index_t OutDims>
+KFR_INTRINSIC xreshape<Arg, OutDims> reshape(Arg&& arg, const shape<OutDims>& out_shape)
{
- constexpr static size_t count = sizeof...(E);
+ return { std::forward<Arg>(arg), out_shape };
+}
- expression_pack(E&&... e) : expression_with_arguments<E...>(std::forward<E>(e)...) {}
- using value_type = vec<common_type<value_type_of<E>...>, count>;
- using T = value_type;
+template <typename Arg, index_t OutDims>
+struct expression_traits<xreshape<Arg, OutDims>> : expression_traits_defaults
+{
+ using ArgTraits = expression_traits<Arg>;
- using expression_with_arguments<E...>::size;
+ using value_type = typename ArgTraits::value_type;
+ constexpr static size_t dims = OutDims;
+ constexpr static bool random_access = ArgTraits::random_access;
- template <size_t N>
- friend KFR_INTRINSIC vec<T, N> get_elements(const expression_pack& self, cinput_t cinput, size_t index,
- vec_shape<T, N> y)
+ KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof(const xreshape<Arg, OutDims>& self)
{
- return self.call(cinput, fn::packtranspose(), index, y);
+ return self.out_shape;
}
+ KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof() { return shape<dims>{ 0 }; }
};
-template <typename... E>
-struct expression_unpack : private expression_with_arguments<E...>, output_expression
+inline namespace CMT_ARCH_NAME
{
- using expression_with_arguments<E...>::begin_block;
- using expression_with_arguments<E...>::end_block;
- using output_expression::begin_block;
- using output_expression::end_block;
- constexpr static size_t count = sizeof...(E);
-
- expression_unpack(E&&... e) : expression_with_arguments<E...>(std::forward<E>(e)...) {}
- using expression_with_arguments<E...>::size;
-
- template <typename U, size_t N>
- KFR_INTRINSIC friend void set_elements(expression_unpack& self, coutput_t coutput, size_t index,
- const vec<vec<U, count>, N>& x)
+template <typename Arg, index_t outdims, index_t Axis, size_t N,
+ typename Traits = expression_traits<xreshape<Arg, outdims>>,
+ typename T = typename Traits::value_type>
+KFR_INTRINSIC vec<T, N> get_elements(const xreshape<Arg, outdims>& self, const shape<Traits::dims>& index,
+ const axis_params<Axis, N>& sh)
+{
+ using ArgTraits = typename Traits::ArgTraits;
+ constexpr index_t indims = ArgTraits::dims;
+ if constexpr (N == 1)
{
- self.output(coutput, index, x, csizeseq<count>);
+ const shape<indims> idx = self.in_shape.from_flat(self.out_shape.to_flat(index));
+ return get_elements(self.first(), idx, axis_params<indims - 1, 1>{});
}
-
- template <typename Input, KFR_ENABLE_IF(is_input_expression<Input>)>
- KFR_MEM_INTRINSIC expression_unpack& operator=(Input&& input)
+ else
{
- process(*this, std::forward<Input>(input));
- return *this;
- }
+ const shape<indims> first_idx = self.in_shape.from_flat(self.out_shape.to_flat(index));
+ const shape<indims> last_idx =
+ self.in_shape.from_flat(self.out_shape.to_flat(index.add_at(N - 1, cindex<Axis>)));
-private:
- template <typename U, size_t N, size_t... indices>
- void output(coutput_t coutput, size_t index, const vec<vec<U, count>, N>& x, csizes_t<indices...>)
- {
- const vec<vec<U, N>, count> xx = vec<vec<U, N>, count>::from_flatten(transpose<count>(flatten(x)));
- swallow{ (set_elements(std::get<indices>(this->args), coutput, index, xx[indices]), void(), 0)... };
- }
-};
-} // namespace internal
+ const shape<indims> diff_idx = last_idx.sub(first_idx);
-template <typename... E, KFR_ENABLE_IF(is_output_expressions<E...>)>
-internal::expression_unpack<E...> unpack(E&&... e)
-{
- return internal::expression_unpack<E...>(std::forward<E>(e)...);
-}
+ vec<T, N> result;
+ bool done = false;
-template <typename... E, KFR_ENABLE_IF(is_input_expressions<E...>)>
-internal::expression_pack<internal::arg<E>...> pack(E&&... e)
-{
- return internal::expression_pack<internal::arg<E>...>(std::forward<E>(e)...);
+ if (diff_idx.sum() == N - 1)
+ {
+ cforeach(cvalseq_t<index_t, indims, 0>{},
+ [&](auto n) CMT_INLINE_LAMBDA
+ {
+ constexpr index_t axis = val_of<decltype(n)>({});
+ if (!done && diff_idx[axis] == N - 1)
+ {
+ result = get_elements(self.first(), first_idx, axis_params<axis, N>{});
+ done = true;
+ }
+ });
+ }
+
+ if (!done)
+ {
+ portable_vec<T, N> tmp;
+ CMT_LOOP_NOUNROLL
+ for (size_t i = 0; i < N; ++i)
+ {
+ shape<Traits::dims> idx = index.add_at(i, cindex<Axis>);
+ tmp[i] = get_elements(self.first(), self.in_shape.from_flat(self.out_shape.to_flat(idx)),
+ axis_params<indims - 1, 1>{})
+ .front();
+ }
+ result = tmp;
+ }
+ return result;
+ }
}
-template <typename OutExpr, typename InExpr>
-struct task_partition
+template <typename Arg, index_t outdims, index_t Axis, size_t N,
+ typename Traits = expression_traits<xreshape<Arg, outdims>>,
+ typename T = typename Traits::value_type>
+KFR_INTRINSIC void set_elements(xreshape<Arg, outdims>& self, const shape<Traits::dims>& index,
+ const axis_params<Axis, N>& sh, const identity<vec<T, N>>& value)
{
- task_partition(OutExpr&& output, InExpr&& input, size_t size, size_t chunk_size, size_t count)
- : output(std::forward<OutExpr>(output)), input(std::forward<InExpr>(input)), size(size),
- chunk_size(chunk_size), count(count)
+ using ArgTraits = typename Traits::ArgTraits;
+ constexpr index_t indims = ArgTraits::dims;
+ if constexpr (N == 1)
{
+ const shape<indims> idx = self.in_shape.from_flat(self.out_shape.to_flat(index));
+ set_elements(self.first(), idx, axis_params<indims - 1, 1>{}, value);
}
- OutExpr output;
- InExpr input;
- size_t size;
- size_t chunk_size;
- size_t count;
- size_t operator()(size_t index)
+ else
{
- if (CMT_UNLIKELY(index >= count))
- return 0;
- return process(output, input, index * chunk_size,
- index == count - 1 ? size - (count - 1) * chunk_size : chunk_size);
- }
-};
+ const shape<indims> first_idx = self.in_shape.from_flat(self.out_shape.to_flat(index));
+ const shape<indims> last_idx =
+ self.in_shape.from_flat(self.out_shape.to_flat(index.add_at(N - 1, cindex<Axis>)));
-template <typename OutExpr, typename InExpr, typename T = value_type_of<InExpr>>
-task_partition<OutExpr, InExpr> partition(OutExpr&& output, InExpr&& input, size_t count,
- size_t minimum_size = 0)
-{
- static_assert(!is_infinite<OutExpr> || !is_infinite<InExpr>, "");
+ const shape<indims> diff_idx = last_idx.sub(first_idx);
- minimum_size = minimum_size == 0 ? vector_width<T> * 8 : minimum_size;
- const size_t size = size_min(output.size(), input.size());
- const size_t chunk_size = align_up(std::max(size / count, minimum_size), vector_width<T>);
+ bool done = false;
- task_partition<OutExpr, InExpr> result(std::forward<OutExpr>(output), std::forward<InExpr>(input), size,
- chunk_size, (size + chunk_size - 1) / chunk_size);
- return result;
+ cforeach(cvalseq_t<index_t, indims, 0>{},
+ [&](auto n) CMT_INLINE_LAMBDA
+ {
+ constexpr index_t axis = val_of<decltype(n)>({});
+ if (!done && diff_idx[axis] == N - 1)
+ {
+ set_elements(self.first(), first_idx, axis_params<axis, N>{}, value);
+ done = true;
+ }
+ });
+
+ if (!done)
+ {
+ CMT_LOOP_NOUNROLL
+ for (size_t i = 0; i < N; ++i)
+ {
+ set_elements(self.first(),
+ self.in_shape.from_flat(self.out_shape.to_flat(index.add_at(i, cindex<Axis>))),
+ axis_params<indims - 1, 1>{}, vec<T, 1>{ value[i] });
+ }
+ }
+ }
}
-namespace internal
+} // namespace CMT_ARCH_NAME
+
+// ----------------------------------------------------------------------------
+
+template <typename T, bool truncated = true>
+struct xlinspace
{
+ T start;
+ T stop;
+ index_t size;
+ bool endpoint;
+};
-template <typename E1, typename E2>
-struct concatenate_expression : expression_with_arguments<E1, E2>
+template <typename T, bool truncated>
+struct expression_traits<xlinspace<T, truncated>> : expression_traits_defaults
{
- using value_type = common_type<value_type_of<E1>, value_type_of<E2>>;
- using T = value_type;
+ using value_type = T;
+ constexpr static size_t dims = 1;
- KFR_MEM_INTRINSIC constexpr size_t size() const CMT_NOEXCEPT
+ constexpr static shape<dims> shapeof(const xlinspace<T, truncated>& self)
{
- return size_add(std::get<0>(this->args).size(), std::get<1>(this->args).size());
- }
- template <typename E1_, typename E2_>
- concatenate_expression(E1_&& e1, E2_&& e2)
- : expression_with_arguments<E1, E2>(std::forward<E1_>(e1), std::forward<E2_>(e2))
- {
- }
-
- template <size_t N>
- KFR_INTRINSIC friend vec<T, N> get_elements(const concatenate_expression& self, cinput_t cinput,
- size_t index, vec_shape<T, N> y)
- {
- const size_t size0 = std::get<0>(self.args).size();
- if (index >= size0)
- {
- return self.argument(cinput, csize<1>, index - size0, y);
- }
- else if (CMT_LIKELY(index + N <= size0))
- {
- return self.argument(cinput, csize<0>, index, y);
- }
- else // (index < size0) && (index + N > size0)
- {
- vec<T, N> result;
- for (size_t i = 0; i < size0 - index; ++i)
- {
- result[i] = self.argument(cinput, csize<0>, index + i, vec_shape<T, 1>{})[0];
- }
- for (size_t i = size0 - index; i < N; ++i)
- {
- result[i] = self.argument(cinput, csize<1>, index + i - size0, vec_shape<T, 1>{})[0];
- }
- return result;
- }
+ return shape<dims>(truncated ? self.size : infinite_size);
}
+ constexpr static shape<dims> shapeof() { return shape<dims>(truncated ? 0 : infinite_size); }
};
-} // namespace internal
-template <typename E1, typename E2, KFR_ENABLE_IF(is_input_expression<E1>&& is_input_expression<E2>)>
-internal::concatenate_expression<E1, E2> concatenate(E1&& e1, E2&& e2)
+template <bool truncated = false, typename T1, typename T2, typename Tout = std::common_type_t<T1, T2>>
+KFR_INTRINSIC xlinspace<Tout, truncated> linspace(T1 start, T2 stop, size_t size, bool endpoint = false)
{
- return { std::forward<E1>(e1), std::forward<E2>(e2) };
+ return { static_cast<Tout>(start), static_cast<Tout>(stop), size, endpoint };
}
+inline namespace CMT_ARCH_NAME
+{
+
+template <typename T, bool truncated, size_t N>
+KFR_INTRINSIC vec<T, N> get_elements(const xlinspace<T, truncated>& self, const shape<1>& index,
+ const axis_params<0, N>&)
+{
+ T acc = self.start;
+ using TI = itype<T>;
+ return mix(enumerate(vec_shape<T, N>(), static_cast<T>(static_cast<TI>(index))) * self.invsize,
+ self.start, self.stop);
+}
} // namespace CMT_ARCH_NAME
+
+// ----------------------------------------------------------------------------
+
} // namespace kfr
diff --git a/include/kfr/base/expression.hpp b/include/kfr/base/expression.hpp
@@ -112,8 +112,33 @@ struct expression_traits_defaults
namespace internal_generic
{
template <typename... Xs>
+using expressions_condition = std::void_t<expression_traits<Xs>...>;
+template <typename... Xs>
using expressions_check = std::enable_if_t<(expression_traits<Xs>::explicit_operand || ...)>;
-}
+} // namespace internal_generic
+
+template <typename T>
+using enable_if_input_expression =
+ std::void_t<expression_traits<T>,
+ decltype(get_elements(std::declval<T>(), shape<expression_traits<T>::dims>(),
+ axis_params<0, 1>{}))>;
+
+template <typename T>
+using enable_if_output_expression =
+ std::void_t<expression_traits<T>,
+ decltype(set_elements(std::declval<T&>(), shape<expression_traits<T>::dims>(),
+ axis_params<0, 1>{},
+ vec<typename expression_traits<T>::value_type, 1>{}))>;
+
+template <typename T>
+using enable_if_inout_output_expression =
+ std::void_t<enable_if_input_expression<T>, enable_if_output_expression<T>>;
+
+template <typename... T>
+using enable_if_input_expressions = std::void_t<enable_if_input_expression<T>...>;
+
+template <typename... T>
+using enable_if_output_expressions = std::void_t<enable_if_output_expression<T>...>;
#define KFR_ACCEPT_EXPRESSIONS(...) internal_generic::expressions_check<__VA_ARGS__>* = nullptr
diff --git a/include/kfr/base/function_expressions.hpp b/include/kfr/base/function_expressions.hpp
@@ -1,30 +0,0 @@
-/** @addtogroup expressions
- * @{
- */
-/*
- Copyright (C) 2016 D Levin (https://www.kfrlib.com)
- This file is part of KFR
-
- KFR is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 2 of the License, or
- (at your option) any later version.
-
- KFR is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with KFR.
-
- If GPL is not suitable for your project, you must purchase a commercial license to use KFR.
- Buying a commercial license is mandatory as soon as you develop commercial activities without
- disclosing the source code of your own applications.
- See https://www.kfrlib.com for details.
- */
-#pragma once
-
-namespace kfr
-{
-} // namespace kfr
diff --git a/include/kfr/base/math_expressions.hpp b/include/kfr/base/math_expressions.hpp
@@ -26,7 +26,7 @@
#pragma once
#include "../math.hpp"
-#include "new_expressions.hpp"
+#include "basic_expressions.hpp"
#include "expression.hpp"
namespace kfr
diff --git a/include/kfr/base/new_expressions.hpp b/include/kfr/base/new_expressions.hpp
@@ -1,675 +0,0 @@
-/** @addtogroup expressions
- * @{
- */
-/*
- Copyright (C) 2016 D Levin (https://www.kfrlib.com)
- This file is part of KFR
-
- KFR is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 2 of the License, or
- (at your option) any later version.
-
- KFR is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with KFR.
-
- If GPL is not suitable for your project, you must purchase a commercial license to use KFR.
- Buying a commercial license is mandatory as soon as you develop commercial activities without
- disclosing the source code of your own applications.
- See https://www.kfrlib.com for details.
- */
-#pragma once
-
-#include "expression.hpp"
-
-namespace kfr
-{
-// ----------------------------------------------------------------------------
-
-template <typename T>
-struct xscalar
-{
- T value;
-};
-
-template <typename T>
-struct expression_traits<xscalar<T>> : expression_traits_defaults
-{
- using value_type = T;
- constexpr static size_t dims = 0;
-
- constexpr static shape<0> shapeof(const xscalar<T>& self) { return {}; }
- constexpr static shape<0> shapeof() { return {}; }
-};
-
-template <typename T>
-KFR_INTRINSIC xscalar<T> scalar(T value)
-{
- return { std::move(value) };
-}
-
-template <typename T = fbase>
-KFR_INTRINSIC xscalar<T> zeros()
-{
- return { static_cast<T>(0) };
-}
-
-template <typename T = fbase>
-KFR_INTRINSIC xscalar<T> ones()
-{
- return { static_cast<T>(1) };
-}
-
-inline namespace CMT_ARCH_NAME
-{
-template <typename T, index_t Axis, size_t N>
-KFR_INTRINSIC vec<T, N> get_elements(const xscalar<T>& self, const shape<0>& index,
- const axis_params<Axis, N>&)
-{
- return self.value;
-}
-} // namespace CMT_ARCH_NAME
-
-// ----------------------------------------------------------------------------
-
-template <typename T, index_t Dims = 1>
-struct xcounter
-{
- T start;
- T steps[Dims];
-
- T back() const { return steps[Dims - 1]; }
- T front() const { return steps[0]; }
-};
-
-template <typename T, index_t Dims>
-struct expression_traits<xcounter<T, Dims>> : expression_traits_defaults
-{
- using value_type = T;
- constexpr static size_t dims = Dims;
-
- constexpr static shape<dims> shapeof(const xcounter<T, Dims>& self) { return shape<dims>(max_index_t); }
- constexpr static shape<dims> shapeof() { return shape<dims>(max_index_t); }
-};
-
-template <typename T, typename... Args, typename Tout = std::common_type_t<T, Args...>>
-KFR_INTRINSIC xcounter<Tout, sizeof...(Args)> counter(T start, Args... steps)
-{
- return { static_cast<Tout>(std::move(start)), { static_cast<Tout>(std::move(steps))... } };
-}
-
-inline namespace CMT_ARCH_NAME
-{
-
-template <typename T, index_t Axis, size_t N>
-KFR_INTRINSIC vec<T, N> get_elements(const xcounter<T, 1>& self, const shape<1>& index,
- const axis_params<Axis, N>&)
-{
- T acc = self.start;
- acc += static_cast<T>(index.back()) * self.back();
- return acc + enumerate(vec_shape<T, N>(), self.back());
-}
-template <typename T, index_t dims, index_t Axis, size_t N>
-KFR_INTRINSIC vec<T, N> get_elements(const xcounter<T, dims>& self, const shape<dims>& index,
- const axis_params<Axis, N>&)
-{
- T acc = self.start;
- vec<T, dims> tindices = cast<T>(*index);
- cfor(csize<0>, csize<dims>, [&](auto i) CMT_INLINE_LAMBDA { acc += tindices[i] * self.steps[i]; });
- return acc + enumerate(vec_shape<T, N>(), self.steps[Axis]);
-}
-} // namespace CMT_ARCH_NAME
-
-// ----------------------------------------------------------------------------
-
-template <typename Arg>
-struct xslice : public xwitharguments<Arg>
-{
- constexpr static index_t dims = expression_dims<Arg>;
- shape<dims> start;
- shape<dims> size;
-
- KFR_MEM_INTRINSIC xslice(Arg&& arg, shape<dims> start, shape<dims> size)
- : xwitharguments<Arg>{ std::forward<Arg>(arg) }, start(start), size(size)
- {
- }
-};
-
-template <typename Arg>
-struct expression_traits<xslice<Arg>> : expression_traits_defaults
-{
- using ArgTraits = expression_traits<Arg>;
-
- using value_type = typename ArgTraits::value_type;
- constexpr static size_t dims = ArgTraits::dims;
- constexpr static bool random_access = ArgTraits::random_access;
-
- KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof(const xslice<Arg>& self)
- {
- return min(ArgTraits::shapeof(self.first()).sub_inf(self.start), self.size);
- }
- KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof() { return shape<dims>(0); }
-};
-
-template <typename Arg, KFR_ACCEPT_EXPRESSIONS(Arg), index_t Dims = expression_dims<Arg>>
-KFR_INTRINSIC xslice<Arg> slice(Arg&& arg, shape<Dims> start, shape<Dims> size)
-{
- return { std::forward<Arg>(arg), start, size };
-}
-
-template <typename Arg, KFR_ACCEPT_EXPRESSIONS(Arg), index_t Dims = expression_dims<Arg>>
-KFR_INTRINSIC xslice<Arg> truncate(Arg&& arg, shape<Dims> size)
-{
- return { std::forward<Arg>(arg), shape<Dims>{ 0 }, size };
-}
-
-inline namespace CMT_ARCH_NAME
-{
-
-template <typename Arg, index_t NDims, index_t Axis, size_t N,
- typename T = typename expression_traits<xslice<Arg>>::value_type>
-KFR_INTRINSIC vec<T, N> get_elements(const xslice<Arg>& self, const shape<NDims>& index,
- const axis_params<Axis, N>& sh)
-{
- return static_cast<vec<T, N>>(get_elements(self.first(), index.add(self.start), sh));
-}
-
-template <typename Arg, index_t NDims, index_t Axis, size_t N,
- typename T = typename expression_traits<xslice<Arg>>::value_type>
-KFR_INTRINSIC void set_elements(const xslice<Arg>& self, const shape<NDims>& index,
- const axis_params<Axis, N>& sh, const identity<vec<T, N>>& value)
-{
- set_elements(self.first(), index.add(self.start), sh, value);
-}
-} // namespace CMT_ARCH_NAME
-
-// ----------------------------------------------------------------------------
-
-template <typename T, typename Arg>
-struct xcast : public xwitharguments<Arg>
-{
- using xwitharguments<Arg>::xwitharguments;
-};
-
-template <typename T, typename Arg>
-struct expression_traits<xcast<T, Arg>> : expression_traits_defaults
-{
- using ArgTraits = expression_traits<Arg>;
-
- using value_type = T;
- constexpr static size_t dims = ArgTraits::dims;
- constexpr static bool random_access = ArgTraits::random_access;
-
- KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof(const xcast<T, Arg>& self)
- {
- return ArgTraits::shapeof(self.first());
- }
- KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof() { return ArgTraits::shapeof(); }
-};
-
-template <typename T, typename Arg, KFR_ACCEPT_EXPRESSIONS(Arg)>
-KFR_INTRINSIC xcast<T, Arg> cast(Arg&& arg)
-{
- return { std::forward<Arg>(arg) };
-}
-
-template <typename T, typename Arg, KFR_ACCEPT_EXPRESSIONS(Arg)>
-KFR_INTRINSIC xcast<T, Arg> cast(Arg&& arg, ctype_t<T>)
-{
- return { std::forward<Arg>(arg) };
-}
-
-inline namespace CMT_ARCH_NAME
-{
-
-template <typename T, typename Arg, index_t NDims, index_t Axis, size_t N>
-KFR_INTRINSIC vec<T, N> get_elements(const xcast<T, Arg>& self, const shape<NDims>& index,
- const axis_params<Axis, N>& sh)
-{
- return static_cast<vec<T, N>>(get_elements(self.first(), index, sh));
-}
-
-template <typename T, typename Arg, index_t NDims, index_t Axis, size_t N>
-KFR_INTRINSIC void set_elements(const xcast<T, Arg>& self, const shape<NDims>& index,
- const axis_params<Axis, N>& sh, const identity<vec<T, N>>& value)
-{
- set_elements(self.first(), index, sh, value);
-}
-} // namespace CMT_ARCH_NAME
-
-// ----------------------------------------------------------------------------
-
-template <typename T, index_t Dims, typename Fn, bool Rnd>
-struct xlambda
-{
- Fn&& fn;
-};
-
-template <typename T, index_t Dims, typename Fn, bool Rnd>
-struct expression_traits<xlambda<T, Dims, Fn, Rnd>> : expression_traits_defaults
-{
- using value_type = T;
- constexpr static size_t dims = Dims;
- constexpr static inline bool random_access = Rnd;
-
- KFR_MEM_INTRINSIC constexpr static shape<Dims> shapeof(const xlambda<T, Dims, Fn, Rnd>& self)
- {
- return shape<Dims>(infinite_size);
- }
- KFR_MEM_INTRINSIC constexpr static shape<Dims> shapeof() { return shape<Dims>(infinite_size); }
-};
-
-template <typename T, index_t Dims = 1, typename Fn, bool RandomAccess = true>
-KFR_INTRINSIC xlambda<T, Dims, Fn, RandomAccess> lambda(Fn&& fn, cbool_t<RandomAccess> = {})
-{
- return { std::forward<Fn>(fn) };
-}
-template <typename T, index_t Dims = 1, typename Fn>
-KFR_INTRINSIC xlambda<T, Dims, Fn, false> lambda_generator(Fn&& fn)
-{
- return { std::forward<Fn>(fn) };
-}
-
-template <typename... Ts, typename T = std::common_type_t<Ts...>>
-KFR_INTRINSIC auto sequence(const Ts&... list)
-{
- return lambda<T>([seq = std::array<T, sizeof...(Ts)>{ { static_cast<T>(list)... } }](size_t index)
- { return seq[index % seq.size()]; });
-}
-
-inline namespace CMT_ARCH_NAME
-{
-
-template <typename T, index_t Dims, typename Fn, bool Rnd, index_t Axis, size_t N>
-KFR_INTRINSIC vec<T, N> get_elements(const xlambda<T, Dims, Fn, Rnd>& self, const shape<Dims>& index,
- const axis_params<Axis, N>& sh)
-{
- if constexpr (std::is_invocable_v<Fn, shape<Dims>, csize_t<N>>)
- return self.fn(index, sh);
- else if constexpr (std::is_invocable_v<Fn, shape<Dims>>)
- return vec<T, N>{ [&](size_t idx) { return self.fn(index.add(idx)); } };
- else if constexpr (std::is_invocable_v<Fn>)
- return apply<N>(self.fn);
- else
- return czeros;
-}
-
-} // namespace CMT_ARCH_NAME
-
-// ----------------------------------------------------------------------------
-
-template <typename Arg>
-struct xpadded : public xwitharguments<Arg>
-{
- using ArgTraits = typename xwitharguments<Arg>::first_arg_trait;
- typename ArgTraits::value_type fill_value;
- shape<ArgTraits::dims> input_shape;
-
- KFR_MEM_INTRINSIC xpadded(Arg&& arg, typename ArgTraits::value_type fill_value)
- : xwitharguments<Arg>{ std::forward<Arg>(arg) }, fill_value(std::move(fill_value)),
- input_shape(ArgTraits::shapeof(this->first()))
- {
- }
-};
-
-template <typename Arg, typename T = expression_value_type<Arg>>
-KFR_INTRINSIC xpadded<Arg> padded(Arg&& arg, T fill_value = T{})
-{
- static_assert(expression_dims<Arg> >= 1);
- return { std::forward<Arg>(arg), std::move(fill_value) };
-}
-
-template <typename Arg>
-struct expression_traits<xpadded<Arg>> : expression_traits_defaults
-{
- using ArgTraits = expression_traits<Arg>;
-
- using value_type = typename ArgTraits::value_type;
- constexpr static size_t dims = ArgTraits::dims;
- constexpr static bool random_access = ArgTraits::random_access;
-
- KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof(const xpadded<Arg>& self) { return infinite_size; }
- KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof() { return infinite_size; }
-};
-
-inline namespace CMT_ARCH_NAME
-{
-
-template <typename Arg, index_t Axis, size_t N, typename Traits = expression_traits<xpadded<Arg>>,
- typename T = typename Traits::value_type>
-KFR_INTRINSIC vec<T, N> get_elements(const xpadded<Arg>& self, const shape<Traits::dims>& index,
- const axis_params<Axis, N>& sh)
-{
- if (index.ge(self.input_size))
- {
- return self.fill_value;
- }
- else if (CMT_LIKELY(index.add(N).le(self.input_size)))
- {
- return get_elements(self.first(), index, sh);
- }
- else
- {
- vec<T, N> x = self.fill_value;
- for (size_t i = 0; i < N; i++)
- {
- shape ish = index.add(i);
- if (ish.back() < self.input_size.back())
- x[i] = get_elements(self.first(), ish, csize_t<1>()).front();
- }
- return x;
- }
-}
-
-} // namespace CMT_ARCH_NAME
-
-// ----------------------------------------------------------------------------
-
-template <typename Arg>
-struct xreverse : public xwitharguments<Arg>
-{
- using ArgTraits = typename xwitharguments<Arg>::first_arg_trait;
- shape<ArgTraits::dims> input_shape;
-
- KFR_MEM_INTRINSIC xreverse(Arg&& arg)
- : xwitharguments<Arg>{ std::forward<Arg>(arg) }, input_shape(ArgTraits::shapeof(this->first()))
- {
- }
-};
-
-template <typename Arg>
-KFR_INTRINSIC xreverse<Arg> x_reverse(Arg&& arg)
-{
- static_assert(expression_dims<Arg> >= 1);
- return { std::forward<Arg>(arg) };
-}
-
-template <typename Arg>
-struct expression_traits<xreverse<Arg>> : expression_traits_defaults
-{
- using ArgTraits = expression_traits<Arg>;
-
- using value_type = typename ArgTraits::value_type;
- constexpr static size_t dims = ArgTraits::dims;
- static_assert(ArgTraits::random_access, "xreverse requires an expression with random access");
-
- KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof(const xreverse<Arg>& self)
- {
- return ArgTraits::shapeof(self.first());
- }
- KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof() { return ArgTraits::shapeof(); }
-};
-
-inline namespace CMT_ARCH_NAME
-{
-
-template <typename Arg, index_t Axis, size_t N, typename Traits = expression_traits<xreverse<Arg>>,
- typename T = typename Traits::value_type>
-KFR_INTRINSIC vec<T, N> get_elements(const xreverse<Arg>& self, const shape<Traits::dims>& index,
- const axis_params<Axis, N>& sh)
-{
- return reverse(get_elements(self.first(), self.input_shape.sub(index).sub(shape<Traits::dims>(N)), sh));
-}
-
-} // namespace CMT_ARCH_NAME
-
-// ----------------------------------------------------------------------------
-
-template <index_t... Values>
-struct fixed_shape
-{
- constexpr static shape<sizeof...(Values)> get() { return { Values... }; }
-};
-
-template <typename Arg, typename Shape>
-struct xfixshape : public xwitharguments<Arg>
-{
- using ArgTraits = typename xwitharguments<Arg>::first_arg_trait;
-
- KFR_MEM_INTRINSIC xfixshape(Arg&& arg) : xwitharguments<Arg>{ std::forward<Arg>(arg) } {}
-};
-
-template <typename Arg, index_t... ShapeValues>
-KFR_INTRINSIC xfixshape<Arg, fixed_shape<ShapeValues...>> fixshape(Arg&& arg,
- const fixed_shape<ShapeValues...>&)
-{
- return { std::forward<Arg>(arg) };
-}
-
-template <typename Arg, index_t... ShapeValues>
-struct expression_traits<xfixshape<Arg, fixed_shape<ShapeValues...>>> : expression_traits_defaults
-{
- using ArgTraits = expression_traits<Arg>;
-
- using value_type = typename ArgTraits::value_type;
- constexpr static size_t dims = ArgTraits::dims;
- constexpr static bool random_access = ArgTraits::random_access;
-
- KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof(
- const xfixshape<Arg, fixed_shape<ShapeValues...>>& self)
- {
- return fixed_shape<ShapeValues...>::get();
- }
- KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof() { return fixed_shape<ShapeValues...>::get(); }
-};
-
-inline namespace CMT_ARCH_NAME
-{
-
-template <typename Arg, typename Shape, index_t Axis, size_t N,
- typename Traits = expression_traits<xfixshape<Arg, Shape>>,
- typename T = typename Traits::value_type>
-KFR_INTRINSIC vec<T, N> get_elements(const xfixshape<Arg, Shape>& self, const shape<Traits::dims>& index,
- const axis_params<Axis, N>& sh)
-{
- return get_elements(self.first(), index, sh);
-}
-
-template <typename Arg, typename Shape, index_t Axis, size_t N,
- typename Traits = expression_traits<xfixshape<Arg, Shape>>,
- typename T = typename Traits::value_type>
-KFR_INTRINSIC void set_elements(xfixshape<Arg, Shape>& self, const shape<Traits::dims>& index,
- const axis_params<Axis, N>& sh, const identity<vec<T, N>>& value)
-{
- set_elements(self.first(), index, sh, value);
-}
-
-} // namespace CMT_ARCH_NAME
-
-// ----------------------------------------------------------------------------
-
-template <typename Arg, index_t OutDims>
-struct xreshape : public xwitharguments<Arg>
-{
- using ArgTraits = typename xwitharguments<Arg>::first_arg_trait;
- shape<ArgTraits::dims> in_shape;
- shape<OutDims> out_shape;
-
- KFR_MEM_INTRINSIC xreshape(Arg&& arg, const shape<OutDims>& out_shape)
- : xwitharguments<Arg>{ std::forward<Arg>(arg) }, in_shape(ArgTraits::shapeof(arg)),
- out_shape(out_shape)
- {
- }
-};
-
-template <typename Arg, index_t OutDims>
-KFR_INTRINSIC xreshape<Arg, OutDims> reshape(Arg&& arg, const shape<OutDims>& out_shape)
-{
- return { std::forward<Arg>(arg), out_shape };
-}
-
-template <typename Arg, index_t OutDims>
-struct expression_traits<xreshape<Arg, OutDims>> : expression_traits_defaults
-{
- using ArgTraits = expression_traits<Arg>;
-
- using value_type = typename ArgTraits::value_type;
- constexpr static size_t dims = OutDims;
- constexpr static bool random_access = ArgTraits::random_access;
-
- KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof(const xreshape<Arg, OutDims>& self)
- {
- return self.out_shape;
- }
- KFR_MEM_INTRINSIC constexpr static shape<dims> shapeof() { return shape<dims>{ 0 }; }
-};
-
-inline namespace CMT_ARCH_NAME
-{
-
-template <typename Arg, index_t outdims, index_t Axis, size_t N,
- typename Traits = expression_traits<xreshape<Arg, outdims>>,
- typename T = typename Traits::value_type>
-KFR_INTRINSIC vec<T, N> get_elements(const xreshape<Arg, outdims>& self, const shape<Traits::dims>& index,
- const axis_params<Axis, N>& sh)
-{
- using ArgTraits = typename Traits::ArgTraits;
- constexpr index_t indims = ArgTraits::dims;
- if constexpr (N == 1)
- {
- const shape<indims> idx = self.in_shape.from_flat(self.out_shape.to_flat(index));
- return get_elements(self.first(), idx, axis_params<indims - 1, 1>{});
- }
- else
- {
- const shape<indims> first_idx = self.in_shape.from_flat(self.out_shape.to_flat(index));
- const shape<indims> last_idx =
- self.in_shape.from_flat(self.out_shape.to_flat(index.add_at(N - 1, cindex<Axis>)));
-
- const shape<indims> diff_idx = last_idx.sub(first_idx);
-
- vec<T, N> result;
- bool done = false;
-
- if (diff_idx.sum() == N - 1)
- {
- cforeach(cvalseq_t<index_t, indims, 0>{},
- [&](auto n) CMT_INLINE_LAMBDA
- {
- constexpr index_t axis = val_of<decltype(n)>({});
- if (!done && diff_idx[axis] == N - 1)
- {
- result = get_elements(self.first(), first_idx, axis_params<axis, N>{});
- done = true;
- }
- });
- }
-
- if (!done)
- {
- portable_vec<T, N> tmp;
- CMT_LOOP_NOUNROLL
- for (size_t i = 0; i < N; ++i)
- {
- shape<Traits::dims> idx = index.add_at(i, cindex<Axis>);
- tmp[i] = get_elements(self.first(), self.in_shape.from_flat(self.out_shape.to_flat(idx)),
- axis_params<indims - 1, 1>{})
- .front();
- }
- result = tmp;
- }
- return result;
- }
-}
-
-template <typename Arg, index_t outdims, index_t Axis, size_t N,
- typename Traits = expression_traits<xreshape<Arg, outdims>>,
- typename T = typename Traits::value_type>
-KFR_INTRINSIC void set_elements(xreshape<Arg, outdims>& self, const shape<Traits::dims>& index,
- const axis_params<Axis, N>& sh, const identity<vec<T, N>>& value)
-{
- using ArgTraits = typename Traits::ArgTraits;
- constexpr index_t indims = ArgTraits::dims;
- if constexpr (N == 1)
- {
- const shape<indims> idx = self.in_shape.from_flat(self.out_shape.to_flat(index));
- set_elements(self.first(), idx, axis_params<indims - 1, 1>{}, value);
- }
- else
- {
- const shape<indims> first_idx = self.in_shape.from_flat(self.out_shape.to_flat(index));
- const shape<indims> last_idx =
- self.in_shape.from_flat(self.out_shape.to_flat(index.add_at(N - 1, cindex<Axis>)));
-
- const shape<indims> diff_idx = last_idx.sub(first_idx);
-
- bool done = false;
-
- cforeach(cvalseq_t<index_t, indims, 0>{},
- [&](auto n) CMT_INLINE_LAMBDA
- {
- constexpr index_t axis = val_of<decltype(n)>({});
- if (!done && diff_idx[axis] == N - 1)
- {
- set_elements(self.first(), first_idx, axis_params<axis, N>{}, value);
- done = true;
- }
- });
-
- if (!done)
- {
- CMT_LOOP_NOUNROLL
- for (size_t i = 0; i < N; ++i)
- {
- set_elements(self.first(),
- self.in_shape.from_flat(self.out_shape.to_flat(index.add_at(i, cindex<Axis>))),
- axis_params<indims - 1, 1>{}, vec<T, 1>{ value[i] });
- }
- }
- }
-}
-
-} // namespace CMT_ARCH_NAME
-
-// ----------------------------------------------------------------------------
-
-template <typename T, bool truncated = true>
-struct xlinspace
-{
- T start;
- T stop;
- index_t size;
- bool endpoint;
-};
-
-template <typename T, bool truncated>
-struct expression_traits<xlinspace<T, truncated>> : expression_traits_defaults
-{
- using value_type = T;
- constexpr static size_t dims = 1;
-
- constexpr static shape<dims> shapeof(const xlinspace<T, truncated>& self)
- {
- return shape<dims>(truncated ? self.size : infinite_size);
- }
- constexpr static shape<dims> shapeof() { return shape<dims>(truncated ? 0 : infinite_size); }
-};
-
-template <bool truncated = false, typename T1, typename T2, typename Tout = std::common_type_t<T1, T2>>
-KFR_INTRINSIC xlinspace<Tout, truncated> linspace(T1 start, T2 stop, size_t size, bool endpoint = false)
-{
- return { static_cast<Tout>(start), static_cast<Tout>(stop), size, endpoint };
-}
-
-inline namespace CMT_ARCH_NAME
-{
-
-template <typename T, bool truncated, size_t N>
-KFR_INTRINSIC vec<T, N> get_elements(const xlinspace<T, truncated>& self, const shape<1>& index,
- const axis_params<0, N>&)
-{
- T acc = self.start;
- using TI = itype<T>;
- return mix(enumerate(vec_shape<T, N>(), static_cast<T>(static_cast<TI>(index))) * self.invsize,
- self.start, self.stop);
-}
-} // namespace CMT_ARCH_NAME
-
-// ----------------------------------------------------------------------------
-
-} // namespace kfr
diff --git a/include/kfr/base/basic_expressions.hpp b/include/kfr/base/old_basic_expressions.hpp
diff --git a/sources.cmake b/sources.cmake
@@ -24,7 +24,6 @@ set(
${PROJECT_SOURCE_DIR}/include/kfr/base/expression.hpp
${PROJECT_SOURCE_DIR}/include/kfr/base/filter.hpp
${PROJECT_SOURCE_DIR}/include/kfr/base/fraction.hpp
- ${PROJECT_SOURCE_DIR}/include/kfr/base/function_expressions.hpp
${PROJECT_SOURCE_DIR}/include/kfr/base/generators.hpp
${PROJECT_SOURCE_DIR}/include/kfr/base/math_expressions.hpp
${PROJECT_SOURCE_DIR}/include/kfr/base/memory.hpp
diff --git a/tests/unit/base/tensor.cpp b/tests/unit/base/tensor.cpp
@@ -6,7 +6,7 @@
#include <kfr/base/simd_expressions.hpp>
#include <kfr/base/math_expressions.hpp>
-#include <kfr/base/new_expressions.hpp>
+#include <kfr/base/basic_expressions.hpp>
#include <kfr/base/tensor.hpp>
#include <kfr/io/tostring.hpp>
#include <kfr/simd.hpp>