16 #ifndef OPENKALMAN_EIGEN_TENSOR_LIBRARY_INTERFACE_HPP 17 #define OPENKALMAN_EIGEN_TENSOR_LIBRARY_INTERFACE_HPP 19 #include <type_traits> 32 template<Eigen3::eigen_tensor_general<true> T>
33 struct library_interface<T>
41 using IndexType =
typename Eigen::internal::traits<T>::Index;
45 template<
typename Derived>
49 #ifdef __cpp_lib_concepts 50 template<indexible Arg, std::
size_t NumIndices> requires (NumIndices == index_count_v<Arg>)
51 static constexpr values::scalar decltype(
auto)
53 template <
typename Arg, std::
size_t NumIndices, std::enable_if_t<NumIndices == index_count_v<Arg>,
int> = 0>
54 static constexpr decltype(
auto)
56 get_component(Arg&& arg,
const std::array<IndexType, NumIndices>& indices)
58 if constexpr ((Eigen::internal::traits<T>::Flags & Eigen::LvalueBit) != 0)
59 return Eigen::TensorEvaluator<std::remove_reference_t<Arg>, Eigen::DefaultDevice> {std::forward<Arg>(arg), Eigen::DefaultDevice{}}.coeffRef(indices);
61 return Eigen::TensorEvaluator<std::remove_reference_t<Arg>, Eigen::DefaultDevice> {std::forward<Arg>(arg), Eigen::DefaultDevice{}}.coeff(indices);
66 template<std::size_t ix_count,
typename I,
typename End,
typename...Ixs>
67 static constexpr decltype(
auto)
68 make_ix_array(I i,
const End& end, Ixs...indices)
70 if constexpr (ix_count == 0)
72 if (i != end)
throw std::logic_error(
"Too many indices on component access");
73 return std::array<IndexType,
sizeof...(Ixs)> {indices...};
77 if (i == end)
throw std::logic_error(
"Not enough indices on component access");
79 return make_ix_array<ix_count - 1>(++i, end, indices...,
static_cast<IndexType
>(this_ix));
85 #ifdef __cpp_lib_ranges 86 template<indexible Arg, std::ranges::input_range Indices> requires
87 std::convertible_to<std::ranges::range_value_t<Indices>,
const typename std::decay_t<Arg>::Index>
88 static constexpr values::scalar decltype(
auto)
90 template<
typename Arg,
typename Indices>
91 static constexpr decltype(
auto)
95 constexpr std::size_t ix_count = Eigen::internal::traits<T>::NumDimensions;
96 #ifdef __cpp_lib_ranges 97 namespace ranges = std::ranges;
99 return get_component(std::forward<Arg>(arg), make_ix_array<ix_count>(ranges::begin(indices), ranges::end(indices)));
103 #ifdef __cpp_lib_concepts 104 template<indexible Arg, std::
size_t NumIndices> requires (NumIndices == index_count_v<Arg>) and (not std::is_const_v<Arg>)
112 Eigen::TensorEvaluator<Arg, Eigen::DefaultDevice> {arg, Eigen::DefaultDevice{}}.coeffRef(indices) = s;
116 #ifdef __cpp_lib_ranges 117 template<indexible Arg, std::ranges::input_range Indices> requires
118 std::convertible_to<std::ranges::range_value_t<Indices>,
const typename std::decay_t<Arg>::Index> and
119 ((Eigen::internal::traits<std::decay_t<Arg>>::Flags & Eigen::LvalueBit) != 0x0) and (not std::is_const_v<Arg>)
121 template<
typename Arg,
typename Indices, std::enable_if_t<
122 ((Eigen::internal::traits<std::decay_t<Arg>>::Flags & Eigen::LvalueBit) != 0x0) and (not std::is_const_v<Arg>),
int> = 0>
127 constexpr std::size_t ix_count = Eigen::internal::traits<T>::NumDimensions;
128 #ifdef __cpp_lib_ranges 129 namespace ranges = std::ranges;
131 set_component(arg, s, make_ix_array<ix_count>(ranges::begin(indices), ranges::end(indices)));
136 template<
auto l,
typename Arg, std::size_t...Is>
137 static constexpr
auto 138 make_TensorMap_impl(
const Arg& arg, std::index_sequence<Is...>)
140 using M = Eigen::TensorFixedSize<scalar_type_of_t<Arg>, Eigen::Sizes<static_cast<std::ptrdiff_t>(index_dimension_of_v<Arg, Is>)...>, l, IndexType>;
141 return Eigen::TensorMap<const M, l> {internal::raw_data(arg), index_dimension_of_v<Arg, Is>...};
145 template<auto l,
typename Arg>
146 static constexpr
auto 147 make_TensorMap(
const Arg& arg)
149 if constexpr (has_dynamic_dimensions<Arg>)
151 using M = Eigen::Tensor<scalar_type_of_t<Arg>, index_count_v<Arg>, l, IndexType>;
152 return Eigen::TensorMap<const M, l>{internal::raw_data(arg)};
156 return make_TensorMap_impl<l>(arg, std::make_index_sequence<index_count_v<Arg>>{});
162 template<
typename Arg>
163 static decltype(
auto)
166 if constexpr (Eigen3::eigen_tensor_wrapper<Arg>)
168 return std::forward<Arg>(arg);
170 else if constexpr (internal::library_wrapper<Arg>)
174 else if constexpr (not Eigen3::eigen_tensor_general<Arg> and directly_accessible<Arg> and std::is_lvalue_reference_v<Arg>)
176 if constexpr (layout_of_v<Arg> ==
Layout::stride and internal::has_static_strides<Arg>)
178 auto strides = internal::strides(arg);
179 constexpr std::ptrdiff_t stride0 = std::get<0>(strides);
180 constexpr std::ptrdiff_t strideN = std::get<index_count_v<Arg> - 1>(strides);
181 constexpr
auto l = stride0 > strideN ? Eigen::RowMajor : Eigen::ColMajor;
183 [](
auto&& map,
auto&&...s){
184 return Eigen::TensorStridingOp {map, std::array<std::size_t, index_count_v<Arg>>{s...}};
186 std::tuple_cat(make_TensorMap<l>(arg), std::move(strides)));
190 constexpr
auto l = layout_of_v<Arg> ==
Layout::right ? Eigen::RowMajor : Eigen::ColMajor;
191 return make_TensorMap<l>(arg);
196 return Eigen3::make_eigen_tensor_wrapper(std::forward<Arg>(arg));
201 #ifdef __cpp_concepts 202 template<
typename To, Eigen3::eigen_tensor_general From> requires (std::assignable_from<To&, From&&>)
204 template<
typename To,
typename From, std::enable_if_t<Eigen3::eigen_tensor_general<From> and std::is_assignable_v<To&, From&&>,
int> = 0>
206 static void assign(To& a, From&& b)
208 a = std::forward<From>(b);
212 template<
Layout layout,
typename Scalar,
typename...D>
213 static auto make_default(D&&...d)
215 constexpr
auto options = layout ==
Layout::right ? Eigen::RowMajor : Eigen::ColMajor;
216 if constexpr (((dynamic_pattern<D>) or ...))
217 return Eigen::Tensor<Scalar,
sizeof...(D), options, IndexType>(static_cast<IndexType>(get_dimension(d))...);
219 return Eigen::TensorFixedSize<Scalar, Eigen::Sizes<static_cast<std::ptrdiff_t>(coordinates::dimension_of_v<D>)...>, options, IndexType> {};
223 #ifdef __cpp_concepts 224 template<Layout layout, writable Arg, std::convertible_to<scalar_type_of_t<Arg>> ... Scalars>
227 template<
Layout layout,
typename Arg,
typename...Scalars, std::enable_if_t<writable<Arg> and
229 std::conjunction<std::is_convertible<Scalars, typename scalar_type_of<Arg>::type>
::value...>
::value,
int> = 0>
234 arg.swap_layout().setValues({scalars...});
236 arg.setValues({scalars...});
240 #ifdef __cpp_concepts 241 template<
values::dynamic C,
typename...Ds> requires (... and (not dynamic_pattern<Ds>))
244 template<
typename C,
typename...Ds, std::enable_if_t<values::dynamic<C> and
245 (... and (not dynamic_pattern<Ds>)),
int> = 0>
246 static constexpr
auto 251 using Scalar = std::decay_t<decltype(value)>;
252 auto m = make_default<Layout::none, Scalar>(std::forward<Ds>(ds)...);
254 return Eigen::TensorCwiseNullaryOp {m, Eigen::internal::scalar_constant_op<Scalar>(
value)};
261 template<
typename Arg,
typename...Begin,
typename...Size>
263 get_slice(Arg&& arg, std::tuple<Begin...> begin, std::tuple<Size...>
size)
265 auto offsets = std::apply([](
auto&&...a) {
266 return std::array<std::size_t,
sizeof...(Begin)> {std::forward<decltype(a)>(a)...};
268 auto extents = std::apply([](
auto&&...a) {
269 return std::array<std::size_t,
sizeof...(Size)> {std::forward<decltype(a)>(a)...};
275 #ifdef __cpp_concepts 276 template<Eigen3::eigen_tensor_general<true> Arg, Eigen3::eigen_tensor_general Block,
typename...Begin>
278 template<
typename Arg,
typename Block,
typename...Begin, std::enable_if_t<
279 Eigen3::eigen_tensor_general<Arg, true> and Eigen3::eigen_tensor_general<Block>,
int> = 0>
281 static constexpr
void 282 set_slice(Arg& arg, Block&& block, Begin...begin)
284 auto offsets = std::array {
static_cast<std::size_t
>(begin)...};
285 auto extents = std::apply([](
auto&&...a) {
287 arg.slice(offsets, extents) = std::forward<Block>(block);
1085 #endif //OPENKALMAN_EIGEN_TENSOR_LIBRARY_INTERFACE_HPP Definition: basics.hpp:41
Forward declarations for OpenKalman's Eigen Tensor module interface.
Row-major storage (C or C++ style): contiguous storage in which the right-most index has a stride of ...
constexpr bool constant_matrix
Specifies that all components of an object are the same constant value.
Definition: constant_matrix.hpp:31
Arg && set_component(Arg &&arg, const scalar_type_of_t< Arg > &s, const Indices &indices)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: set_component.hpp:51
decltype(auto) constexpr get_slice(Arg &&arg, const std::tuple< Offset... > &offsets, const std::tuple< Extent... > &extents)
Extract a slice from a matrix or tensor.
Definition: get_slice.hpp:101
typename scalar_type_of< T >::type scalar_type_of_t
helper template for scalar_type_of.
Definition: scalar_type_of.hpp:54
decltype(auto) to_native_matrix(Arg &&arg)
If it isn't already, convert Arg to a native object in the library associated with LibraryObject...
Definition: to_native_matrix.hpp:35
Definition: tuple_reverse.hpp:103
constexpr bool value
T is numerical value or is reducible to a numerical value.
Definition: value.hpp:31
constexpr auto to_number(Arg arg)
Convert any values::value to a values::number.
Definition: to_number.hpp:34
decltype(auto) constexpr all_vector_space_descriptors(const T &t)
Return a collection of coordinates::pattern objects associated with T.
Definition: all_vector_space_descriptors.hpp:52
An interface to various routines from the linear algebra library associated with indexible object T...
Definition: library_interface.hpp:37
Column-major storage (Fortran, Matlab, or Eigen style): contiguous storage in which the left-most ext...
Definition: eigen-tensor-forward-declarations.hpp:30
A generalization of the above: a custom stride is specified for each index.
constexpr bool size
T is either an index representing a size, or void which represents that there is no size...
Definition: size.hpp:32
Arg && fill_components(Arg &&arg, S...s)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: fill_components.hpp:44
Layout
The layout format of a multidimensional array.
Definition: global-definitions.hpp:47
constexpr bool dynamic
T is a values::value that is not determinable at compile time.
Definition: dynamic.hpp:48
constexpr auto make_constant(C &&c, Descriptors &&descriptors)
Make a constant object based on a particular library object.
Definition: make_constant.hpp:37
constexpr To && assign(To &&a, From &&b)
Assign a writable object from an indexible object.
Definition: assign.hpp:51
decltype(auto) constexpr get_component(Arg &&arg, const Indices &indices)
Get a component of an object at a particular set of indices.
Definition: get_component.hpp:54
decltype(auto) constexpr nested_object(Arg &&arg)
Retrieve a nested object of Arg, if it exists.
Definition: nested_object.hpp:34
constexpr Arg && set_slice(Arg &&arg, Block &&block, const Begin &...begin)
Assign an object to a particular slice of a matrix or tensor.
Definition: set_slice.hpp:56