157#include "sequoia/PlatformSpecific/Preprocessor.hpp"
167namespace sequoia::maths
203 { t += t } -> std::same_as<T&>;
204 { t + t } -> std::convertible_to<T>;
214 { t -= t } -> std::same_as<T&>;
215 { t - t } -> std::convertible_to<T>;
225 { t *= t } -> std::same_as<T&>;
226 { t * t } -> std::convertible_to<T>;
236 { t /= t } -> std::same_as<T&>;
237 { t / t } -> std::convertible_to<T>;
270 template<arithmetic T>
273 template<std::
floating_po
int T>
295 template<std::
floating_po
int T>
298 template<std::
floating_po
int T>
324 && weakly_abelian_group_under_addition_v<T>
325 && multiplication_weakly_distributive_over_addition_v<T>
327 && is_subtractable_v<T>
328 && is_multiplicable_v<T>;
347 typename T::commutative_ring_type;
358 typename T::field_type;
383 typename T::commutative_ring_type;
393 requires { { T::dimension } -> std::convertible_to<std::size_t>; }
401 requires {
typename T::set_type; }
427 typename T::is_convex_space;
428 requires std::convertible_to<typename T::is_convex_space, std::true_type>;
438 typename T::is_affine_space;
439 requires std::convertible_to<typename T::is_affine_space, std::true_type>;
449 typename T::is_free_module;
450 requires std::convertible_to<typename T::is_free_module, std::true_type>;
460 typename T::is_vector_space;
461 requires std::convertible_to<typename T::is_vector_space, std::true_type>;
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>);
492 typename T::vector_space_type;
504 typename T::free_module_type;
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>));
547 template<convex_space ConvexSpace>
548 requires identifies_as_free_module_v<ConvexSpace> || identifies_as_vector_space_v<ConvexSpace>
551 using type = ConvexSpace;
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>
558 using type = ConvexSpace::free_module_type;
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>
565 using type = ConvexSpace::vector_space_type;
569 using free_module_type_of_t = free_module_type_of<T>::type;
576 template<convex_space ConvexSpace>
579 using type = free_module_type_of_t<ConvexSpace>::commutative_ring_type;
582 template<convex_space ConvexSpace>
586 using type = free_module_type_of_t<ConvexSpace>::field_type;
589 template<convex_space ConvexSpace>
590 using commutative_ring_type_of_t = commutative_ring_type_of<ConvexSpace>::type;
592 template<convex_space ConvexSpace>
593 using space_value_type = commutative_ring_type_of_t<ConvexSpace>;
599 template<convex_space ConvexSpace>
600 inline constexpr std::size_t
dimension_of{free_module_type_of_t<ConvexSpace>::dimension};
603 template<free_module V>
604 inline constexpr bool has_admits_canonical_basis_v{
606 typename V::admits_canonical_basis;
610 template<free_module M>
613 template<free_module M>
614 requires has_admits_canonical_basis_v<M> && std::convertible_to<typename M::admits_canonical_basis, std::true_type>
617 template<free_module M>
620 template<free_module M>
633 typename T::is_basis;
634 requires std::convertible_to<typename T::is_basis, std::true_type>;
644 concept basis = identifies_as_basis_v<B> && (has_free_module_type_v<B> || has_vector_space_type_v<B>);
647 requires has_free_module_type_v<B>
650 using type = B::free_module_type;
654 requires has_vector_space_type_v<B>
657 using type = B::vector_space_type;
661 inline constexpr bool has_isomorphism_type_v{
662 requires {
typename T::isomorphism_type; }
671 requires admits_canonical_basis_v<free_module_type_of_t<B>>
681 requires (!admits_canonical_basis_v<free_module_type_of_t<B>>) && has_isomorphism_type_v<B>
684 using type = B::isomorphism_type;
690 template<
class B,
class M>
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>; };
724 template<
class V,
class ConvexSpace>
726 (dimension_of<ConvexSpace> == 1)
727 &&
requires(V& v,
const space_value_type<ConvexSpace>& val) { { v(val) } -> std::convertible_to<
decltype(val)>; }
738 template<
class V,
class ConvexSpace>
740 requires (V& v,
const std::array<space_value_type<ConvexSpace>, dimension_of<ConvexSpace>>& values) {
741 { v(values) } -> std::convertible_to<
decltype(values)>;
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>);
777 template<arithmetic T>
778 constexpr T operator()(
const T val)
const
780 if(val < T{})
throw std::domain_error{std::format(
"Domain error: attempting to use a value of {} for a semi-positive quantity", val)};
785 template<arithmetic T>
786 requires std::is_unsigned_v<T>
788 constexpr T operator()(
const T val)
const
797 template<std::floating_point T, T Lower, T Upper=std::numeric_limits<T>::infinity()>
798 requires (Upper > Lower)
801 constexpr static T lower{Lower}, upper{Upper};
803 template<std::
floating_po
int U>
804 requires (
sizeof(U) <=
sizeof(T))
805 constexpr U
operator()(
const U val)
const
807 if constexpr(Lower > -std::numeric_limits<T>::infinity())
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)};
813 if constexpr(Upper < std::numeric_limits<T>::infinity())
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)};
822 template<std::
floating_po
int 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
826 for(
const auto v : vals)
842 template<std::
floating_po
int T, T Lower, T Upper>
860 template<std::
floating_po
int T, T Lower, T Upper>
862 : std::bool_constant<(Lower == T{}) && (Upper == std::numeric_limits<T>::infinity())>
865 template<std::
floating_po
int T, T Lower, T Upper>
867 : std::bool_constant<(Lower == -std::numeric_limits<T>::infinity()) && (Upper == std::numeric_limits<T>::infinity())>
894 template<
class... Ts>
900 inline constexpr bool has_common_ring_v{
904 template<free_module... Ts>
905 requires (
sizeof...(Ts) >= 1) && has_common_ring_v<commutative_ring_type_of_t<Ts>...>
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 + ...)};
920 using is_affine_space = std::true_type;
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...>
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;
936 template<
class... Ts>
951 template<
class... Ts>
954 constexpr static auto value{
sizeof...(Ts)};
1019 template<convex_space From,
class To>
1031 template<vector_space From,
class To>
1046 template<convex_space C>
1052 using is_convex_space = std::true_type;
1058 template<affine_space A>
1064 using is_affine_space = std::true_type;
1070 template<vector_space V>
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};
1106 using dual_of_t = dual_of<T>::type;
1123 template<convex_space C>
1127 template<convex_space C>
1130 template<convex_space C>
1133 template<convex_space Space>
1134 inline constexpr bool has_non_negative_orthant_type_v{
1136 typename Space::non_negative_orthant;
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>
1147 template<convex_space C>
1153 template<convex_space Space>
1154 inline constexpr bool has_distinguished_origin_type_v{
1156 typename Space::distinguished_origin;
1160 template<convex_space Space>
1164 template<convex_space Space>
1167 template<convex_space Space>
1170 template<convex_space Space>
1171 requires has_distinguished_origin_type_v<Space> && std::convertible_to<typename Space::distinguished_origin, std::true_type>
1176 template<convex_space Space>
1177 requires (!has_distinguished_origin_type_v<Space>) && is_non_negative_orthant_v<Space>
1182 template<free_module Space>
1183 struct has_distinguished_origin<Space> : std::true_type
1186 template<affine_space Space>
1187 requires (!free_module<Space>)
1188 struct has_distinguished_origin<Space> : std::false_type
1191 template<convex_space Space>
1247 template<affine_space AffineSpace, basis_for<free_module_type_of_t<AffineSpace>> Basis,
class Origin>
1253 template<vector_space VectorSpace, basis_for<free_module_type_of_t<VectorSpace>> Basis>
1259 template<free_module FreeModule, basis_for<free_module_type_of_t<FreeModule>> Basis>
1289 template<
basis B,
class Rep,
class...>
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> && ...)
1301 template<
basis B,
class Rep,
class... Args>
1305 template<
basis B,
class Rep,
class... Args>
1306 requires (
sizeof...(Args) > 1)
1311 template<
basis B,
class Rep,
class... Args>
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>
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>;
1335 constexpr static bool has_identity_validator{defines_identity_validator_v<Validator>};
1339 constexpr static std::size_t dimension{free_module_type::dimension};
1340 constexpr static std::size_t D{dimension};
1344 constexpr explicit coordinates_base(std::span<const value_type, D> vals)
noexcept(has_identity_validator)
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)}
1353 template<
class... Ts>
1355 constexpr explicit(
sizeof...(Ts) == 1)
coordinates_base(Ts... ts)
noexcept(has_identity_validator)
1359 template<
class... Ts>
1360 requires (D > 1) && (
sizeof...(Ts) > 1) && is_units_terminated_pack_v<basis_type, value_type, Ts...>
1362 :
coordinates_base{std::make_index_sequence<
sizeof...(Ts) - 1>{}, std::tuple{ts...}}
1365 constexpr explicit coordinates_base(value_type val)
noexcept(has_identity_validator)
1370 constexpr coordinates_base(value_type val, basis_isomorphism_type)
noexcept(has_identity_validator)
1371 : m_Values{m_Validator(val)}
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)
1378 return self = (self + v);
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)
1387 return self = (self + v);
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)
1394 return self = (self - v);
1397 template<
class Self>
1399 constexpr Self&
operator*=(
this Self& self, value_type u)
noexcept(has_identity_validator)
1401 return self = (self * u);
1404 template<
class Self>
1406 constexpr Self&
operator*=(
this Self& self, std::span<const value_type, D> u)
noexcept(has_identity_validator)
1408 return self = (self * u);
1411 template<
class Self>
1413 constexpr Self&
operator/=(
this Self& self, value_type u)
1415 return self = (self / u);
1418 template<
class Self>
1420 constexpr Self&
operator/=(
this Self& self, std::span<const value_type, D> u)
1422 return self = (self / u);
1425 template<
class Self>
1426 requires (!std::same_as<Self, coordinates_base>)
1428 constexpr Self
operator+(
this const Self& self)
noexcept
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>)
1439 constexpr Self
operator-(
this const Self& self)
noexcept(has_identity_validator)
1441 return Self{utilities::to_array(self.values(), [](value_type t) { return -t; }), basis_isomorphism_type{}};
1444 template<
class Derived>
1445 requires std::derived_from<Derived, coordinates_base>
1446 && (!std::same_as<Derived, displacement_coordinates_type>)
1448 friend constexpr typename Derived::displacement_coordinates_type
operator-(
const Derived& lhs,
const Derived& rhs)
noexcept(has_identity_validator)
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>{});
1455 template<
class Derived>
1456 requires std::derived_from<Derived, coordinates_base>
1458 friend constexpr Derived operator+(Derived c,
const displacement_coordinates_type& v)
noexcept(has_identity_validator)
1460 return c.apply_to_each_element(v.values(), [](value_type& lhs, value_type rhs){ lhs += rhs; });
1463 template<
class Derived>
1464 requires std::derived_from<Derived, coordinates_base> && (!std::same_as<Derived, displacement_coordinates_type>)
1466 friend constexpr Derived
operator+(
const displacement_coordinates_type& v, Derived c)
noexcept(has_identity_validator)
1471 template<
class Derived>
1472 requires std::derived_from<Derived, coordinates_base>
1473 && (!std::same_as<Derived, displacement_coordinates_type>)
1476 friend constexpr Derived
operator+(Derived c,
const Derived& v)
noexcept(has_identity_validator)
1478 return c.apply_to_each_element(v.values(), [](value_type& lhs, value_type rhs){ lhs += rhs; });
1481 template<
class Derived>
1482 requires std::derived_from<Derived, coordinates_base>
1484 friend constexpr Derived operator-(Derived c,
const displacement_coordinates_type& v)
noexcept(has_identity_validator)
1486 return c.apply_to_each_element(v.values(), [](value_type& lhs, value_type rhs){ lhs -= rhs; });
1489 template<
class Derived>
1492 friend constexpr Derived operator*(Derived v, value_type u)
noexcept(has_identity_validator)
1494 return v.for_each_element([u](value_type& x) {
return x *= u; });
1497 template<
class Derived>
1500 friend constexpr Derived operator*(value_type u, Derived v)
noexcept(has_identity_validator)
1505 template<
class Derived>
1508 friend constexpr Derived operator*(Derived c, std::span<const value_type, D> u)
noexcept(has_identity_validator)
1510 return c.apply_to_each_element(u, [](value_type& lhs, value_type rhs){ lhs *= rhs; });
1513 template<
class Derived>
1516 friend constexpr Derived operator*(std::span<const value_type, D> u, Derived c)
noexcept(has_identity_validator)
1521 template<
class Derived>
1524 friend constexpr Derived operator/(Derived v, value_type u)
1526 return v.for_each_element([u](value_type& x) {
return x /= u; });
1529 template<
class Derived>
1532 friend constexpr Derived operator/(Derived c, std::span<const value_type, D> u)
noexcept(has_identity_validator)
1534 return c.apply_to_each_element(u, [](value_type& lhs, value_type rhs){ lhs /= rhs; });
1538 constexpr const validator_type& validator()
const noexcept {
return m_Validator; }
1541 constexpr std::span<const value_type, D> values()
const noexcept {
return m_Values; }
1544 constexpr std::span<value_type, D> values()
noexcept requires has_freely_mutable_components {
return m_Values; }
1547 constexpr const value_type& value()
const noexcept requires (D == 1) {
return m_Values[0]; }
1550 constexpr value_type& value()
noexcept requires (D == 1) && has_freely_mutable_components {
return m_Values[0]; }
1554 constexpr explicit operator bool() const noexcept requires (D == 1) && std::convertible_to<value_type,
bool>
1560 constexpr value_type operator[](std::size_t i)
const {
return m_Values[i]; }
1563 constexpr value_type& operator[](std::size_t i)
requires has_freely_mutable_components {
return m_Values[i]; }
1566 constexpr auto begin() const noexcept {
return m_Values.begin(); }
1569 constexpr auto end() const noexcept {
return m_Values.end(); }
1572 constexpr auto rbegin() const noexcept {
return m_Values.rbegin(); }
1575 constexpr auto rend() const noexcept {
return m_Values.rend(); }
1578 constexpr auto cbegin() const noexcept {
return begin(); }
1581 constexpr auto cend() const noexcept {
return end(); }
1584 constexpr auto crbegin() const noexcept {
return rbegin(); }
1587 constexpr auto crend() const noexcept {
return rend(); }
1590 constexpr auto begin() noexcept requires has_freely_mutable_components {
return m_Values.begin(); }
1593 constexpr auto end() noexcept requires has_freely_mutable_components {
return m_Values.end(); }
1596 constexpr auto rbegin() noexcept requires has_freely_mutable_components {
return m_Values.rbegin(); }
1599 constexpr auto rend() noexcept requires has_freely_mutable_components {
return m_Values.rend(); }
1603 friend constexpr bool operator==(
const coordinates_base& lhs,
const coordinates_base& rhs)
noexcept {
return lhs.m_Values == rhs.m_Values; }
1606 friend constexpr auto operator<=>(
const coordinates_base& lhs,
const coordinates_base& rhs)
noexcept
1607 requires (D == 1) && std::totally_ordered<value_type>
1609 return lhs.value() <=> rhs.value();
1612 coordinates_base(
const coordinates_base&) =
default;
1613 coordinates_base(coordinates_base&&) noexcept = default;
1615 coordinates_base& operator=(const coordinates_base&) = default;
1616 coordinates_base& operator=(coordinates_base&&) noexcept = default;
1618 ~coordinates_base() = default;
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)
1624 if constexpr(has_identity_validator)
1626 std::ranges::for_each(std::views::zip(self.m_Values, rhs), [&f](
auto&& z){ f(std::get<0>(z), std::get<1>(z)); });
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);
1635 return std::forward<Self>(self);
1638 template<
class Self,
class Fn>
1639 requires std::invocable<Fn, value_type&>
1640 constexpr Self& for_each_element(
this Self& self, Fn f)
1642 if constexpr(has_identity_validator)
1644 std::ranges::for_each(self.values(), f);
1648 auto tmp{self.m_Values};
1649 std::ranges::for_each(tmp, f);
1650 self.m_Values = validate(tmp, self.m_Validator);
1656 SEQUOIA_NO_UNIQUE_ADDRESS validator_type m_Validator;
1657 std::array<value_type, D> m_Values{};
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)...})}
1665 static std::array<value_type, D> validate(std::span<const value_type, D> vals, Validator& validator)
1667 return validate(utilities::to_array(vals), validator);
1671 static std::array<value_type, D> validate(std::array<value_type, D> vals, Validator& validator)
1673 if constexpr(validator_for_array<Validator, ConvexSpace>)
1674 return validator(vals);
1676 return {validator(vals.front())};
1684 template<convex_space ConvexSpace, basis_for<free_module_type_of_t<ConvexSpace>> Basis,
class Origin, val
idator_for<ConvexSpace> Val
idator>
1689 using origin_type = Origin;
1694 template<convex_space ConvexSpace, basis_for<free_module_type_of_t<ConvexSpace>> Basis, val
idator_for<ConvexSpace> Val
idator>
1695 requires has_distinguished_origin_v<ConvexSpace>
1703 template<affine_space AffineSpace, basis_for<free_module_type_of_t<AffineSpace>> Basis,
class Origin>
1709 using origin_type = Origin;
1711 using coordinates_base<AffineSpace, Basis, std::identity>::coordinates_base;
1714 template<free_module M, basis_for<free_module_type_of_t<M>> Basis>
1722 template<
class From,
class To>
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>;
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));
1747 template<std::
size_t D>
1750 constexpr static std::size_t dimension{D};
1756 template<std::
size_t D>
1759 constexpr static std::size_t dimension{D};
1765 template<std::
size_t D>
1768 constexpr static std::size_t dimension{D};
1775 template<std::
size_t D>
1778 constexpr static std::size_t dimension{D};
1784 template<std::
size_t D>
1787 constexpr static std::size_t dimension{D};
1792 inline constexpr bool is_orthonormal_basis_v{
1794 typename B::orthonormal;
1795 requires std::same_as<typename B::orthonormal, std::true_type>;
1799 template<vector_space V>
1802 template<vector_space V>
1803 inline constexpr bool has_norm_v{
1805 { norm(v) } -> std::convertible_to<typename V::field_type>;
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>;
1825 template<std::
floating_po
int T, std::
size_t D,
class Arena=mathematical_arena>
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};
1835 template<basis Basis>
1836 requires is_orthonormal_basis_v<Basis>
1841 std::ranges::fold_left(
1842 std::views::zip(v.values(), w.values()),
1844 [](field_type f,
const auto& z){ return f + std::get<0>(z) * std::get<1>(z); }
1848 template<basis Basis>
1849 requires is_orthonormal_basis_v<Basis>
1853 return inner_product(v, w);
1856 template<basis Basis>
1857 requires is_orthonormal_basis_v<Basis>
1861 if constexpr(D == 1)
1863 return std::abs(v.value());
1867 return std::sqrt(inner_product(v, v));
1872 template<std::
floating_po
int T, std::
size_t D,
class Arena=mathematical_arena>
1877 using is_affine_space = std::true_type;
1878 using arena_type = Arena;
1881 template<std::
floating_po
int T,
class Arena=mathematical_arena>
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;
1893 inline constexpr bool has_arena_type_v{
1894 requires {
typename T::arena_type;}
1904 requires has_arena_type_v<T>
1907 using type = T::arena_type;
1910 template<convex_space T>
1911 requires (!has_arena_type_v<dual<T>>)
1914 using type = arena_type_of_t<T>;
1921 using type = std::common_type_t<arena_type_of_t<Ts>...>;
1924 template<std::
floating_po
int T, std::
size_t D, basis Basis,
class Origin,
class Arena=mathematical_arena>
1927 template<std::
floating_po
int T, std::
size_t D, basis Basis,
class Arena=mathematical_arena>
1935 template<free_module M>
1938 using is_basis = std::true_type;
1939 using free_module_type = M;
1942 template<free_module M>
1948 template<free_module M>
1957 template<auto Num, auto Den>
1963 template<std::
intmax_t Num, std::
intmax_t Den>
1966 using ratio_type = std::ratio<Num, Den>;
1972 template<
class Ratio>
1981 template<free_module M,
class Ratio, basis_for<M> ReferenceBasis>
1984 using reference_basis_type = ReferenceBasis;
1985 using is_basis = std::true_type;
1986 using free_module_type = M;
1989 template<std::
floating_po
int T, std::
size_t D,
class Arena=mathematical_arena>
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:1707
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
Definition: Spaces.hpp:668
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:946
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
Definition: Spaces.hpp:1290
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
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