Sequoia
Loading...
Searching...
No Matches
Spaces.hpp
Go to the documentation of this file.
1
2// Copyright Oliver J. Rosten 2024. //
3// Distributed under the GNU GENERAL PUBLIC LICENSE, Version 3.0. //
4// (See accompanying file LICENSE.md or copy at //
5// https://www.gnu.org/licenses/gpl-3.0.en.html) //
7
8#pragma once
9
157#include "sequoia/PlatformSpecific/Preprocessor.hpp"
158
159#include <algorithm>
160#include <cmath>
161#include <concepts>
162#include <complex>
163#include <format>
164#include <ranges>
165#include <span>
166
167namespace sequoia::maths
168{
200 template<class T>
201 inline constexpr bool is_addable_v{
202 requires(T& t) {
203 { t += t } -> std::same_as<T&>;
204 { t + t } -> std::convertible_to<T>;
205 }
206 };
207
211 template<class T>
212 inline constexpr bool is_subtractable_v{
213 requires(T& t) {
214 { t -= t } -> std::same_as<T&>;
215 { t - t } -> std::convertible_to<T>;
216 }
217 };
218
222 template<class T>
223 inline constexpr bool is_multiplicable_v{
224 requires(T& t) {
225 { t *= t } -> std::same_as<T&>;
226 { t * t } -> std::convertible_to<T>;
227 }
228 };
229
233 template<class T>
234 inline constexpr bool is_divisible_v{
235 requires(T& t) {
236 { t /= t } -> std::same_as<T&>;
237 { t / t } -> std::convertible_to<T>;
238 }
239 };
240
261 template<class T>
262 struct weakly_abelian_group_under_addition : std::false_type {};
263
264 template<class T>
265 using weakly_abelian_group_under_addition_t = typename weakly_abelian_group_under_addition<T>::type;
266
267 template<class T>
268 inline constexpr bool weakly_abelian_group_under_addition_v{weakly_abelian_group_under_addition<T>::value};
269
270 template<arithmetic T>
271 struct weakly_abelian_group_under_addition<T> : std::true_type {};
272
273 template<std::floating_point T>
274 struct weakly_abelian_group_under_addition<std::complex<T>> : std::true_type {};
275
286 template<class T>
287 struct weakly_abelian_group_under_multiplication : std::false_type {};
288
289 template<class T>
290 using weakly_abelian_group_under_multiplication_t = typename weakly_abelian_group_under_multiplication<T>::type;
291
292 template<class T>
293 inline constexpr bool weakly_abelian_group_under_multiplication_v{weakly_abelian_group_under_multiplication<T>::value};
294
295 template<std::floating_point T>
296 struct weakly_abelian_group_under_multiplication<T> : std::true_type {};
297
298 template<std::floating_point T>
299 struct weakly_abelian_group_under_multiplication<std::complex<T>> : std::true_type {};
300
301 template<>
302 struct weakly_abelian_group_under_multiplication<bool> : std::true_type {};
303
308 template<class T>
310
311 template<class T>
312 using multiplication_weakly_distributive_over_addition_t = typename multiplication_weakly_distributive_over_addition<T>::type;
313
314 template<class T>
315 inline constexpr bool multiplication_weakly_distributive_over_addition_v{multiplication_weakly_distributive_over_addition<T>::value};
316
321 template<class T>
323 = std::regular<T>
324 && weakly_abelian_group_under_addition_v<T>
325 && multiplication_weakly_distributive_over_addition_v<T>
326 && is_addable_v<T>
327 && is_subtractable_v<T>
328 && is_multiplicable_v<T>;
329
334 template<class T>
335 concept weak_field = weak_commutative_ring<T> && weakly_abelian_group_under_multiplication_v<T> && is_divisible_v<T>;
336
344 template<class T>
345 inline constexpr bool has_commutative_ring_type_v{
346 requires {
347 typename T::commutative_ring_type;
349 }
350 };
351
355 template<class T>
356 inline constexpr bool has_field_type_v{
357 requires {
358 typename T::field_type;
360 }
361 };
362
369 template<class T>
370 inline constexpr bool defines_commutative_ring_v{has_commutative_ring_type_v<T> || has_field_type_v<T>};
371
379 template<class T>
380 inline constexpr bool defines_field_v{
381 has_field_type_v<T>
382 || requires {
383 typename T::commutative_ring_type;
385 }
386 };
387
391 template<class T>
392 inline constexpr bool has_dimension_v{
393 requires { { T::dimension } -> std::convertible_to<std::size_t>; }
394 };
395
399 template<class T>
400 inline constexpr bool has_set_type_v{
401 requires { typename T::set_type; }
402 };
403
424 template<class T>
425 inline constexpr bool identifies_as_convex_space_v{
426 requires {
427 typename T::is_convex_space;
428 requires std::convertible_to<typename T::is_convex_space, std::true_type>;
429 }
430 };
431
435 template<class T>
436 inline constexpr bool identifies_as_affine_space_v{
437 requires {
438 typename T::is_affine_space;
439 requires std::convertible_to<typename T::is_affine_space, std::true_type>;
440 }
441 };
442
446 template<class T>
447 inline constexpr bool identifies_as_free_module_v{
448 requires {
449 typename T::is_free_module;
450 requires std::convertible_to<typename T::is_free_module, std::true_type>;
451 }
452 };
453
457 template<class T>
458 inline constexpr bool identifies_as_vector_space_v{
459 requires {
460 typename T::is_vector_space;
461 requires std::convertible_to<typename T::is_vector_space, std::true_type>;
462 }
463 };
464
476 template<class T>
477 concept free_module = has_set_type_v<T> && has_dimension_v<T> && defines_commutative_ring_v<T> && (identifies_as_free_module_v<T> || identifies_as_vector_space_v<T>);
478
482 template<class T>
483 concept vector_space = free_module<T> && defines_field_v<T>;
484
489 template<class T>
490 inline constexpr bool has_vector_space_type_v{
491 requires {
492 typename T::vector_space_type;
494 }
495 };
496
501 template<class T>
502 inline constexpr bool has_free_module_type_v{
503 requires {
504 typename T::free_module_type;
506 }
507 };
508
516 template<class T>
519 || ( has_set_type_v<T>
520 && (has_vector_space_type_v<T> || has_free_module_type_v<T>)
521 && (identifies_as_convex_space_v<T> || identifies_as_affine_space_v<T>));
522
529 template<class T>
530 concept affine_space = vector_space<T> || (convex_space<T> && identifies_as_affine_space_v<T>);
531
535 template<class T>
536 struct is_free_module : std::integral_constant<bool, free_module<T>> {};
537
538
544 template<class>
546
547 template<convex_space ConvexSpace>
548 requires identifies_as_free_module_v<ConvexSpace> || identifies_as_vector_space_v<ConvexSpace>
549 struct free_module_type_of<ConvexSpace>
550 {
551 using type = ConvexSpace;
552 };
553
554 template<convex_space ConvexSpace>
555 requires (!identifies_as_free_module_v<ConvexSpace> && !identifies_as_vector_space_v<ConvexSpace>) && has_free_module_type_v<ConvexSpace>
557 {
558 using type = ConvexSpace::free_module_type;
559 };
560
561 template<convex_space ConvexSpace>
562 requires (!identifies_as_free_module_v<ConvexSpace> && !identifies_as_vector_space_v<ConvexSpace>) && has_vector_space_type_v<ConvexSpace>
563 struct free_module_type_of<ConvexSpace>
564 {
565 using type = ConvexSpace::vector_space_type;
566 };
567
568 template<class T>
569 using free_module_type_of_t = free_module_type_of<T>::type;
570
576 template<convex_space ConvexSpace>
578 {
579 using type = free_module_type_of_t<ConvexSpace>::commutative_ring_type;
580 };
581
582 template<convex_space ConvexSpace>
583 requires vector_space<free_module_type_of_t<ConvexSpace>> && has_field_type_v<free_module_type_of_t<ConvexSpace>>
584 struct commutative_ring_type_of<ConvexSpace>
585 {
586 using type = free_module_type_of_t<ConvexSpace>::field_type;
587 };
588
589 template<convex_space ConvexSpace>
590 using commutative_ring_type_of_t = commutative_ring_type_of<ConvexSpace>::type;
591
592 template<convex_space ConvexSpace>
593 using space_value_type = commutative_ring_type_of_t<ConvexSpace>;
594
599 template<convex_space ConvexSpace>
600 inline constexpr std::size_t dimension_of{free_module_type_of_t<ConvexSpace>::dimension};
601
602
603 template<free_module V>
604 inline constexpr bool has_admits_canonical_basis_v{
605 requires{
606 typename V::admits_canonical_basis;
607 }
608 };
609
610 template<free_module M>
611 struct admits_canonical_basis : std::false_type {};
612
613 template<free_module M>
614 requires has_admits_canonical_basis_v<M> && std::convertible_to<typename M::admits_canonical_basis, std::true_type>
615 struct admits_canonical_basis<M> : std::true_type {};
616
617 template<free_module M>
618 using admits_canonical_basis_t = admits_canonical_basis<M>::type;
619
620 template<free_module M>
621 inline constexpr bool admits_canonical_basis_v{admits_canonical_basis<M>::value};
622
630 template<class T>
631 inline constexpr bool identifies_as_basis_v{
632 requires {
633 typename T::is_basis;
634 requires std::convertible_to<typename T::is_basis, std::true_type>;
635 }
636 };
637
643 template<class B>
644 concept basis = identifies_as_basis_v<B> && (has_free_module_type_v<B> || has_vector_space_type_v<B>);
645
646 template<basis B>
647 requires has_free_module_type_v<B>
649 {
650 using type = B::free_module_type;
651 };
652
653 template<basis B>
654 requires has_vector_space_type_v<B>
655 struct free_module_type_of<B>
656 {
657 using type = B::vector_space_type;
658 };
659
660 template<class T>
661 inline constexpr bool has_isomorphism_type_v{
662 requires { typename T::isomorphism_type; }
663 };
664
666
667 template<basis B>
669
670 template<basis B>
671 requires admits_canonical_basis_v<free_module_type_of_t<B>>
673 {
675 };
676
677 template<basis B>
678 using basis_isomorphism_type_of_t = basis_isomorphism_type_of<B>::type;
679
680 template<basis B>
681 requires (!admits_canonical_basis_v<free_module_type_of_t<B>>) && has_isomorphism_type_v<B>
683 {
684 using type = B::isomorphism_type;
685 };
686
690 template<class B, class M>
691 concept basis_for
692 = basis<B>
693 && (admits_canonical_basis_v<free_module_type_of_t<B>> || has_isomorphism_type_v<B>)
694 && requires { requires std::is_same_v<free_module_type_of_t<B>, M>; };
695
724 template<class V, class ConvexSpace>
725 inline constexpr bool validator_for_single_value{
726 (dimension_of<ConvexSpace> == 1)
727 && requires(V& v, const space_value_type<ConvexSpace>& val) { { v(val) } -> std::convertible_to<decltype(val)>; }
728 };
729
738 template<class V, class ConvexSpace>
739 inline constexpr bool validator_for_array{
740 requires (V& v, const std::array<space_value_type<ConvexSpace>, dimension_of<ConvexSpace>>& values) {
741 { v(values) } -> std::convertible_to<decltype(values)>;
742 }
743 };
744
748 template<class V, class ConvexSpace>
751 && std::default_initializable<V>
752 && std::constructible_from<V, V>
753 && (validator_for_single_value<V, ConvexSpace> || validator_for_array<V, ConvexSpace>);
754
758 template<class T>
759 struct defines_identity_validator : std::false_type {};
760
761 template<class T>
762 using defines_identity_validator_t = defines_identity_validator<T>::type;
763
764 template<class T>
765 inline constexpr bool defines_identity_validator_v{defines_identity_validator<T>::value};
766
767 template<>
768 struct defines_identity_validator<std::identity> : std::true_type {};
769
776 {
777 template<arithmetic T>
778 constexpr T operator()(const T val) const
779 {
780 if(val < T{}) throw std::domain_error{std::format("Domain error: attempting to use a value of {} for a semi-positive quantity", val)};
781
782 return val;
783 }
784
785 template<arithmetic T>
786 requires std::is_unsigned_v<T>
787 [[nodiscard]]
788 constexpr T operator()(const T val) const
789 {
790 return val;
791 }
792 };
793
797 template<std::floating_point T, T Lower, T Upper=std::numeric_limits<T>::infinity()>
798 requires (Upper > Lower)
800 {
801 constexpr static T lower{Lower}, upper{Upper};
802
803 template<std::floating_point U>
804 requires (sizeof(U) <= sizeof(T))
805 constexpr U operator()(const U val) const
806 {
807 if constexpr(Lower > -std::numeric_limits<T>::infinity())
808 {
809 if(const auto ulower{static_cast<U>(Lower)}; val < ulower)
810 throw std::domain_error{std::format("interval_validator: invoked with {}, but values should be >= {} ", val, ulower)};
811 }
812
813 if constexpr(Upper < std::numeric_limits<T>::infinity())
814 {
815 if(const auto uUpper{static_cast<U>(Upper)}; val > uUpper)
816 throw std::domain_error{std::format("interval_validator: invoked with {}, but values should be <= {} ", val, uUpper)};
817 }
818
819 return val;
820 }
821
822 template<std::floating_point U, std::size_t D>
823 requires (sizeof(U) <= sizeof(T))
824 constexpr const std::array<U, D>& operator()(const std::array<U, D>& vals) const
825 {
826 for(const auto v : vals)
827 (*this)(v);
828
829 return vals;
830 }
831 };
832
833 template<class T>
834 struct is_interval_validator : std::false_type {};
835
836 template<class T>
837 using is_interval_validator_t = is_interval_validator<T>::type;
838
839 template<class T>
840 inline constexpr bool is_interval_validator_v{is_interval_validator<T>::value};
841
842 template<std::floating_point T, T Lower, T Upper>
843 struct is_interval_validator<interval_validator<T, Lower, Upper>> : std::true_type {};
844
848 template<class T>
849 struct defines_half_line_validator : std::false_type {};
850
851 template<class T>
852 using defines_half_line_validator_t = typename defines_half_line_validator<T>::type;
853
854 template<class T>
855 inline constexpr bool defines_half_line_validator_v{defines_half_line_validator<T>::value};
856
857 template<>
859
860 template<std::floating_point T, T Lower, T Upper>
862 : std::bool_constant<(Lower == T{}) && (Upper == std::numeric_limits<T>::infinity())>
863 {};
864
865 template<std::floating_point T, T Lower, T Upper>
867 : std::bool_constant<(Lower == -std::numeric_limits<T>::infinity()) && (Upper == std::numeric_limits<T>::infinity())>
868 {};
869
894 template<class... Ts>
896 {
897 };
898
899 template<weak_commutative_ring... Rs>
900 inline constexpr bool has_common_ring_v{
901 ((weak_field<Rs> && ...) || (!weak_field<Rs> && ...)) && requires { typename std::common_type<Rs...>::type; }
902 };
903
904 template<free_module... Ts>
905 requires (sizeof...(Ts) >= 1) && has_common_ring_v<commutative_ring_type_of_t<Ts>...>
906 struct direct_product<Ts...>
907 {
908 using set_type = direct_product<typename Ts::set_type...>;
909 using commutative_ring_type = std::common_type_t<commutative_ring_type_of_t<Ts>...>;
910 using is_free_module = std::true_type;
911 constexpr static std::size_t dimension{(Ts::dimension + ...)};
912 };
913
914 template<affine_space... Ts>
915 requires (sizeof...(Ts) >= 1) && (!free_module<Ts> && ...)
916 struct direct_product<Ts...>
917 {
918 using set_type = direct_product<typename Ts::set_type...>;
919 using free_module_type = direct_product<free_module_type_of_t<Ts>...>;
920 using is_affine_space = std::true_type;
921 };
922
923 template<convex_space... Ts>
924 requires (sizeof...(Ts) >= 1)
925 && ((!affine_space<Ts> && ...) || ((free_module<Ts> || ...) && (!free_module<Ts> || ...)))
926 struct direct_product<Ts...>
927 {
928 using set_type = direct_product<typename Ts::set_type...>;
929 using free_module_type = direct_product<free_module_type_of_t<Ts>...>;
930 using is_convex_space = std::true_type;
931 };
932
933 template<class T>
934 struct is_direct_product : std::false_type {};
935
936 template<class... Ts>
937 struct is_direct_product<direct_product<Ts...>> : std::true_type {};
938
939 template<class T>
940 using is_direct_product_t = is_direct_product<T>::type;
941
942 template<class T>
943 inline constexpr bool is_direct_product_v = is_direct_product<T>::value;
944
945 template<class T>
947
948 template<class T>
949 inline constexpr std::size_t direct_product_cardinality_v{direct_product_cardinality<T>::value};
950
951 template<class... Ts>
953 {
954 constexpr static auto value{sizeof...(Ts)};
955 };
956
1010 namespace sets
1011 {
1019 template<convex_space From, class To>
1021 {
1022 };
1023
1031 template<vector_space From, class To>
1033 {
1034 };
1035 }
1036
1040 template<class>
1041 struct dual;
1042
1046 template<convex_space C>
1047 requires (!affine_space<C>)
1048 struct dual<C>
1049 {
1052 using is_convex_space = std::true_type;
1053 };
1054
1058 template<affine_space A>
1059 requires (!vector_space<A>)
1060 struct dual<A>
1061 {
1064 using is_affine_space = std::true_type;
1065 };
1066
1070 template<vector_space V>
1071 struct dual<V>
1072 {
1073 using field_type = commutative_ring_type_of_t<V>;
1075 using is_vector_space = std::true_type;
1076 constexpr static auto dimension{V::dimension};
1077 };
1078
1082 template<class T>
1083 struct is_dual : std::false_type {};
1084
1085 template<class T>
1086 struct is_dual<dual<T>> : std::true_type {};
1087
1088 template<class T>
1089 using is_dual_t = is_dual<T>::type;
1090
1091 template<class T>
1092 inline constexpr bool is_dual_v{is_dual<T>::value};
1093
1102 template<class>
1103 struct dual_of;
1104
1105 template<class T>
1106 using dual_of_t = dual_of<T>::type;
1107
1108 template<class T>
1109 struct dual_of {
1110 using type = dual<T>;
1111 };
1112
1113 template<class T>
1114 requires (!convex_space<T>) || (convex_space<T> && weak_field<commutative_ring_type_of_t<T>>)
1115 struct dual_of<dual<T>> {
1116 using type = T;
1117 };
1118
1123 template<convex_space C>
1124 struct is_non_negative_orthant : std::false_type
1125 {};
1126
1127 template<convex_space C>
1128 using is_non_negative_orthant_t = is_non_negative_orthant<C>::type;
1129
1130 template<convex_space C>
1131 inline constexpr bool is_non_negative_orthant_v{is_non_negative_orthant<C>::value};
1132
1133 template<convex_space Space>
1134 inline constexpr bool has_non_negative_orthant_type_v{
1135 requires {
1136 typename Space::non_negative_orthant;
1137 }
1138 };
1139
1140 template<convex_space C>
1141 requires has_non_negative_orthant_type_v<C> && std::convertible_to<typename C::non_negative_orthant, std::true_type>
1142 struct is_non_negative_orthant<C> : std::true_type
1143 {
1144 static_assert(!affine_space<C>);
1145 };
1146
1147 template<convex_space C>
1149 {
1150 };
1151
1152
1153 template<convex_space Space>
1154 inline constexpr bool has_distinguished_origin_type_v{
1155 requires {
1156 typename Space::distinguished_origin;
1157 }
1158 };
1159
1160 template<convex_space Space>
1161 struct has_distinguished_origin : std::false_type
1162 {};
1163
1164 template<convex_space Space>
1165 using has_distinguished_origin_t = has_distinguished_origin<Space>::type;
1166
1167 template<convex_space Space>
1168 inline constexpr bool has_distinguished_origin_v{has_distinguished_origin<Space>::value};
1169
1170 template<convex_space Space>
1171 requires has_distinguished_origin_type_v<Space> && std::convertible_to<typename Space::distinguished_origin, std::true_type>
1172 struct has_distinguished_origin<Space> : std::true_type
1173 {
1174 };
1175
1176 template<convex_space Space>
1177 requires (!has_distinguished_origin_type_v<Space>) && is_non_negative_orthant_v<Space>
1178 struct has_distinguished_origin<Space> : std::true_type
1179 {
1180 };
1181
1182 template<free_module Space>
1183 struct has_distinguished_origin<Space> : std::true_type
1184 {};
1185
1186 template<affine_space Space>
1187 requires (!free_module<Space>)
1188 struct has_distinguished_origin<Space> : std::false_type
1189 {};
1190
1191 template<convex_space Space>
1193 {
1194 };
1195
1234 template<
1235 convex_space ConvexSpace,
1237 class... Ts
1238 >
1240
1247 template<affine_space AffineSpace, basis_for<free_module_type_of_t<AffineSpace>> Basis, class Origin>
1249
1253 template<vector_space VectorSpace, basis_for<free_module_type_of_t<VectorSpace>> Basis>
1255
1259 template<free_module FreeModule, basis_for<free_module_type_of_t<FreeModule>> Basis>
1261
1287 namespace impl
1288 {
1289 template<basis B, class Rep, class...>
1290 struct is_units_terminated_pack : std::false_type {};
1291
1292 template<basis B, class Rep, class... Args, std::size_t... Is>
1293 requires (sizeof...(Args) == sizeof...(Is) + 1)
1294 && std::same_as<std::tuple_element_t<sizeof...(Is), std::tuple<Args...>>, basis_isomorphism_type_of_t<B>>
1295 && (std::same_as<std::tuple_element_t<Is, std::tuple<Args...>>, Rep> && ...)
1296 struct is_units_terminated_pack<B, Rep, std::tuple<Args...>, std::index_sequence<Is...>> : std::true_type
1297 {
1298 };
1299 }
1300
1301 template<basis B, class Rep, class... Args>
1302 struct is_units_terminated_pack : std::false_type
1303 {};
1304
1305 template<basis B, class Rep, class... Args>
1306 requires (sizeof...(Args) > 1)
1307 struct is_units_terminated_pack<B, Rep, Args...>
1308 : impl::is_units_terminated_pack<B, Rep, std::tuple<Args...>, std::make_index_sequence<sizeof...(Args) - 1>>
1309 {};
1310
1311 template<basis B, class Rep, class... Args>
1312 inline constexpr bool is_units_terminated_pack_v{is_units_terminated_pack<B, Rep, Args...>::value};
1313
1314 template<
1315 convex_space ConvexSpace,
1316 basis_for<free_module_type_of_t<ConvexSpace>> Basis,
1317 validator_for<ConvexSpace> Validator,
1318 class DisplacementCoordinates=free_module_coordinates<free_module_type_of_t<ConvexSpace>, Basis>
1319 >
1321 {
1322 public:
1323 using space_type = ConvexSpace;
1324 using basis_type = Basis;
1325 using validator_type = Validator;
1326 using set_type = ConvexSpace::set_type;
1327 using free_module_type = free_module_type_of_t<ConvexSpace>;
1328 using commutative_ring_type = commutative_ring_type_of_t<ConvexSpace>;
1329 using value_type = commutative_ring_type;
1330 using displacement_coordinates_type = DisplacementCoordinates;
1331 using basis_isomorphism_type = basis_isomorphism_type_of_t<Basis>;
1332
1333 // TO DO: improve conventions
1334 constexpr static bool has_distinguished_origin{has_distinguished_origin_v<ConvexSpace>};
1335 constexpr static bool has_identity_validator{defines_identity_validator_v<Validator>};
1336 constexpr static bool has_freely_mutable_components{has_identity_validator && has_distinguished_origin};
1337 constexpr static bool admits_canonical_basis{admits_canonical_basis_v<free_module_type>};
1338
1339 constexpr static std::size_t dimension{free_module_type::dimension};
1340 constexpr static std::size_t D{dimension};
1341
1342 constexpr coordinates_base() noexcept = default;
1343
1344 constexpr explicit coordinates_base(std::span<const value_type, D> vals) noexcept(has_identity_validator)
1345 requires admits_canonical_basis
1346 : coordinates_base{vals, basis_isomorphism_type{}}
1347 {}
1348
1349 constexpr coordinates_base(std::span<const value_type, D> vals, basis_isomorphism_type) noexcept(has_identity_validator)
1350 : m_Values{validate(vals, m_Validator)}
1351 {}
1352
1353 template<class... Ts>
1354 requires admits_canonical_basis && (D > 1) && (std::convertible_to<Ts, value_type> && ...)
1355 constexpr explicit(sizeof...(Ts) == 1) coordinates_base(Ts... ts) noexcept(has_identity_validator)
1356 : coordinates_base{ts..., basis_isomorphism_type{}}
1357 {}
1358
1359 template<class... Ts>
1360 requires (D > 1) && (sizeof...(Ts) > 1) && is_units_terminated_pack_v<basis_type, value_type, Ts...>
1361 constexpr coordinates_base(Ts... ts) noexcept(has_identity_validator)
1362 : coordinates_base{std::make_index_sequence<sizeof...(Ts) - 1>{}, std::tuple{ts...}}
1363 {}
1364
1365 constexpr explicit coordinates_base(value_type val) noexcept(has_identity_validator)
1366 requires admits_canonical_basis && (D == 1)
1367 : coordinates_base{val, basis_isomorphism_type{}}
1368 {}
1369
1370 constexpr coordinates_base(value_type val, basis_isomorphism_type) noexcept(has_identity_validator)
1371 : m_Values{m_Validator(val)}
1372 {}
1373
1374 template<class Self>
1375 requires (!std::same_as<Self, coordinates_base>)
1376 constexpr Self& operator+=(this Self& self, const displacement_coordinates_type& v) noexcept(has_identity_validator)
1377 {
1378 return self = (self + v);
1379 }
1380
1381 template<class Self>
1382 requires (!std::same_as<Self, coordinates_base>)
1384 && (!std::same_as<coordinates_base, displacement_coordinates_type>)
1385 constexpr Self& operator+=(this Self& self, const coordinates_base& v) noexcept(has_identity_validator)
1386 {
1387 return self = (self + v);
1388 }
1389
1390 template<class Self>
1391 requires (!std::same_as<Self, coordinates_base>)
1392 constexpr Self& operator-=(this Self& self, const displacement_coordinates_type& v) noexcept(has_identity_validator)
1393 {
1394 return self = (self - v);
1395 }
1396
1397 template<class Self>
1398 requires (!std::same_as<Self, coordinates_base>) && has_distinguished_origin
1399 constexpr Self& operator*=(this Self& self, value_type u) noexcept(has_identity_validator)
1400 {
1401 return self = (self * u);
1402 }
1403
1404 template<class Self>
1405 requires (!std::same_as<Self, coordinates_base>) && has_distinguished_origin
1406 constexpr Self& operator*=(this Self& self, std::span<const value_type, D> u) noexcept(has_identity_validator)
1407 {
1408 return self = (self * u);
1409 }
1410
1411 template<class Self>
1412 requires (!std::same_as<Self, coordinates_base>) && vector_space<free_module_type>
1413 constexpr Self& operator/=(this Self& self, value_type u)
1414 {
1415 return self = (self / u);
1416 }
1417
1418 template<class Self>
1419 requires (!std::same_as<Self, coordinates_base>) && vector_space<free_module_type>
1420 constexpr Self& operator/=(this Self& self, std::span<const value_type, D> u)
1421 {
1422 return self = (self / u);
1423 }
1424
1425 template<class Self>
1426 requires (!std::same_as<Self, coordinates_base>)
1427 [[nodiscard]]
1428 constexpr Self operator+(this const Self& self) noexcept
1429 {
1430 return self;
1431 }
1432
1433 template<class Self>
1434 requires (!std::same_as<Self, coordinates_base>)
1436 && (!is_non_negative_orthant_v<space_type>)
1437 && (!std::is_unsigned_v<value_type>)
1438 [[nodiscard]]
1439 constexpr Self operator-(this const Self& self) noexcept(has_identity_validator)
1440 {
1441 return Self{utilities::to_array(self.values(), [](value_type t) { return -t; }), basis_isomorphism_type{}};
1442 }
1443
1444 template<class Derived>
1445 requires std::derived_from<Derived, coordinates_base>
1446 && (!std::same_as<Derived, displacement_coordinates_type>)
1447 [[nodiscard]]
1448 friend constexpr typename Derived::displacement_coordinates_type operator-(const Derived& lhs, const Derived& rhs) noexcept(has_identity_validator)
1449 {
1450 return[&] <std::size_t... Is>(std::index_sequence<Is...>) {
1451 return typename Derived::displacement_coordinates_type{(lhs.values()[Is] - rhs.values()[Is])..., basis_isomorphism_type{}};
1452 }(std::make_index_sequence<D>{});
1453 }
1454
1455 template<class Derived>
1456 requires std::derived_from<Derived, coordinates_base>
1457 [[nodiscard]]
1458 friend constexpr Derived operator+(Derived c, const displacement_coordinates_type& v) noexcept(has_identity_validator)
1459 {
1460 return c.apply_to_each_element(v.values(), [](value_type& lhs, value_type rhs){ lhs += rhs; });
1461 }
1462
1463 template<class Derived>
1464 requires std::derived_from<Derived, coordinates_base> && (!std::same_as<Derived, displacement_coordinates_type>)
1465 [[nodiscard]]
1466 friend constexpr Derived operator+(const displacement_coordinates_type& v, Derived c) noexcept(has_identity_validator)
1467 {
1468 return v + c;
1469 }
1470
1471 template<class Derived>
1472 requires std::derived_from<Derived, coordinates_base>
1473 && (!std::same_as<Derived, displacement_coordinates_type>)
1475 [[nodiscard]]
1476 friend constexpr Derived operator+(Derived c, const Derived& v) noexcept(has_identity_validator)
1477 {
1478 return c.apply_to_each_element(v.values(), [](value_type& lhs, value_type rhs){ lhs += rhs; });
1479 }
1480
1481 template<class Derived>
1482 requires std::derived_from<Derived, coordinates_base>
1483 [[nodiscard]]
1484 friend constexpr Derived operator-(Derived c, const displacement_coordinates_type& v) noexcept(has_identity_validator)
1485 {
1486 return c.apply_to_each_element(v.values(), [](value_type& lhs, value_type rhs){ lhs -= rhs; });
1487 }
1488
1489 template<class Derived>
1490 requires std::derived_from<Derived, coordinates_base> && has_distinguished_origin
1491 [[nodiscard]]
1492 friend constexpr Derived operator*(Derived v, value_type u) noexcept(has_identity_validator)
1493 {
1494 return v.for_each_element([u](value_type& x) { return x *= u; });
1495 }
1496
1497 template<class Derived>
1498 requires std::derived_from<Derived, coordinates_base> && has_distinguished_origin
1499 [[nodiscard]]
1500 friend constexpr Derived operator*(value_type u, Derived v) noexcept(has_identity_validator)
1501 {
1502 return v * u;
1503 }
1504
1505 template<class Derived>
1506 requires std::derived_from<Derived, coordinates_base> && has_distinguished_origin
1507 [[nodiscard]]
1508 friend constexpr Derived operator*(Derived c, std::span<const value_type, D> u) noexcept(has_identity_validator)
1509 {
1510 return c.apply_to_each_element(u, [](value_type& lhs, value_type rhs){ lhs *= rhs; });
1511 }
1512
1513 template<class Derived>
1514 requires std::derived_from<Derived, coordinates_base> && has_distinguished_origin
1515 [[nodiscard]]
1516 friend constexpr Derived operator*(std::span<const value_type, D> u, Derived c) noexcept(has_identity_validator)
1517 {
1518 return c * u;
1519 }
1520
1521 template<class Derived>
1522 requires std::derived_from<Derived, coordinates_base> && vector_space<free_module_type> && has_distinguished_origin
1523 [[nodiscard]]
1524 friend constexpr Derived operator/(Derived v, value_type u)
1525 {
1526 return v.for_each_element([u](value_type& x) { return x /= u; });
1527 }
1528
1529 template<class Derived>
1530 requires std::derived_from<Derived, coordinates_base> && has_distinguished_origin
1531 [[nodiscard]]
1532 friend constexpr Derived operator/(Derived c, std::span<const value_type, D> u) noexcept(has_identity_validator)
1533 {
1534 return c.apply_to_each_element(u, [](value_type& lhs, value_type rhs){ lhs /= rhs; });
1535 }
1536
1537 [[nodiscard]]
1538 constexpr const validator_type& validator() const noexcept { return m_Validator; }
1539
1540 [[nodiscard]]
1541 constexpr std::span<const value_type, D> values() const noexcept { return m_Values; }
1542
1543 [[nodiscard]]
1544 constexpr std::span<value_type, D> values() noexcept requires has_freely_mutable_components { return m_Values; }
1545
1546 [[nodiscard]]
1547 constexpr const value_type& value() const noexcept requires (D == 1) { return m_Values[0]; }
1548
1549 [[nodiscard]]
1550 constexpr value_type& value() noexcept requires (D == 1) && has_freely_mutable_components { return m_Values[0]; }
1551
1553 [[nodiscard]]
1554 constexpr explicit operator bool() const noexcept requires (D == 1) && std::convertible_to<value_type, bool>
1555 {
1556 return m_Values[0];
1557 }
1558
1559 [[nodiscard]]
1560 constexpr value_type operator[](std::size_t i) const { return m_Values[i]; }
1561
1562 [[nodiscard]]
1563 constexpr value_type& operator[](std::size_t i) requires has_freely_mutable_components { return m_Values[i]; }
1564
1565 [[nodiscard]]
1566 constexpr auto begin() const noexcept { return m_Values.begin(); }
1567
1568 [[nodiscard]]
1569 constexpr auto end() const noexcept { return m_Values.end(); }
1570
1571 [[nodiscard]]
1572 constexpr auto rbegin() const noexcept { return m_Values.rbegin(); }
1573
1574 [[nodiscard]]
1575 constexpr auto rend() const noexcept { return m_Values.rend(); }
1576
1577 [[nodiscard]]
1578 constexpr auto cbegin() const noexcept { return begin(); }
1579
1580 [[nodiscard]]
1581 constexpr auto cend() const noexcept { return end(); }
1582
1583 [[nodiscard]]
1584 constexpr auto crbegin() const noexcept { return rbegin(); }
1585
1586 [[nodiscard]]
1587 constexpr auto crend() const noexcept { return rend(); }
1588
1589 [[nodiscard]]
1590 constexpr auto begin() noexcept requires has_freely_mutable_components { return m_Values.begin(); }
1591
1592 [[nodiscard]]
1593 constexpr auto end() noexcept requires has_freely_mutable_components { return m_Values.end(); }
1594
1595 [[nodiscard]]
1596 constexpr auto rbegin() noexcept requires has_freely_mutable_components { return m_Values.rbegin(); }
1597
1598 [[nodiscard]]
1599 constexpr auto rend() noexcept requires has_freely_mutable_components { return m_Values.rend(); }
1600
1601
1602 [[nodiscard]]
1603 friend constexpr bool operator==(const coordinates_base& lhs, const coordinates_base& rhs) noexcept { return lhs.m_Values == rhs.m_Values; }
1604
1605 [[nodiscard]]
1606 friend constexpr auto operator<=>(const coordinates_base& lhs, const coordinates_base& rhs) noexcept
1607 requires (D == 1) && std::totally_ordered<value_type>
1608 {
1609 return lhs.value() <=> rhs.value();
1610 }
1611 protected:
1612 coordinates_base(const coordinates_base&) = default;
1613 coordinates_base(coordinates_base&&) noexcept = default;
1614
1615 coordinates_base& operator=(const coordinates_base&) = default;
1616 coordinates_base& operator=(coordinates_base&&) noexcept = default;
1617
1618 ~coordinates_base() = default;
1619
1620 template<class Self, class Fn>
1621 requires std::invocable<Fn, value_type&, value_type>
1622 constexpr Self&& apply_to_each_element(this Self&& self, std::span<const value_type, D> rhs, Fn f)
1623 {
1624 if constexpr(has_identity_validator)
1625 {
1626 std::ranges::for_each(std::views::zip(self.m_Values, rhs), [&f](auto&& z){ f(std::get<0>(z), std::get<1>(z)); });
1627 }
1628 else
1629 {
1630 auto tmp{self.m_Values};
1631 std::ranges::for_each(std::views::zip(tmp, rhs), [&f](auto&& z){ f(std::get<0>(z), std::get<1>(z)); });
1632 self.m_Values = validate(tmp, self.m_Validator);
1633 }
1634
1635 return std::forward<Self>(self);
1636 }
1637
1638 template<class Self, class Fn>
1639 requires std::invocable<Fn, value_type&>
1640 constexpr Self& for_each_element(this Self& self, Fn f)
1641 {
1642 if constexpr(has_identity_validator)
1643 {
1644 std::ranges::for_each(self.values(), f);
1645 }
1646 else
1647 {
1648 auto tmp{self.m_Values};
1649 std::ranges::for_each(tmp, f);
1650 self.m_Values = validate(tmp, self.m_Validator);
1651 }
1652
1653 return self;
1654 }
1655 private:
1656 SEQUOIA_NO_UNIQUE_ADDRESS validator_type m_Validator;
1657 std::array<value_type, D> m_Values{};
1658
1659 template<std::size_t... Is, class... Args>
1660 constexpr coordinates_base(std::index_sequence<Is...>, const std::tuple<Args...>& args)
1661 : m_Values{m_Validator(std::array<value_type, D>{std::get<Is>(args)...})}
1662 {}
1663
1664 [[nodiscard]]
1665 static std::array<value_type, D> validate(std::span<const value_type, D> vals, Validator& validator)
1666 {
1667 return validate(utilities::to_array(vals), validator);
1668 }
1669
1670 [[nodiscard]]
1671 static std::array<value_type, D> validate(std::array<value_type, D> vals, Validator& validator)
1672 {
1673 if constexpr(validator_for_array<Validator, ConvexSpace>)
1674 return validator(vals);
1675 else
1676 return {validator(vals.front())};
1677 }
1678 };
1679
1684 template<convex_space ConvexSpace, basis_for<free_module_type_of_t<ConvexSpace>> Basis, class Origin, validator_for<ConvexSpace> Validator>
1685 class coordinates<ConvexSpace, Basis, Origin, Validator> final
1686 : public coordinates_base<ConvexSpace, Basis, Validator>
1687 {
1688 public:
1689 using origin_type = Origin;
1690
1691 using coordinates_base<ConvexSpace, Basis, Validator>::coordinates_base;
1692 };
1693
1694 template<convex_space ConvexSpace, basis_for<free_module_type_of_t<ConvexSpace>> Basis, validator_for<ConvexSpace> Validator>
1695 requires has_distinguished_origin_v<ConvexSpace>
1696 class coordinates<ConvexSpace, Basis, Validator> final
1697 : public coordinates_base<ConvexSpace, Basis, Validator>
1698 {
1699 public:
1700 using coordinates_base<ConvexSpace, Basis, Validator>::coordinates_base;
1701 };
1702
1703 template<affine_space AffineSpace, basis_for<free_module_type_of_t<AffineSpace>> Basis, class Origin>
1704 requires (!free_module<AffineSpace>)
1707 {
1708 public:
1709 using origin_type = Origin;
1710
1711 using coordinates_base<AffineSpace, Basis, std::identity>::coordinates_base;
1712 };
1713
1714 template<free_module M, basis_for<free_module_type_of_t<M>> Basis>
1715 class coordinates<M, Basis> final
1716 : public coordinates_base<M, Basis, std::identity>
1717 {
1718 public:
1719 using coordinates_base<M, Basis, std::identity>::coordinates_base;
1720 };
1721
1722 template<class From, class To>
1724 {
1725 };
1726
1727 template<class From, class To>
1728 inline constexpr bool has_coordinate_transformation_v{
1729 requires (const From& f){
1730 { std::declval<coordinate_transformation<From, To>>()(f) } -> std::convertible_to<To>;
1731 }
1732 };
1733
1734 template<class From, class To>
1735 inline constexpr bool has_noexcept_coordinate_transformation_v{
1736 has_coordinate_transformation_v<From, To>
1737 && requires (const From& f){
1738 requires noexcept(std::declval<coordinate_transformation<From, To>>()(f));
1739 }
1740 };
1741
1742 namespace sets
1743 {
1747 template<std::size_t D>
1748 struct Z
1749 {
1750 constexpr static std::size_t dimension{D};
1751 };
1752
1756 template<std::size_t D>
1757 struct N_0
1758 {
1759 constexpr static std::size_t dimension{D};
1760 };
1761
1765 template<std::size_t D>
1766 struct R
1767 {
1768 constexpr static std::size_t dimension{D};
1769 };
1770
1771
1775 template<std::size_t D>
1776 struct orthant
1777 {
1778 constexpr static std::size_t dimension{D};
1779 };
1780
1784 template<std::size_t D>
1785 struct C
1786 {
1787 constexpr static std::size_t dimension{D};
1788 };
1789 }
1790
1791 template<class B>
1792 inline constexpr bool is_orthonormal_basis_v{
1793 requires {
1794 typename B::orthonormal;
1795 requires std::same_as<typename B::orthonormal, std::true_type>;
1796 }
1797 };
1798
1799 template<vector_space V>
1801
1802 template<vector_space V>
1803 inline constexpr bool has_norm_v{
1804 requires (const vector_coordinates<V, arbitary_basis<V>>& v) {
1805 { norm(v) } -> std::convertible_to<typename V::field_type>;
1806 }
1807 };
1808
1809 template<vector_space V>
1810 inline constexpr bool has_inner_product_v{
1811 requires (const vector_coordinates<V, arbitary_basis<V>>& v) {
1812 { inner_product(v, v) } -> std::convertible_to<typename V::field_type>;
1813 }
1814 };
1815
1816 template<class V>
1817 concept normed_vector_space = vector_space<V> && has_norm_v<V>;
1818
1819 template<class V>
1820 concept inner_product_space = vector_space<V> && has_inner_product_v<V>;
1821
1822 // TO DO: reconsider whether this is necessary
1824
1825 template<std::floating_point T, std::size_t D, class Arena=mathematical_arena>
1827 {
1828 using set_type = sets::R<D>;
1829 using field_type = T;
1830 using is_vector_space = std::true_type;
1831 using arena_type = Arena;
1832 using admits_canonical_basis = std::true_type;
1833 constexpr static std::size_t dimension{D};
1834
1835 template<basis Basis>
1836 requires is_orthonormal_basis_v<Basis>
1837 [[nodiscard]]
1838 friend constexpr field_type inner_product(const vector_coordinates<euclidean_vector_space, Basis>& v, const vector_coordinates<euclidean_vector_space, Basis>& w)
1839 {
1840 return
1841 std::ranges::fold_left(
1842 std::views::zip(v.values(), w.values()),
1843 field_type{},
1844 [](field_type f, const auto& z){ return f + std::get<0>(z) * std::get<1>(z); }
1845 );
1846 }
1847
1848 template<basis Basis>
1849 requires is_orthonormal_basis_v<Basis>
1850 [[nodiscard]]
1852 {
1853 return inner_product(v, w);
1854 }
1855
1856 template<basis Basis>
1857 requires is_orthonormal_basis_v<Basis>
1858 [[nodiscard]]
1859 friend constexpr field_type norm(const vector_coordinates<euclidean_vector_space, Basis>& v)
1860 {
1861 if constexpr(D == 1)
1862 {
1863 return std::abs(v.value());
1864 }
1865 else
1866 {
1867 return std::sqrt(inner_product(v, v));
1868 }
1869 }
1870 };
1871
1872 template<std::floating_point T, std::size_t D, class Arena=mathematical_arena>
1874 {
1875 using set_type = sets::R<D>;
1877 using is_affine_space = std::true_type;
1878 using arena_type = Arena;
1879 };
1880
1881 template<std::floating_point T, class Arena=mathematical_arena>
1883 {
1884 using set_type = sets::orthant<1>;
1886 using is_convex_space = std::true_type;
1887 using arena_type = Arena;
1888 using distinguished_origin = std::true_type;
1889 using non_negative_orthant = std::true_type;
1890 };
1891
1892 template<class T>
1893 inline constexpr bool has_arena_type_v{
1894 requires { typename T::arena_type;}
1895 };
1896
1897 template<class T>
1899
1900 template<class T>
1901 using arena_type_of_t = arena_type_of<T>::type;
1902
1903 template<class T>
1904 requires has_arena_type_v<T>
1906 {
1907 using type = T::arena_type;
1908 };
1909
1910 template<convex_space T>
1911 requires (!has_arena_type_v<dual<T>>)
1913 {
1914 using type = arena_type_of_t<T>;
1915 };
1916
1917 template<convex_space... Ts>
1918 requires (!has_arena_type_v<direct_product<Ts...>>)
1920 {
1921 using type = std::common_type_t<arena_type_of_t<Ts>...>;
1922 };
1923
1924 template<std::floating_point T, std::size_t D, basis Basis, class Origin, class Arena=mathematical_arena>
1926
1927 template<std::floating_point T, std::size_t D, basis Basis, class Arena=mathematical_arena>
1929
1935 template<free_module M>
1937 {
1938 using is_basis = std::true_type;
1939 using free_module_type = M;
1940 };
1941
1942 template<free_module M>
1944 {
1946 };
1947
1948 template<free_module M>
1950 {
1952 };
1953
1954 template<class T>
1956
1957 template<auto Num, auto Den>
1958 struct dilatation<ratio<Num, Den>>
1959 {
1961 };
1962
1963 template<std::intmax_t Num, std::intmax_t Den>
1964 struct dilatation<std::ratio<Num, Den>>
1965 {
1966 using ratio_type = std::ratio<Num, Den>;
1967 };
1968
1969 template<class...>
1971
1972 template<class Ratio> // TO DO: reflections and rotations
1974 {
1976 };
1977
1978 template<class...>
1980
1981 template<free_module M, class Ratio, basis_for<M> ReferenceBasis>
1983 {
1984 using reference_basis_type = ReferenceBasis;
1985 using is_basis = std::true_type;
1986 using free_module_type = M;
1987 };
1988
1989 template<std::floating_point T, std::size_t D, class Arena=mathematical_arena>
1991}
Utility to convert an initializer_list into an array, potentially transforming the initializer_list i...
Concepts which are sufficiently general to appear in the sequoia namespace.
Definition: Spaces.hpp:1321
Type to indicate a distinguished origin, relevant for free modules.
Definition: Spaces.hpp:1239
concept for affine spaces
Definition: Spaces.hpp:530
A concept to determine if a basis is appropriate for a particular free module.
Definition: Spaces.hpp:692
A basis must identify the free module to which it corresponds.
Definition: Spaces.hpp:644
concept for convex spaces
Definition: Spaces.hpp:518
concept for a free module, implicitly understood to be over a commutative ring.
Definition: Spaces.hpp:477
Definition: Spaces.hpp:1820
Definition: Spaces.hpp:1817
concept to check if a validator is compatible with a convex space.
Definition: Spaces.hpp:749
concept for a vector space, which is a special case of a free module
Definition: Spaces.hpp:483
concept representing reasonable approximations to a commutative ring.
Definition: Spaces.hpp:323
concept representing reasonable approximations to a field.
Definition: Spaces.hpp:335
constexpr bool is_multiplicable_v
Compile time constant for multiplicability.
Definition: Spaces.hpp:223
constexpr bool is_divisible_v
Compile time constant for divisibility.
Definition: Spaces.hpp:234
constexpr bool is_subtractable_v
Compile time constant for subtractability.
Definition: Spaces.hpp:212
constexpr bool is_addable_v
Compile time constant for addability.
Definition: Spaces.hpp:201
constexpr bool identifies_as_basis_v
Compile time constant reflecting whether a type self-identifies as a basis.
Definition: Spaces.hpp:631
constexpr bool identifies_as_convex_space_v
Compile time constant reflecting whether a space self-identifies as convex.
Definition: Spaces.hpp:425
constexpr bool identifies_as_free_module_v
Compile time constant reflecting whether a space self-identifies as a free module.
Definition: Spaces.hpp:447
constexpr bool identifies_as_affine_space_v
Compile time constant reflecting whether a space self-identifies as affine.
Definition: Spaces.hpp:436
constexpr bool identifies_as_vector_space_v
Compile time constant reflecting whether a space self-identifies as vector space.
Definition: Spaces.hpp:458
constexpr bool has_commutative_ring_type_v
Compile time constant reflecting whether a type exposes a nested type named commutative_ring_type whi...
Definition: Spaces.hpp:345
constexpr bool has_free_module_type_v
Compile time constant reflecting whether a type exposes a nested free_modul_type which satisfies the ...
Definition: Spaces.hpp:502
constexpr bool defines_commutative_ring_v
Compile time constant reflecting whether a type exposes a nested type with the properties of a commut...
Definition: Spaces.hpp:370
constexpr bool has_field_type_v
Compile time constant reflecting whether a type exposes a nested type named field_type which satisife...
Definition: Spaces.hpp:356
constexpr bool has_vector_space_type_v
Compile time constant reflecting whether a type exposes a nested vector_space_type which satisfies th...
Definition: Spaces.hpp:490
constexpr bool has_dimension_v
Compile time constant reflecting whether a type exposes a nested value, dimension,...
Definition: Spaces.hpp:392
constexpr std::size_t dimension_of
Helper to extract the dimension of the free module associated with a convex space.
Definition: Spaces.hpp:600
constexpr bool defines_field_v
Reports whether a type exposes a nested type with the properties of a field.
Definition: Spaces.hpp:380
constexpr bool has_set_type_v
Compile time constant reflecting whether a type exposes a nested type named set_type.
Definition: Spaces.hpp:400
constexpr bool validator_for_single_value
Validators for spaces of dimension 1 must provide an operator() for validating single values.
Definition: Spaces.hpp:725
constexpr bool validator_for_array
Validators for spaces of dimension d>1 must provide an operator() for an array of d values.
Definition: Spaces.hpp:739
Definition: Spaces.hpp:611
Definition: Spaces.hpp:1800
Definition: Spaces.hpp:1898
Right-handed bases for arbitrary D, built recursively from 1D.
Definition: Spaces.hpp:1937
Helper to extract the commutative ring type of the free module associated with a convex space.
Definition: Spaces.hpp:578
Trait to determine if a type defines the half line.
Definition: Spaces.hpp:849
Trait for validators that behave like the identity.
Definition: Spaces.hpp:759
Definition: Spaces.hpp:1955
Definition: Spaces.hpp:896
Specialization for units, such as degrees Celsius, for which the corresponding quantity cannot be inv...
Definition: PhysicalValues.hpp:66
Helper to generate the dual of a space, taking into account that the dual of the dual may be related ...
Definition: Spaces.hpp:1109
Primary class template for defining duals.
Definition: Spaces.hpp:1041
Definition: Spaces.hpp:1874
Definition: Spaces.hpp:1883
Definition: Spaces.hpp:1827
Helper to extract the free module type associated with a convex space.
Definition: Spaces.hpp:545
A validator for the half line.
Definition: Spaces.hpp:776
Definition: Spaces.hpp:1162
Definition: Spaces.hpp:665
A generic interval validator for floating-point types.
Definition: Spaces.hpp:800
Definition: Spaces.hpp:934
Helper to detect if a type is defined as a dual of something else.
Definition: Spaces.hpp:1083
Helper that universal template parameters will obviate the need for.
Definition: Spaces.hpp:536
Definition: Spaces.hpp:834
Definition: Spaces.hpp:1125
Definition: Spaces.hpp:1303
Definition: Spaces.hpp:1823
Trait for specifying whether a type exhibits multiplication that (approximately) distributes over add...
Definition: Spaces.hpp:309
Definition: Spaces.hpp:1979
Definition: Ratio.hpp:23
Definition: Ratio.hpp:18
Class template for giving a name to the set of complex numbers and its generalization to other dimens...
Definition: Spaces.hpp:1786
Class template for giving a name to the set of semi-positive integers and its generalization to other...
Definition: Spaces.hpp:1758
Class template for giving a name to the set of real numbers and its generalization to other dimension...
Definition: Spaces.hpp:1767
Class template for giving a name to the set of integers and its generalization to other dimensionalit...
Definition: Spaces.hpp:1749
Class template for giving a name to convex functionals.
Definition: Spaces.hpp:1021
Class template for giving a name to linear functionals.
Definition: Spaces.hpp:1033
Class template for giving a name to the set of non-negative real numbers and its generalization to ot...
Definition: Spaces.hpp:1777
Trait for specifying whether a type behaves (appoximately) as an abelian group under addition.
Definition: Spaces.hpp:262
Trait for specifying whether a type behaves (appoximately) as an abelian group under multiplication.
Definition: Spaces.hpp:287
Detects value_type.
Definition: Iterator.hpp:111