16 #ifndef OPENKALMAN_CONSTANTADAPTER_HPP 17 #define OPENKALMAN_CONSTANTADAPTER_HPP 19 #include <type_traits> 29 template<
indexible PatternMatrix, values::scalar Scalar,
auto...constant>
30 requires (
sizeof...(constant) == 0) or requires { Scalar {constant...}; }
32 template<
typename PatternMatrix,
typename Scalar,
auto...constant>
34 struct ConstantAdapter : internal::library_base_t<ConstantAdapter<PatternMatrix, Scalar, constant...>, PatternMatrix>
39 #ifndef __cpp_concepts 40 static_assert(indexible<PatternMatrix>);
41 static_assert(values::scalar<Scalar>);
42 static_assert(
sizeof...(constant) == 0 or std::is_constructible_v<Scalar, decltype(constant)...>);
49 using DescriptorCollection = std::conditional_t<
50 pattern_tuple<AllDescriptorsType>,
52 std::vector<DynamicDescriptor<MyScalarType>>>;
55 template<
typename D, std::size_t...Ix, std::size_t...IxExtra>
56 static constexpr
auto make_descriptors_tuple(D&& d, std::index_sequence<Ix...>, std::index_sequence<IxExtra...>)
58 if constexpr ((... or dynamic_pattern<std::tuple_element_t<IxExtra, D>>))
59 if ((... or (std::get<IxExtra>(d) != Axis{})));
60 throw std::invalid_argument {
"Too many elements in vector space descriptors_collection_tuple argument of a constant adapter"};
62 return std::tuple {[](D&& d){
63 using E = std::tuple_element_t<Ix, DescriptorCollection>;
65 if constexpr (Ix < std::tuple_size_v<D>)
67 if constexpr (fixed_pattern<E>)
69 if constexpr (dynamic_pattern<std::tuple_element_t<Ix, D>>)
70 if (std::get<Ix>(d) != E{})
throw std::invalid_argument {
71 "Invalid dynamic element in pattern_tuple argument of a constant adapter"};
76 return std::forward<D>(d);
83 }(std::forward<D>(d))...};
87 template<std::
size_t N = 0,
typename Iterator,
typename Sentinel>
88 static constexpr
auto make_descriptors_tuple_from_range(Iterator it,
const Sentinel& end)
90 if constexpr (N >= std::tuple_size_v<DescriptorCollection>)
92 for (; it != end; ++it)
if (*it != Axis{})
throw std::invalid_argument {
93 "Too many elements in vector space descriptors_collection range argument of a constant adapter"};
96 else if constexpr (fixed_pattern<std::tuple_element_t<N, DescriptorCollection>>)
98 using E = std::tuple_element_t<N, DescriptorCollection>;
101 if (not compares_with<E, Axis>)
throw std::invalid_argument {
102 "Too few elements in vector space descriptors_collection range argument of a constant adapter"};
103 return std::tuple_cat(std::forward_as_tuple(E{}),
104 make_descriptors_tuple_from_range<N + 1>(std::move(it), end));
108 if constexpr (dynamic_pattern<decltype(*it)>)
109 if (*it != E{})
throw std::invalid_argument {
110 "Invalid dynamic element in pattern_collection range argument of a constant adapter"};
111 return std::tuple_cat(std::forward_as_tuple(E{}),
112 make_descriptors_tuple_from_range<N + 1>(++it, end));
117 using E = std::tuple_element_t<N, DescriptorCollection>;
118 if (it == end)
throw std::invalid_argument {
119 "Too few elements in vector space descriptors_collection range argument of a constant adapter"};
120 std::tuple_element_t<N, DescriptorCollection> e {*it};
121 return std::tuple_cat(std::forward_as_tuple(std::move(e)),
122 make_descriptors_tuple_from_range<N + 1>(++it, end));
127 template<
typename D, std::size_t...Ix>
128 static constexpr
auto make_descriptors_range_from_tuple(D&& d, std::index_sequence<Ix...>)
130 return DescriptorCollection {{DynamicDescriptor<MyScalarType> {std::get<Ix>(std::forward<D>(d))}...}};
134 template<
typename Descriptors>
135 static constexpr
auto make_descriptors_collection(Descriptors&& descriptors)
137 #ifdef __cpp_lib_ranges 138 namespace ranges = std::ranges;
140 if constexpr (pattern_tuple<DescriptorCollection>)
142 if constexpr (pattern_tuple<Descriptors>)
144 constexpr
auto N = std::tuple_size_v<DescriptorCollection>;
145 constexpr
auto M = std::tuple_size_v<Descriptors>;
146 return make_descriptors_tuple(std::forward<Descriptors>(descriptors),
147 std::make_index_sequence<N> {},
148 std::make_index_sequence<(M > N) ? M - N : 0> {});
152 return make_descriptors_tuple_from_range(ranges::begin(descriptors), ranges::end(descriptors));
155 else if constexpr (pattern_tuple<Descriptors>)
157 return make_descriptors_range_from_tuple(std::forward<Descriptors>(descriptors),
158 std::make_index_sequence<std::tuple_size_v<Descriptors>> {});
162 DescriptorCollection ret;
163 std::copy(ranges::begin(descriptors), ranges::end(descriptors), ranges::begin(ret));
173 #ifdef __cpp_lib_ranges 174 template<values::scalar C, pattern_collection Descriptors> requires
175 std::constructible_from<MyConstant, C&&> and
176 compatible_with_vector_space_descriptor_collection<PatternMatrix, Descriptors>
178 template<
typename C,
typename Descriptors, std::enable_if_t<
179 values::scalar<C> and pattern_collection<Descriptors> and
180 std::is_constructible_v<MyConstant, C&&> and
181 compatible_with_vector_space_descriptor_collection<PatternMatrix, Descriptors>,
int> = 0>
184 : my_constant {std::forward<C>(c)},
185 descriptor_collection {make_descriptors_collection(std::forward<Descriptors>(descriptors))} {}
192 #ifdef __cpp_lib_ranges 193 template<pattern_collection Descriptors> requires
194 values::fixed<MyConstant> and
195 compatible_with_vector_space_descriptor_collection<PatternMatrix, Descriptors>
197 template<
typename Descriptors, std::enable_if_t<
198 pattern_collection<Descriptors> and
199 values::fixed<MyConstant> and
200 compatible_with_vector_space_descriptor_collection<PatternMatrix, Descriptors>,
int> = 0>
203 : descriptor_collection {make_descriptors_collection(std::forward<Descriptors>(descriptors))} {}
217 #ifdef __cpp_concepts 218 template<values::scalar C, vector_space_descriptors_may_match_with<PatternMatrix> Arg> requires
219 std::constructible_from<MyConstant, C&&>
221 template<
typename C,
typename Arg, std::enable_if_t<
222 values::scalar<C> and vector_space_descriptors_may_match_with<Arg, PatternMatrix> and
223 std::is_constructible_v<MyConstant, C&&>,
int> = 0>
226 my_constant {std::forward<C>(c)},
234 #ifdef __cpp_concepts 235 template<vector_space_descriptors_may_match_with<PatternMatrix> Arg> requires
236 (not std::is_base_of_v<ConstantAdapter, Arg>) and
237 values::fixed<MyConstant>
239 template<
typename Arg, std::enable_if_t<
240 vector_space_descriptors_may_match_with<Arg, PatternMatrix> and
241 (not std::is_base_of_v<ConstantAdapter, Arg>) and
242 values::fixed<MyConstant>,
int> = 0>
251 #ifdef __cpp_concepts 252 template<constant_matrix Arg> requires
253 (not std::is_base_of_v<ConstantAdapter, Arg>) and
254 vector_space_descriptors_may_match_with<Arg, PatternMatrix> and
255 std::constructible_from<MyConstant, constant_coefficient<Arg>>
257 template<
typename Arg, std::enable_if_t<constant_matrix<Arg> and
258 (not std::is_base_of_v<ConstantAdapter, Arg>) and
259 vector_space_descriptors_may_match_with<Arg, PatternMatrix> and
260 std::is_constructible_v<MyConstant, constant_coefficient<Arg>>,
int> = 0>
276 #ifdef __cpp_concepts 277 template<values::scalar C, coordinates::pattern...Ds> requires
278 std::constructible_from<MyConstant, C&&> and
281 template<
typename C,
typename...Ds, std::enable_if_t<
282 values::scalar<C> and (coordinates::pattern<Ds> and ...) and
283 std::is_constructible_v<MyConstant, C&&> and
287 : ConstantAdapter(
std::forward<C>(c),
std::tuple {std::forward<Ds>(ds)...}) {}
303 #ifdef __cpp_concepts 304 template<coordinates::pattern...Ds> requires
305 values::fixed<MyConstant> and
308 template<
typename...Ds, std::enable_if_t<
309 (coordinates::pattern<Ds> and ...) and
310 values::fixed<MyConstant> and
314 : ConstantAdapter(
std::tuple {std::forward<Ds>(ds)...}) {}
318 template<std::
size_t N = 0>
319 constexpr
auto make_dynamic_dimensions_tuple()
321 if constexpr (N < index_count_v<PatternMatrix>)
322 return std::tuple_cat(std::forward_as_tuple(std::get<N>(descriptor_collection)), make_dynamic_dimensions_tuple<N + 1>());
324 return std::tuple {};
328 template<std::size_t N = 0,
typename D,
typename...Ds>
329 constexpr
auto make_dynamic_dimensions_tuple(D&& d, Ds&&...ds)
331 if constexpr (dynamic_pattern<std::tuple_element_t<N, DescriptorCollection>>)
332 return std::tuple_cat(std::forward_as_tuple(std::forward<D>(d)),
333 make_dynamic_dimensions_tuple<N + 1>(std::forward<Ds>(ds)...));
335 return std::tuple_cat(std::forward_as_tuple(std::get<N>(descriptor_collection)),
336 make_dynamic_dimensions_tuple<N + 1>(std::forward<D>(d), std::forward<Ds>(ds)...));
355 #ifdef __cpp_concepts 356 template<values::scalar C, dynamic_pattern...Ds> requires
357 pattern_tuple<DescriptorCollection> and
358 (dynamic_index_count_v<PatternMatrix> !=
dynamic_size) and
359 (
sizeof...(Ds) == dynamic_index_count_v<PatternMatrix>) and
360 std::constructible_from<MyConstant, C&&>
362 template<
typename C,
typename...Ds, std::enable_if_t<
363 values::scalar<C> and (dynamic_pattern<Ds> and ...) and
364 pattern_tuple<DescriptorCollection> and
365 (dynamic_index_count_v<PatternMatrix> !=
dynamic_size) and
366 (
sizeof...(Ds) == dynamic_index_count_v<PatternMatrix>) and
367 std::is_constructible_v<MyConstant, C&&>,
int> = 0>
370 : ConstantAdapter(
std::forward<C>(c), make_dynamic_dimensions_tuple(
std::forward<Ds>(ds)...)) {}
384 #ifdef __cpp_concepts 385 template<dynamic_pattern...Ds> requires
386 pattern_tuple<DescriptorCollection> and
387 (dynamic_index_count_v<PatternMatrix> !=
dynamic_size) and
388 (
sizeof...(Ds) == dynamic_index_count_v<PatternMatrix>) and
389 values::fixed<MyConstant>
391 template<
typename...Ds, std::enable_if_t<
392 values::scalar<C> and (dynamic_pattern<Ds> and ...) and
393 pattern_tuple<DescriptorCollection> and
394 (dynamic_index_count_v<PatternMatrix> !=
dynamic_size) and
395 (
sizeof...(Ds) == dynamic_index_count_v<PatternMatrix>) and
396 values::fixed<MyConstant>,
int> = 0>
399 : ConstantAdapter(make_dynamic_dimensions_tuple(
std::forward<Ds>(ds)...)) {}
405 #ifdef __cpp_concepts 406 template<constant_matrix Arg> requires
407 (not std::derived_from<Arg, ConstantAdapter>) and
408 vector_space_descriptors_may_match_with<Arg, PatternMatrix> and
409 std::assignable_from<MyConstant, constant_coefficient<Arg>>
411 template<
typename Arg, std::enable_if_t<constant_matrix<Arg> and
412 (not std::is_base_of_v<ConstantAdapter, Arg>) and
413 vector_space_descriptors_may_match_with<Arg, PatternMatrix> and
414 std::is_assignable_v<MyConstant, constant_coefficient<Arg>>,
int> = 0>
418 if constexpr (not vector_space_descriptors_match_with<Arg, PatternMatrix>)
420 "Argument to ConstantAdapter assignment operator has non-matching vector space descriptors."};
429 #ifdef __cpp_concepts 430 template<indexible Arg>
432 template<
typename Arg, std::enable_if_t<indexible<Arg>,
int> = 0>
436 if constexpr (not vector_space_descriptors_may_match_with<Arg, PatternMatrix>)
438 else if constexpr (constant_matrix<Arg>)
442 auto c = to_native_matrix<PatternMatrix>(*this);
444 "interface::library_interface<PatternMatrix>::to_native_matrix(*this) must define an object within the library of Arg");
445 return std::move(c) == arg;
450 #ifndef __cpp_impl_three_way_comparison 454 #ifdef __cpp_concepts 455 template<indexible Arg> (not constant_adapter<Arg>)
457 template<
typename Arg, std::enable_if_t<indexible<Arg> and not constant_adapter<Arg>,
int> = 0>
461 if constexpr (not vector_space_descriptors_may_match_with<Arg, PatternMatrix>)
463 else if constexpr (constant_matrix<Arg>)
467 auto new_c = to_native_matrix<Arg>(c);
469 "interface::library_interface<Arg>::to_native_matrix(c) must define an object within the library of Arg");
470 return arg == std::move(new_c);
475 #ifdef __cpp_concepts 476 template<indexible Arg>
478 template<
typename Arg, std::enable_if_t<indexible<Arg>,
int> = 0>
480 constexpr
bool operator!=(
const Arg& arg)
const {
return not (*
this == arg); }
483 #ifdef __cpp_concepts 484 template<indexible Arg> (not std::same_as<Arg, ConstantAdapter>)
486 template<
typename Arg, std::enable_if_t<indexible<Arg> and not std::is_same_v<Arg, ConstantAdapter>,
int> = 0>
488 friend constexpr
bool operator!=(
const Arg& arg,
const ConstantAdapter& c) {
return not (arg == c); }
496 #ifdef __cpp_lib_ranges 497 template<index_range_for<PatternMatrix> Indices> requires (not empty_object<PatternMatrix>)
498 constexpr values::scalar
auto 500 template<
typename Indices, std::enable_if_t<
501 index_range_for<Indices, PatternMatrix> and (not empty_object<PatternMatrix>),
int> = 0>
513 #ifdef __cpp_concepts 514 constexpr values::scalar
auto 526 if constexpr (zero<ConstantAdapter>)
return arg;
535 #ifdef __cpp_concepts 536 friend auto operator*(
const ConstantAdapter& arg, values::scalar
auto s)
538 template<
typename S, std::enable_if_t<values::scalar<S>,
int> = 0>
542 if constexpr (
zero<decltype(arg)>)
return arg;
550 #ifdef __cpp_concepts 551 friend auto operator*(values::scalar
auto s,
const ConstantAdapter& arg)
553 template<
typename S, std::enable_if_t<values::scalar<S>,
int> = 0>
557 if constexpr (
zero<decltype(arg)>)
return arg;
565 #ifdef __cpp_concepts 566 friend auto operator/(
const ConstantAdapter& arg, values::scalar
auto s)
568 template<
typename S, std::enable_if_t<values::scalar<S>,
int> = 0>
577 MyConstant my_constant;
579 DescriptorCollection descriptor_collection;
591 #ifdef __cpp_concepts 592 template<values::scalar C, indexible Arg>
594 template<
typename C,
typename Arg, std::enable_if_t<values::scalar<C> and indexible<Arg>,
int> = 0>
599 #ifdef __cpp_concepts 600 template<constant_matrix Arg> requires (not constant_adapter<Arg>)
602 template<
typename Arg, std::enable_if_t<constant_matrix<Arg> and (not constant_adapter<Arg>),
int> = 0>
613 template<
typename PatternMatrix,
typename Scalar,
auto...constant>
618 using XprType = ConstantAdapter<PatternMatrix, Scalar, constant...>;
622 using scalar_type =
typename XprType::MyScalarType;
623 using MyDims =
typename XprType::MyDimensions_t;
626 template<
typename Arg>
629 if constexpr (index_count_v<PatternMatrix> ==
dynamic_size)
630 return std::forward<Arg>(arg).descriptor_collection.size();
632 return std::tuple_size<MyDims>{};
636 template<
typename Arg,
typename N>
639 if constexpr (index_count_v<PatternMatrix> ==
dynamic_size)
641 return std::forward<Arg>(arg).descriptor_collection[static_cast<typename MyDims::size_type>(n)];
643 else if constexpr (values::fixed<N>)
645 if constexpr (
N::value >= index_count_v<PatternMatrix>)
return Dimensions<1>{};
646 else return std::get<N::value>(std::forward<Arg>(arg).descriptor_collection);
648 else if (n >= std::tuple_size_v<MyDims>)
655 [](
auto&&...ds){
return std::array<std::size_t, std::tuple_size_v<MyDims>> {std::forward<decltype(ds)>(ds)...}; },
656 std::forward<Arg>(arg).descriptor_collection)[n];
664 template<
typename Arg>
665 static constexpr
auto get_constant(
const Arg& arg) {
return arg.get_scalar_constant(); }
671 template<Applicability b>
672 static constexpr
bool one_dimensional = OpenKalman::one_dimensional<PatternMatrix, b>;
675 template<Applicability b>
676 static constexpr
bool is_square = OpenKalman::square_shaped<PatternMatrix, b>;
682 static constexpr
bool is_writable =
false;
690 template<
typename PatternMatrix,
typename Scalar,
auto...constant>
693 template<
typename Derived>
694 using LibraryBase = internal::library_base_t<Derived, PatternMatrix>;
697 template<
typename Arg,
typename Indices>
698 static constexpr
auto 705 template<
typename Arg>
706 static decltype(
auto)
709 return OpenKalman::to_native_matrix<PatternMatrix>(std::forward<Arg>(arg));
713 template<Layout layout,
typename S,
typename D>
717 return make_dense_object<PatternMatrix, layout, S>(std::forward<D>(d));
724 template<
typename C,
typename D>
725 static constexpr
auto 728 return OpenKalman::make_constant<PatternMatrix>(std::forward<C>(c), std::forward<D>(d));
732 template<
typename S,
typename D>
733 static constexpr
auto 734 make_identity_matrix(D&& d)
736 return make_identity_matrix_like<PatternMatrix, S>(std::forward<D>(d));
747 template<
typename...Ds,
typename Arg>
748 static decltype(
auto)
749 replicate(
const std::tuple<Ds...>& tup, Arg&& arg)
755 template<
typename...Ds,
typename Op,
typename...Args>
756 static constexpr decltype(
auto)
757 n_ary_operation(
const std::tuple<Ds...>& d_tup, Op&& op, Args&&...args)
763 template<std::size_t...indices,
typename BinaryFunction,
typename Arg>
764 static constexpr decltype(
auto)
765 reduce(BinaryFunction&& b, Arg&& arg)
781 template<
typename A,
typename B>
782 static constexpr
auto sum(
A&& a, B&& b)
788 template<
typename A,
typename B>
789 static constexpr
auto contract(
A&& a, B&& b)
800 template<HermitianAdapterType significant_triangle,
typename A,
typename U,
typename Alpha>
804 return Trait::template rank_update_hermitian<significant_triangle>(std::forward<A>(a), std::forward<U>(u), alpha);
824 #endif //OPENKALMAN_CONSTANTADAPTER_HPP constexpr auto count_indices(const T &t)
Get the number of indices available to address the components of an indexible object.
Definition: count_indices.hpp:33
constexpr auto n_ary_operation(const std::tuple< Ds... > &d_tup, Operation &&operation, Args &&...args)
Perform a component-wise n-ary operation, using broadcasting to match the size of a pattern matrix...
Definition: n_ary_operation.hpp:319
constexpr bool one_dimensional
Specifies that a type is one-dimensional in every index.
Definition: one_dimensional.hpp:83
decltype(auto) constexpr contract(A &&a, B &&b)
Matrix multiplication of A * B.
Definition: contract.hpp:54
Definition: indexible_object_traits.hpp:36
decltype(auto) rank_update_hermitian(A &&a, U &&u, scalar_type_of_t< A > alpha=1)
Do a rank update on a hermitian matrix.
Definition: rank_update_hermitian.hpp:45
An operation involving some number of values.
Definition: operation.hpp:69
constexpr auto & operator=(const Arg &arg)
Assign from a compatible constant_matrix.
Definition: ConstantAdapter.hpp:416
constexpr ConstantAdapter(Descriptors &&descriptors)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: ConstantAdapter.hpp:202
constexpr bool indexible
T is a generalized tensor type.
Definition: indexible.hpp:32
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 auto operator[](const Indices &indices) const
Access a component at a set of indices.
Definition: ConstantAdapter.hpp:504
constexpr bool value
T is numerical value or is reducible to a numerical value.
Definition: value.hpp:31
decltype(auto) constexpr reduce(BinaryFunction &&b, Arg &&arg)
Perform a partial reduction based on an associative binary function, across one or more indices...
Definition: reduce.hpp:143
constexpr auto to_number(Arg arg)
Convert any values::value to a values::number.
Definition: to_number.hpp:34
The constant associated with T, assuming T is a constant_matrix.
Definition: constant_coefficient.hpp:36
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
constexpr detail::replicate_adaptor replicate
a std::ranges::range_adaptor_closure associated with replicate_view.
Definition: replicate.hpp:430
The root namespace for OpenKalman.
Definition: basics.hpp:34
An interface to various routines from the linear algebra library associated with indexible object T...
Definition: library_interface.hpp:37
constexpr bool zero
Specifies that a type is known at compile time to be a constant matrix of value zero.
Definition: zero.hpp:43
constexpr ConstantAdapter(C &&c, Ds &&...ds)
Construct using a full set of coordinates::pattern objects.
Definition: ConstantAdapter.hpp:286
constexpr bool vector_space_descriptors_match(const Ts &...ts)
Return true if every set of coordinates::pattern of a set of objects match.
Definition: vector_space_descriptors_match.hpp:62
constexpr ConstantAdapter(C &&c, Descriptors &&descriptors)
Construct from values::scalar and a pattern_collection.
Definition: ConstantAdapter.hpp:183
constexpr ConstantAdapter(Ds &&...ds)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: ConstantAdapter.hpp:313
constexpr ConstantAdapter(const Arg &arg)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: ConstantAdapter.hpp:244
decltype(auto) constexpr sum(Ts &&...ts)
Element-by-element sum of one or more objects.
Definition: sum.hpp:112
A tensor or other matrix in which all elements are a constant scalar value.
Definition: ConstantAdapter.hpp:34
std::decay_t< decltype(values::to_number(std::declval< T >()))> number_type_of_t
Obtain the values::number type associated with avalues::value.
Definition: number_type_of_t.hpp:34
constexpr auto make_constant(C &&c, Descriptors &&descriptors)
Make a constant object based on a particular library object.
Definition: make_constant.hpp:37
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
constexpr bool compatible_with_vector_space_descriptor_collection
indexible T is compatible with pattern_collection D.
Definition: compatible_with_vector_space_descriptor_collection.hpp:74
constexpr ConstantAdapter(C &&c, const Arg &arg)
Construct based on a values::scalar and the shape of an indexible reference object.
Definition: ConstantAdapter.hpp:225
constexpr std::size_t dynamic_size
A constant indicating that a size or index is dynamic.
Definition: global-definitions.hpp:33
constexpr bool operator==(const Arg &arg) const
Comparison operator.
Definition: ConstantAdapter.hpp:434
A matrix with typed rows and columns.
Definition: forward-class-declarations.hpp:448
constexpr auto get_vector_space_descriptor(const T &t, const N &n)
Get the coordinates::pattern object for index N of indexible object T.
Definition: get_vector_space_descriptor.hpp:56
constexpr auto get_scalar_constant() const
Get the values::scalar associated with this object.
Definition: ConstantAdapter.hpp:518