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)
93 get_component(Arg&& arg,
const Indices& indices)
95 constexpr std::size_t ix_count = Eigen::internal::traits<T>::NumDimensions;
96 return get_component(std::forward<Arg>(arg), make_ix_array<ix_count>(stdex::ranges::begin(indices), stdex::ranges::end(indices)));
100 #ifdef __cpp_lib_concepts 101 template<indexible Arg, std::
size_t NumIndices> requires (NumIndices == index_count_v<Arg>) and (not std::is_const_v<Arg>)
107 set_component(Arg& arg,
const scalar_type_of_t<T>& s,
const std::array<IndexType, NumIndices>& indices)
109 Eigen::TensorEvaluator<Arg, Eigen::DefaultDevice> {arg, Eigen::DefaultDevice{}}.coeffRef(indices) = s;
113 #ifdef __cpp_lib_ranges 114 template<indexible Arg, std::ranges::input_range Indices> requires
115 std::convertible_to<std::ranges::range_value_t<Indices>,
const typename std::decay_t<Arg>::Index> and
116 ((Eigen::internal::traits<std::decay_t<Arg>>::Flags & Eigen::LvalueBit) != 0x0) and (not std::is_const_v<Arg>)
118 template<
typename Arg,
typename Indices, std::enable_if_t<
119 ((Eigen::internal::traits<std::decay_t<Arg>>::Flags & Eigen::LvalueBit) != 0x0) and (not std::is_const_v<Arg>),
int> = 0>
122 set_component(Arg& arg,
const scalar_type_of_t<T>& s,
const Indices& indices)
124 constexpr std::size_t ix_count = Eigen::internal::traits<T>::NumDimensions;
125 set_component(arg, s, make_ix_array<ix_count>(stdex::ranges::begin(indices), stdex::ranges::end(indices)));
130 template<
auto l,
typename Arg, std::size_t...Is>
131 static constexpr
auto 134 using M = Eigen::TensorFixedSize<scalar_type_of_t<Arg>, Eigen::Sizes<static_cast<std::ptrdiff_t>(index_dimension_of_v<Arg, Is>)...>, l, IndexType>;
135 return Eigen::TensorMap<const M, l> {internal::raw_data(arg), index_dimension_of_v<Arg, Is>...};
139 template<auto l,
typename Arg>
140 static constexpr
auto 141 make_TensorMap(
const Arg& arg)
143 if constexpr (has_dynamic_dimensions<Arg>)
145 using M = Eigen::Tensor<scalar_type_of_t<Arg>, index_count_v<Arg>, l, IndexType>;
146 return Eigen::TensorMap<const M, l>{internal::raw_data(arg)};
150 return make_TensorMap_impl<l>(arg, std::make_index_sequence<index_count_v<Arg>>{});
156 template<
typename Arg>
157 static decltype(
auto)
158 to_native_matrix(Arg&& arg)
160 if constexpr (Eigen3::eigen_tensor_wrapper<Arg>)
162 return std::forward<Arg>(arg);
164 else if constexpr (internal::library_wrapper<Arg>)
168 else if constexpr (not Eigen3::eigen_tensor_general<Arg> and directly_accessible<Arg> and std::is_lvalue_reference_v<Arg>)
170 if constexpr (layout_of_v<Arg> == data_layout::stride and internal::has_static_strides<Arg>)
172 auto strides = internal::strides(arg);
173 constexpr std::ptrdiff_t stride0 = std::get<0>(strides);
174 constexpr std::ptrdiff_t strideN = std::get<index_count_v<Arg> - 1>(strides);
175 constexpr
auto l = stride0 > strideN ? Eigen::RowMajor : Eigen::ColMajor;
177 [](
auto&& map,
auto&&...s){
178 return Eigen::TensorStridingOp {map, std::array<std::size_t, index_count_v<Arg>>{s...}};
180 std::tuple_cat(make_TensorMap<l>(arg), std::move(strides)));
184 constexpr
auto l = layout_of_v<Arg> == data_layout::right ? Eigen::RowMajor : Eigen::ColMajor;
185 return make_TensorMap<l>(arg);
190 return Eigen3::make_eigen_tensor_wrapper(std::forward<Arg>(arg));
195 #ifdef __cpp_concepts 196 template<
typename To, Eigen3::eigen_tensor_general From> requires (std::assignable_from<To&, From&&>)
198 template<
typename To,
typename From, std::enable_if_t<Eigen3::eigen_tensor_general<From> and std::is_assignable_v<To&, From&&>,
int> = 0>
200 static void copy(To& a, From&& b)
202 a = std::forward<From>(b);
206 template<data_layout layout,
typename Scalar,
typename...D>
207 static auto make_default(D&&...d)
209 constexpr
auto options = layout == data_layout::right ? Eigen::RowMajor : Eigen::ColMajor;
210 if constexpr (((dynamic_pattern<D>) or ...))
211 return Eigen::Tensor<Scalar,
sizeof...(D), options, IndexType>(static_cast<IndexType>(
get_dimension(d))...);
213 return Eigen::TensorFixedSize<Scalar, Eigen::Sizes<static_cast<std::ptrdiff_t>(coordinates::dimension_of_v<D>)...>, options, IndexType> {};
217 #ifdef __cpp_concepts 218 template<data_layout layout, writable Arg, std::convertible_to<scalar_type_of_t<Arg>> ... Scalars>
219 requires (layout == data_layout::right) or (layout == data_layout::left)
221 template<data_layout layout,
typename Arg,
typename...Scalars, std::enable_if_t<writable<Arg> and
222 (layout == data_layout::right or or layout == data_layout::left) and
223 std::conjunction<std::is_convertible<Scalars, typename scalar_type_of<Arg>::type>
::value...>
::value,
int> = 0>
227 if constexpr (layout == data_layout::left)
228 arg.swap_layout().setValues({scalars...});
230 arg.setValues({scalars...});
234 #ifdef __cpp_concepts 235 template<
values::dynamic C,
typename...Ds> requires (... and (not dynamic_pattern<Ds>))
236 static constexpr constant_matrix
auto 238 template<
typename C,
typename...Ds, std::enable_if_t<values::dynamic<C> and
239 (... and (not dynamic_pattern<Ds>)),
int> = 0>
240 static constexpr
auto 245 using Scalar = std::decay_t<decltype(value)>;
246 auto m = make_default<data_layout::none, Scalar>(std::forward<Ds>(ds)...);
248 return Eigen::TensorCwiseNullaryOp {m, Eigen::internal::scalar_constant_op<Scalar>(
value)};
255 template<
typename Arg,
typename...Begin,
typename...Size>
257 get_slice(Arg&& arg, std::tuple<Begin...> begin, std::tuple<Size...>
size)
260 return std::array<std::size_t,
sizeof...(Begin)> {std::forward<decltype(a)>(a)...};
263 return std::array<std::size_t,
sizeof...(Size)> {std::forward<decltype(a)>(a)...};
265 return to_native_matrix(std::forward<Arg>(arg)).slice(offsets, extents);
269 #ifdef __cpp_concepts 270 template<Eigen3::eigen_tensor_general<true> Arg, Eigen3::eigen_tensor_general Block,
typename...Begin>
272 template<
typename Arg,
typename Block,
typename...Begin, std::enable_if_t<
273 Eigen3::eigen_tensor_general<Arg, true> and Eigen3::eigen_tensor_general<Block>,
int> = 0>
275 static constexpr
void 276 set_slice(Arg& arg, Block&& block, Begin...begin)
278 auto offsets = std::array {
static_cast<std::size_t
>(begin)...};
280 return std::array {
get_dimension(std::forward<decltype(a)>(a))...}; }, all_vector_space_descriptors(block));
281 arg.slice(offsets, extents) = std::forward<Block>(block);
Definition: basics.hpp:41
Forward declarations for OpenKalman's Eigen Tensor module interface.
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:103
decltype(auto) constexpr to_value_type(Arg &&arg)
Convert, if necessary, a fixed or dynamic value to its underlying base type.
Definition: to_value_type.hpp:28
constexpr bool value
T is a fixed or dynamic value that is reducible to a number.
Definition: value.hpp:45
decltype(auto) constexpr apply(F &&f, T &&t)
A generalization of std::apply.
Definition: apply.hpp:49
constexpr auto get_dimension(const Arg &arg)
Get the vector dimension of coordinates::pattern Arg.
Definition: get_dimension.hpp:54
An interface to various routines from the linear algebra library associated with indexible object T...
Definition: library_interface.hpp:42
Definition: eigen-tensor-forward-declarations.hpp:30
constexpr bool size
T is either an index representing a size, or unbounded_size_t, which indicates that the size is unbou...
Definition: size.hpp:65
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:67
constexpr bool dynamic
T is a value that is not fixed at compile time.
Definition: dynamic.hpp:30
Definition: trait_backports.hpp:64
constexpr auto make_constant(C c, stdex::extents< IndexType, Extents... > extents)
Make an indexible object in which every element is a constant value.
Definition: make_constant.hpp:39
decltype(auto) constexpr nested_object(Arg &&arg)
Retrieve a nested object of Arg, if it exists.
Definition: nested_object.hpp:35
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