Sequoia
Loading...
Searching...
No Matches
PhysicalValues.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
13
14namespace sequoia::physics
15{
16 template<physical_unit T>
17 struct is_invertible_unit : std::false_type {};
18
19 template<physical_unit T>
20 requires std::is_same_v<typename T::validator_type, std::identity>
21 || std::is_same_v<typename T::validator_type, maths::half_line_validator>
22 struct is_invertible_unit<T> : std::true_type
23 {};
24
25 template<physical_unit T>
26 using is_invertible_unit_t = is_invertible_unit<T>::type;
27
28 template<physical_unit T>
29 inline constexpr bool is_invertible_unit_v{is_invertible_unit<T>::value};
30}
31
32namespace sequoia::maths
33{
34 template<physics::physical_unit T>
35 requires physics::is_invertible_unit_v<T>
36 struct dual<T>
37 {
38 using validator_type = T::validator_type;
39 };
40
48 template<physics::physical_unit T>
49 requires (!physics::is_invertible_unit_v<T>)
50 struct dual<T>
51 {
52 using validator_type = void;
53 };
54}
55
56namespace sequoia::physics
57{
58 using namespace maths;
59
60 template<class... Ts>
62
63 template<class... Ts>
64 using reduced_validator_t = reduced_validator<Ts...>::type;
65
66 template<class T>
68 {
69 using type = T;
70 };
71
72 template<class T, class... Us>
73 struct reduced_validator<T, Us...>
74 {
75 using type = reduced_validator_t<T, reduced_validator_t<Us...>>;
76 };
77
78 struct no_unit_t
79 {
81 };
82
83 inline constexpr no_unit_t no_unit{};
84
85 template<physical_unit... Ts>
87 {
88 using validator_type = reduced_validator_t<typename Ts::validator_type...>;
89 };
90
91 template<class T>
92 inline constexpr bool has_arena_type_v{
93 requires { typename T::arena_type;}
94 };
95
96 template<class T>
98
99 template<class T>
100 using arena_type_of_t = arena_type_of<T>::type;
101
102 template<class T>
103 requires has_arena_type_v<T>
105 {
106 using type = T::arena_type;
107 };
108
109 template<convex_space T>
110 requires (!has_arena_type_v<dual<T>>)
112 {
113 using type = arena_type_of_t<T>;
114 };
115
116 template<convex_space... Ts>
117 requires (!has_arena_type_v<direct_product<Ts...>>)
119 {
120 using type = std::common_type_t<arena_type_of_t<Ts>...>;
121 };
122
124 template<class T>
125 struct reduction;
126
127 template<class T>
128 using reduction_t = reduction<T>::type;
129
130 template<class... Ts>
132
133 template<convex_space... Ts>
134 requires (free_module<Ts> || ...)
135 struct composite_space<Ts...>
136 {
137 using direct_product_t = direct_product<Ts...>;
139 using commutative_ring_type = commutative_ring_type_of_t<direct_product_t>;
140 using is_free_module = std::true_type;
142 constexpr static std::size_t dimension{std::ranges::max({dimension_of<Ts>...})};
143 };
144
145 template<convex_space... Ts>
146 requires (!affine_space<Ts> && ...)
147 struct composite_space<Ts...>
148 {
149 using direct_product_t = direct_product<Ts...>;
151 using free_module_type = composite_space<free_module_type_of_t<Ts>...>;
152 using is_convex_space = std::true_type;
153 using arena_type = arena_type_of<direct_product<Ts...>>;
154 };
155
156 template<physical_unit T, physical_unit U>
158 {
159 using type = impl::simplify_t<direct_product<T>, direct_product<U>>;
160 };
161
162 template<physical_unit... Ts, physical_unit U>
164 {
165 using type = impl::simplify_t<direct_product<Ts...>, direct_product<U>>;
166 };
167
168 template<physical_unit T, physical_unit... Us>
170 {
171 using type = impl::simplify_t<direct_product<Us...>, direct_product<T>>;
172 };
173
174 template<physical_unit... Ts, physical_unit... Us>
176 {
177 using type = impl::simplify_t<direct_product<Ts...>, direct_product<Us...>>;
178 };
179
180 template<convex_space T, convex_space U>
181 struct reduction<direct_product<T, U>>
182 {
183 using type = impl::simplify_t<direct_product<T>, direct_product<U>>;
184 };
185
186 template<convex_space... Ts, convex_space U>
188 {
189 using type = impl::simplify_t<direct_product<Ts...>, direct_product<U>>;
190 };
191
192 template<convex_space T, convex_space... Us>
194 {
195 using type = impl::simplify_t<direct_product<Us...>, direct_product<T>>;
196 };
197
198 template<convex_space... Ts, convex_space... Us>
200 {
201 using type = impl::simplify_t<direct_product<Ts...>, direct_product<Us...>>;
202 };
203
204 template<class T>
205 struct reduced_validator<T, std::identity>
206 {
207 using type = std::identity;
208 };
209
210 template<class T>
211 requires (!std::is_same_v<T, std::identity>)
213 {
214 using type = std::identity;
215 };
216
217 template<>
219 {
221 };
222
223 template<convex_space ValueSpace, physical_unit Unit>
224 inline constexpr bool has_distinguished_origin{
225 free_module<ValueSpace>
226 || (!affine_space<ValueSpace> && defines_half_line_v<typename Unit::validator_type>)
227 };
228
229 template<convex_space ValueSpace, physical_unit Unit, class Origin>
230 inline constexpr bool has_consistent_origin{
231 ( has_distinguished_origin<ValueSpace, Unit> && std::is_same_v<Origin, distinguished_origin>)
232 || (!has_distinguished_origin<ValueSpace, Unit> && !std::is_same_v<Origin, distinguished_origin>)
233 };
234
235 template<convex_space ValueSpace, validator_for<ValueSpace> Validator>
236 inline constexpr bool has_consistent_validator{
237 !affine_space<ValueSpace> || std::is_same_v<Validator, std::identity>
238 };
239
240 template<convex_space ValueSpace, physical_unit Unit>
241 inline constexpr bool has_consistent_unit{
242 !is_dual_v<Unit> || vector_space<ValueSpace> || (!affine_space<ValueSpace> && is_invertible_unit_v<dual_of_t<Unit>>)
243 };
244
245 template<convex_space ValueSpace, physical_unit Unit, basis_for<free_module_type_of_t<ValueSpace>> Basis, class Origin, validator_for<ValueSpace> Validator>
246 requires has_consistent_unit<ValueSpace, Unit>
247 && has_consistent_validator<ValueSpace, Validator>
248 && has_consistent_origin<ValueSpace, Unit, Origin>
249 class physical_value;
250
251 template<physical_unit Unit>
253
254 template<affine_space T>
256
257 template<convex_space ValueSpace, physical_unit Unit>
259
260 template<convex_space ValueSpace, physical_unit Unit>
261 requires (!has_distinguished_origin<ValueSpace, Unit>) && (!affine_space<ValueSpace>)
262 struct to_origin_type<ValueSpace, Unit>
263 {
265 };
266
267 template<convex_space ValueSpace, physical_unit Unit>
268 using to_origin_type_t = to_origin_type<ValueSpace, Unit>::type;
269
270 template<convex_space ValueSpace, physical_unit Unit>
271 requires has_distinguished_origin<ValueSpace, Unit>
272 struct to_origin_type<ValueSpace, Unit>
273 {
274 using type = distinguished_origin;
275 };
276
277 template<convex_space ValueSpace, physical_unit Unit>
278 requires (!has_distinguished_origin<ValueSpace, Unit> && affine_space<ValueSpace>)
279 struct to_origin_type<ValueSpace, Unit>
280 {
281 using type = implicit_affine_origin<ValueSpace>;
282 };
283
284 template<convex_space ValueSpace, physical_unit Unit, basis_for<free_module_type_of_t<ValueSpace>> Basis, class Origin, class Validator>
285 using to_coordinates_base_type
286 = coordinates_base<
287 ValueSpace,
288 Basis,
289 Origin,
290 Validator,
291 physical_value<free_module_type_of_t<ValueSpace>, Unit, Basis, distinguished_origin, std::identity>>;
292
293 template<class T>
294 inline constexpr bool has_base_space_v{
295 requires { typename T::base_space; }
296 };
297
298 template<convex_space T>
300 {
301 using type = T;
302 };
303
304 template<convex_space T>
305 using to_base_space_t = to_base_space<T>::type;
306
307 template<convex_space T>
308 requires has_base_space_v<T>
310 {
311 using type = T::base_space;
312 };
313
314 template<convex_space T>
316 {
317 using type = dual<T>;
318 };
319
320 template<convex_space T>
321 requires has_base_space_v<T>
322 struct to_base_space<dual<T>>
323 {
324 using type = dual<typename T::base_space>;
325 };
326
327 template<convex_space... Ts>
329 {
330 using sorted_direct_product_t = meta::stable_sort_t<direct_product<to_base_space_t<Ts>...>, meta::type_comparator>;
331 using type = impl::to_composite_space_t<reduction<impl::reduce_t<impl::count_and_combine_t<sorted_direct_product_t>>>>;
332 };
333
334 template<convex_space T, convex_space U>
335 inline constexpr bool have_compatible_base_spaces_v{
336 has_base_space_v<T> && has_base_space_v<U> && (free_module_type_of_t<T>::dimension == free_module_type_of_t<U>::dimension) && requires {
337 typename std::common_type<typename T::base_space, typename U::base_space>::type;
338 }
339 };
340
341 template<convex_space T, convex_space U>
343
344 template<convex_space T, convex_space U>
345 using to_displacement_space_t = to_displacement_space<T, U>::type;
346
347 template<convex_space T>
349 {
350 using type = free_module_type_of_t<T>;
351 };
352
353 template<convex_space T, convex_space U>
354 requires (!std::is_same_v<T, U>) && have_compatible_base_spaces_v<T, U>
356 {
357 using type = free_module_type_of_t<std::common_type_t<typename T::base_space, typename U::base_space>>;
358 };
359
360 template<class Basis1, class Basis2>
361 struct consistent_bases : std::false_type {};
362
363 template<class Basis1, class Basis2>
364 inline constexpr bool consistent_bases_v{consistent_bases<Basis1, Basis2>::value};
365
366 template<free_module M1, free_module M2>
368 {
369 template<free_module M>
371 };
372
373 template<class T, class U>
375
376 template<class T, class U>
377 using physical_value_product_t = physical_value_product<T, U>::type;
378
379 template<convex_space C>
380 inline constexpr bool is_1d_euclidean_v{
381 std::is_same_v<euclidean_vector_space<commutative_ring_type_of_t<C>, 1, arena_type_of_t<C>>, C>
382 || std::is_same_v<euclidean_half_space<commutative_ring_type_of_t<C>, arena_type_of_t<C>>, C>
383 };
384
385 template<
386 convex_space LHSValueSpace, physical_unit LHSUnit, basis_for<free_module_type_of_t<LHSValueSpace>> LHSBasis, class LHSValidator,
387 convex_space RHSValueSpace, physical_unit RHSUnit, basis_for<free_module_type_of_t<RHSValueSpace>> RHSBasis, class RHSValidator
388 >
389 requires consistent_bases_v<LHSBasis, RHSBasis> && (!is_1d_euclidean_v<LHSValueSpace> && !is_1d_euclidean_v<RHSValueSpace>)
392 {
393 using value_space_type = impl::to_composite_space_t<reduction_t<direct_product<LHSValueSpace, RHSValueSpace>>>;
394 using type
396 value_space_type,
397 impl::to_composite_space_t<reduction_t<direct_product<LHSUnit, RHSUnit>>>,
398 typename consistent_bases<LHSBasis, RHSBasis>::template rebind_type<free_module_type_of_t<value_space_type>>,
400 reduced_validator_t<LHSValidator, RHSValidator>
401 >;
402 };
403
404 template<
405 convex_space LHSValueSpace, physical_unit LHSUnit, basis_for<free_module_type_of_t<LHSValueSpace>> LHSBasis, class LHSValidator,
406 convex_space RHSValueSpace, physical_unit RHSUnit, basis_for<free_module_type_of_t<RHSValueSpace>> RHSBasis, class RHSValidator
407 >
408 requires consistent_bases_v<LHSBasis, RHSBasis> && is_1d_euclidean_v<LHSValueSpace>
409 struct physical_value_product<physical_value<LHSValueSpace, LHSUnit, LHSBasis, distinguished_origin, LHSValidator>,
410 physical_value<RHSValueSpace, RHSUnit, RHSBasis, distinguished_origin, RHSValidator>>
411 {
412 using type
414 RHSValueSpace,
415 RHSUnit,
416 RHSBasis,
418 reduced_validator_t<LHSValidator, RHSValidator>
419 >;
420 };
421
422 template<
423 convex_space LHSValueSpace, physical_unit LHSUnit, basis_for<free_module_type_of_t<LHSValueSpace>> LHSBasis, class LHSValidator,
424 convex_space RHSValueSpace, physical_unit RHSUnit, basis_for<free_module_type_of_t<RHSValueSpace>> RHSBasis, class RHSValidator
425 >
426 requires consistent_bases_v<LHSBasis, RHSBasis> && is_1d_euclidean_v<RHSValueSpace>
427 struct physical_value_product<physical_value<LHSValueSpace, LHSUnit, LHSBasis, distinguished_origin, LHSValidator>,
428 physical_value<RHSValueSpace, RHSUnit, RHSBasis, distinguished_origin, RHSValidator>>
429 {
430 using type
431 = physical_value<
432 LHSValueSpace,
433 LHSUnit,
434 LHSBasis,
435 distinguished_origin,
436 reduced_validator_t<LHSValidator, RHSValidator>
437 >;
438 };
439
440 template<
441 convex_space ValueSpace,
442 physical_unit Unit,
443 basis_for<free_module_type_of_t<ValueSpace>> Basis = canonical_right_handed_basis<free_module_type_of_t<ValueSpace>>,
444 class Origin = to_origin_type_t<ValueSpace, Unit>,
445 validator_for<ValueSpace> Validator = typename Unit::validator_type
446 >
447 requires has_consistent_unit<ValueSpace, Unit>
448 && has_consistent_validator<ValueSpace, Validator>
449 && has_consistent_origin<ValueSpace, Unit, Origin>
450 class physical_value final : public to_coordinates_base_type<ValueSpace, Unit, Basis, Origin, Validator>
451 {
452 public:
454 using space_type = ValueSpace;
455 using units_type = Unit;
456 using basis_type = Basis;
457 using origin_type = Origin;
458 using displacement_space_type = free_module_type_of_t<ValueSpace>;
459 using intrinsic_validator_type = Unit::validator_type;
460 using validator_type = Validator;
461 using ring_type = commutative_ring_type_of_t<ValueSpace>;
462 using value_type = ring_type;
463 using displacement_type = coordinates_type::displacement_coordinates_type;
464
465 constexpr static std::size_t dimension{displacement_space_type::dimension};
466 constexpr static std::size_t D{dimension};
467
468 constexpr static bool is_intrinsically_absolute{
469 (D == 1) && !affine_space<space_type> && defines_half_line_v<intrinsic_validator_type>
470 };
471
472 constexpr static bool is_effectively_absolute{is_intrinsically_absolute && std::is_same_v<Validator, intrinsic_validator_type>};
473 constexpr static bool has_identity_validator{coordinates_type::has_identity_validator};
474
475 template<convex_space RHSValueSpace, class RHSUnit, class RHSBasis, class RHSOrigin, class RHSValidator>
476 constexpr static bool is_composable_with{
477 consistent_bases_v<basis_type, RHSBasis>
478 && (is_intrinsically_absolute || vector_space<space_type>)
480 };
481
482 template<convex_space RHSValueSpace, class RHSUnit, class RHSBasis, class RHSOrigin, class RHSValidator>
483 constexpr static bool is_multipicable_with{
484 consistent_bases_v<basis_type, RHSBasis>
485 && is_composable_with<RHSValueSpace, RHSUnit, RHSBasis, RHSOrigin, RHSValidator>
487 };
488
489 template<convex_space RHSValueSpace, class RHSUnit, class RHSBasis, class RHSOrigin, class RHSValidator>
490 constexpr static bool is_divisible_with{
491 weak_field<ring_type>
492 && weak_field<commutative_ring_type_of_t<RHSValueSpace>>
493 && consistent_bases_v<basis_type, RHSBasis>
494 && is_composable_with<RHSValueSpace, RHSUnit, RHSBasis, RHSOrigin, RHSValidator>
496 };
497
498 constexpr physical_value() = default;
499
500 constexpr physical_value(value_type val, units_type) requires (D == 1)
501 : coordinates_type{val}
502 {}
503
504 constexpr physical_value(std::span<const value_type, D> val, units_type)
505 : coordinates_type{val}
506 {}
507
508 [[nodiscard]]
509 constexpr physical_value operator-() const noexcept(has_identity_validator)
510 requires (coordinates_type::has_distinguished_origin) && (!std::is_unsigned_v<ring_type>) && (!is_effectively_absolute)
511 {
512 return physical_value{utilities::to_array(this->values(), [](value_type t) { return -t; }), units_type{}};
513 }
514
515 using coordinates_type::operator+=;
516
517 template<convex_space OtherValueSpace, basis_for<free_module_type_of_t<OtherValueSpace>> OtherBasis>
518 requires is_intrinsically_absolute && (std::is_base_of_v<ValueSpace, OtherValueSpace>) && consistent_bases_v<basis_type, OtherBasis>
519 constexpr physical_value& operator+=(const physical_value<OtherValueSpace, Unit, OtherBasis, Origin, Validator>& other) noexcept(has_identity_validator)
520 {
521 this->apply_to_each_element(other.values(), [](value_type& lhs, value_type rhs){ lhs += rhs; });
522 return *this;
523 }
524
525 using coordinates_type::operator-=;
526
527 template<convex_space OtherValueSpace, basis_for<free_module_type_of_t<OtherValueSpace>> OtherBasis>
528 requires is_intrinsically_absolute && (std::is_base_of_v<ValueSpace, OtherValueSpace>) && consistent_bases_v<basis_type, OtherBasis>
529 constexpr physical_value& operator-=(const physical_value<OtherValueSpace, Unit, OtherBasis, Origin, Validator>& other) noexcept(has_identity_validator)
530 {
531 this->apply_to_each_element(other.values(), [](value_type& lhs, value_type rhs){ lhs -= rhs; });
532 return *this;
533 }
534
535 template<convex_space OtherValueSpace, basis_for<free_module_type_of_t<OtherValueSpace>> OtherBasis>
536 requires (!std::is_same_v<ValueSpace, OtherValueSpace>) && have_compatible_base_spaces_v<ValueSpace, OtherValueSpace> && consistent_bases_v<basis_type, OtherBasis>
537 [[nodiscard]]
538 friend constexpr auto operator+(const physical_value& lhs, const physical_value<OtherValueSpace, Unit, OtherBasis, Origin, Validator>& rhs)
539 {
540 using value_space_t = std::common_type_t<typename ValueSpace::base_space, typename OtherValueSpace::base_space>;
541 using physical_value_t
543 return physical_value_t{lhs.values(), units_type{}} += rhs;
544 }
545
546 template<class OtherValueSpace, basis_for<free_module_type_of_t<OtherValueSpace>> OtherBasis>
547 requires (!std::is_same_v<OtherValueSpace, displacement_space_type>)
548 && (std::is_same_v<ValueSpace, OtherValueSpace> || have_compatible_base_spaces_v<ValueSpace, OtherValueSpace>) && consistent_bases_v<basis_type, OtherBasis>
549 [[nodiscard]]
550 friend constexpr auto operator-(const physical_value& lhs, const physical_value<OtherValueSpace, Unit, OtherBasis, Origin, Validator>& rhs)
551 noexcept(has_identity_validator)
552 {
553 using disp_space_t = to_displacement_space_t<ValueSpace, OtherValueSpace>;
555 using disp_t = to_coordinates_base_type<disp_space_t, Unit, basis_t, Origin, Validator>::displacement_coordinates_type;
556 return[&] <std::size_t... Is>(std::index_sequence<Is...>) {
557 return disp_t{std::array{(lhs.values()[Is] - rhs.values()[Is])...}, units_type{}};
558 }(std::make_index_sequence<D>{});
559 }
560
561 template<convex_space RHSValueSpace, physical_unit RHSUnit, basis_for<free_module_type_of_t<RHSValueSpace>> RHSBasis, class RHSOrigin, class RHSValidator>
562 requires is_multipicable_with<RHSValueSpace, RHSUnit, RHSBasis, RHSOrigin, RHSValidator>
563 [[nodiscard]]
564 friend constexpr auto operator*(const physical_value& lhs,
566 {
567 using physical_value_t
568 = physical_value_product_t<
571 >;
572
573 using derived_units_type = physical_value_t::units_type;
574 return physical_value_t{lhs.value() * rhs.value(), derived_units_type{}};
575 }
576
577 template<convex_space RHSValueSpace, class RHSUnit, basis_for<free_module_type_of_t<RHSValueSpace>> RHSBasis, class RHSOrigin, class RHSValidator>
578 requires is_divisible_with<RHSValueSpace, RHSUnit, RHSBasis, RHSOrigin, RHSValidator>
579 [[nodiscard]]
580 friend constexpr auto operator/(const physical_value& lhs,
582 {
583 using physical_value_t
584 = physical_value_product_t<
587 >;
588 using derived_units_type = physical_value_t::units_type;
589 if constexpr(dimension == 1)
590 {
591 return physical_value_t{lhs.value() / rhs.value(), derived_units_type{}};
592 }
593 else
594 {
595 return[&] <std::size_t... Is>(std::index_sequence<Is...>) {
596 return physical_value_t{std::array{(lhs.values()[Is] / rhs.value())...}, derived_units_type{}};
597 }(std::make_index_sequence<D>{});
598 }
599 }
600
601 [[nodiscard]] friend constexpr auto operator/(value_type value, const physical_value& rhs)
602 requires ((D == 1) && (is_intrinsically_absolute || vector_space<ValueSpace>))
603 {
604 using physical_value_t = physical_value<dual_of_t<ValueSpace>, dual_of_t<Unit>, dual_of_t<basis_type>, origin_type, validator_type>;
605 using derived_units_type = physical_value_t::units_type;
606 return physical_value_t{value / rhs.value(), derived_units_type{}};
607 }
608
609 // Reduce *everything* to its base space on both sides of the equation; if these are the same, allow the conversion
610 template<class LoweredValueSpace, class OtherUnit, basis_for<free_module_type_of_t<LoweredValueSpace>> OtherBasis>
611 requires std::same_as<to_base_space_t<space_type>, to_base_space_t<LoweredValueSpace>> && consistent_bases_v<basis_type, OtherBasis>
612 [[nodiscard]]
614 {
615 using value_space_t = to_base_space_t<LoweredValueSpace>;
617 using physical_value_t = physical_value<to_base_space_t<LoweredValueSpace>, Unit, basis_t, origin_type, validator_type>;
618 if constexpr(dimension == 1)
619 {
620 return physical_value_t{this->value(), OtherUnit{}};
621 }
622 else
623 {
624 return [this] <std::size_t... Is>(std::index_sequence<Is...>) {
625 return physical_value_t{std::array{this->values()[Is]...}, OtherUnit{}};
626 }(std::make_index_sequence<D>{});
627 }
628 }
629 };
630
631 namespace sets::classical
632 {
633 template<class Arena>
634 struct masses
635 {
636 using arena_type = Arena;
637 };
638
639 template<class Arena>
641 {
642 using arena_type = Arena;
643 };
644
645 template<class Arena>
647 {
648 using arena_type = Arena;
649 };
650
651 template<class Arena>
652 struct times
653 {
654 using arena_type = Arena;
655 };
656
657 template<class Arena>
659 {
660 using arena_type = Arena;
661 };
662
663 template<class Arena>
665 {
666 using arena_type = Arena;
667 };
668
669 template<class Arena>
670 struct lengths
671 {
672 using arena_type = Arena;
673 };
674
675 template<class Arena>
676 struct angles
677 {
678 using arena_type = Arena;
679 };
680
681 template<class PhysicalValueSet>
683 {
684 using physical_value_set_type = PhysicalValueSet;
685 };
686 }
687
688 template<class Space>
690 {
691 constexpr static std::size_t dimension{Space::dimension};
693 using commutative_ring_type = Space::representation_type;
694 using is_free_module = std::true_type;
695 using arena_type = Space::arena_type;
696 };
697
698 template<class Space>
699 requires has_base_space_v<Space>
701 {
702 constexpr static std::size_t dimension{Space::dimension};
704 using commutative_ring_type = Space::representation_type;
705 using is_free_module = std::true_type;
707 using arena_type = Space::arena_type;
708 };
709
710 template<class PhysicalValueSet, arithmetic Rep, std::size_t D, class Derived>
712 {
713 constexpr static std::size_t dimension{D};
714 using set_type = PhysicalValueSet;
715 using representation_type = Rep;
717 using is_convex_space = std::true_type;
718 using arena_type = PhysicalValueSet::arena_type;
719 };
720
721 template<class PhysicalValueSet, arithmetic Rep, std::size_t D, class Derived>
723 {
724 constexpr static std::size_t dimension{D};
725 using set_type = PhysicalValueSet;
726 using representation_type = Rep;
728 using is_affine_space = std::true_type;
729 using arena_type = PhysicalValueSet::arena_type;
730 };
731
732 template<class PhysicalValueSet, arithmetic Rep, std::size_t D, class Derived>
734 {
735 constexpr static std::size_t dimension{D};
736 using set_type = PhysicalValueSet;
737 using representation_type = Rep;
738 using field_type = Rep;
739 using is_vector_space = std::true_type;
740 };
741
742 template<std::floating_point Rep, class Arena>
744 : physical_value_convex_space<sets::classical::masses<Arena>, Rep, 1, mass_space<Rep, Arena>>
745 {
746 using arena_type = Arena;
747 using base_space = mass_space;
748 };
749
750 template<std::floating_point Rep, class Arena>
752 : physical_value_convex_space<sets::classical::temperatures<Arena>, Rep, 1, temperature_space<Rep, Arena>>
753 {
754 using arena_type = Arena;
756 };
757
758 template<std::floating_point Rep, class Arena>
760 : physical_value_vector_space<sets::classical::electrical_currents<Arena>, Rep, 1, electrical_current_space<Rep, Arena>>
761 {
762 using arena_type = Arena;
764 };
765
766 template<std::floating_point Rep, class Arena>
767 struct angular_space : physical_value_vector_space<sets::classical::angles<Arena>, Rep, 1, angular_space<Rep, Arena>>
768 {
769 using arena_type = Arena;
771 };
772
773 template<arithmetic Rep, class Arena>
775 : physical_value_convex_space<sets::classical::lengths<Arena>, Rep, 1, length_space<Rep, Arena>>
776 {
777 using arena_type = Arena;
778 using base_space = length_space;
779 };
780
781 template<arithmetic Rep, class Arena>
782 struct width_space : length_space<Rep, Arena>
783 {
784 struct free_module_type : associated_displacement_space<width_space<Rep, Arena>> {};
785 };
786
787 template<arithmetic Rep, class Arena>
788 struct height_space : length_space<Rep, Arena>
789 {
790 struct free_module_type : associated_displacement_space<height_space<Rep, Arena>> {};
791 };
792
793 template<arithmetic Rep, class Arena>
795 : physical_value_convex_space<sets::classical::time_intervals<Arena>, Rep, 1, time_interval_space<Rep, Arena>>
796 {
797 using arena_type = Arena;
798 };
799
800 template<arithmetic Rep, class Arena>
801 struct time_space : physical_value_affine_space<sets::classical::times<Arena>, Rep, 1, time_space<Rep, Arena>>
802 {
803 using arena_type = Arena;
804 };
805
806 template<arithmetic Rep, std::size_t D, class Arena>
807 struct position_space : physical_value_affine_space<sets::classical::positions<Arena>, Rep, D, position_space<Rep, D, Arena>>
808 {
809 using arena_type = Arena;
810 };
811
813
814 template<physical_unit U>
815 inline constexpr bool has_symbol_v{
816 requires {
817 { U::symbol } -> std::convertible_to<std::string_view>; }
818 };
819
820 namespace si
821 {
822 namespace units
823 {
824 struct ampere_t
825 {
826 using validator_type = std::identity;
827 constexpr static std::string_view symbol{"A"};
828 };
829
831 {
833 constexpr static std::string_view symbol{"kg"};
834 };
835
836 struct metre_t
837 {
839 constexpr static std::string_view symbol{"m"};
840 };
841
842 struct second_t
843 {
845 constexpr static std::string_view symbol{"s"};
846 };
847
848 struct kelvin_t
849 {
851 constexpr static std::string_view symbol{"K"};
852 };
853
855 {
856 using validator_type = std::identity;
857 constexpr static std::string_view symbol{"C"};
858 };
859
860 struct radian_t
861 {
862 using validator_type = std::identity;
863 constexpr static std::string_view symbol{"rad"};
864 };
865
866
868 {
870 {
871 template<std::floating_point T>
872 [[nodiscard]]
873 constexpr T operator()(const T val) const
874 {
875 if(val < T(-273.15)) throw std::domain_error{std::format("Value {} less than -273.15", val)};
876
877 return val;
878 }
879 };
880
882 constexpr static std::string_view symbol{"degC"};
883 };
884
885 inline constexpr ampere_t ampere{};
886 inline constexpr kilogram_t kilogram{};
887 inline constexpr metre_t metre{};
888 inline constexpr second_t second{};
889 inline constexpr kelvin_t kelvin{};
890 inline constexpr coulomb_t coulomb{};
891 inline constexpr radian_t radian{};
892
893 inline constexpr celsius_t celsius{};
894 }
895
896 template<std::floating_point T, class Arena=implicit_common_arena>
897 using mass = physical_value<mass_space<T, Arena>, units::kilogram_t>;
898
899 template<std::floating_point T, class Arena=implicit_common_arena>
900 using length = physical_value<length_space<T, Arena>, units::metre_t>;
901
902 template<std::floating_point T, class Arena=implicit_common_arena>
903 using time_interval = physical_value<time_interval_space<T, Arena>, units::second_t>;
904
905 template<std::floating_point T, class Arena=implicit_common_arena>
906 using temperature = physical_value<temperature_space<T, Arena>, units::kelvin_t>;
907
908 template<std::floating_point T, class Arena=implicit_common_arena>
909 using electrical_current = physical_value<electrical_current_space<T, Arena>, units::ampere_t>;
910
911 template<std::floating_point T, class Arena=implicit_common_arena>
912 using angle = physical_value<angular_space<T, Arena>, units::radian_t>;
913
914 template<std::floating_point T, class Arena=implicit_common_arena>
915 using width = physical_value<width_space<T, Arena>, units::metre_t>;
916
917 template<std::floating_point T, class Arena=implicit_common_arena>
918 using height = physical_value<height_space<T, Arena>, units::metre_t>;
919
920 template<
921 std::floating_point T,
922 class Arena=implicit_common_arena,
923 class Origin=implicit_affine_origin<time_space<T, Arena>>
924 >
925 using time = physical_value<time_space<T, Arena>, units::second_t, canonical_right_handed_basis<free_module_type_of_t<time_space<T, Arena>>>, Origin, std::identity>;
926
927 template<
928 std::floating_point T,
929 std::size_t D,
930 class Arena = implicit_common_arena,
931 basis_for<free_module_type_of_t<position_space<T, D, Arena>>> Basis = canonical_right_handed_basis<free_module_type_of_t<position_space<T, D, Arena>>>,
932 class Origin = implicit_affine_origin<position_space<T, D, Arena>>
933 >
934 using position = physical_value<position_space<T, D, Arena>, units::metre_t, Basis, Origin, std::identity>;
935 }
936
937 template<vector_space ValueSpace, physical_unit Unit, class Basis, class Origin, validator_for<ValueSpace> Validator>
938 requires (dimension_of<ValueSpace> == 1)
939 [[nodiscard]]
940 constexpr physical_value<ValueSpace, Unit, Basis, Origin, Validator> abs(physical_value<ValueSpace, Unit, Basis, Origin, Validator> q)
941 {
942 return {std::abs(q.value()), Unit{}};
943 }
944
945 template<std::floating_point T, class Arena=implicit_common_arena>
946 [[nodiscard]]
947 constexpr T sin(physical_value<angular_space<T, Arena>, si::units::radian_t> theta)
948 {
949 return std::sin(theta.value());
950 }
951
952 template<std::floating_point T, class Arena=implicit_common_arena>
953 [[nodiscard]]
954 constexpr T cos(physical_value<angular_space<T, Arena>, si::units::radian_t> theta)
955 {
956 return std::cos(theta.value());
957 }
958
959 template<std::floating_point T, class Arena=implicit_common_arena>
960 [[nodiscard]]
961 constexpr T tan(physical_value<angular_space<T, Arena>, si::units::radian_t> theta)
962 {
963 return std::tan(theta.value());
964 }
965
966 template<class Arena=implicit_common_arena, std::floating_point T>
967 [[nodiscard]]
968 constexpr physical_value<angular_space<T, Arena>, si::units::radian_t> asin(T x)
969 {
970 return {std::asin(x), si::units::radian};
971 }
972
973 template<class Arena=implicit_common_arena, std::floating_point T>
974 [[nodiscard]]
975 constexpr physical_value<angular_space<T, Arena>, si::units::radian_t> acos(T x)
976 {
977 return {std::acos(x), si::units::radian};
978 }
979
980 template<class Arena=implicit_common_arena, std::floating_point T>
981 [[nodiscard]]
982 constexpr physical_value<angular_space<T, Arena>, si::units::radian_t> atan(T x)
983 {
984 return {std::atan(x), si::units::radian};
985 }
986
987 template<
988 convex_space ValueSpace,
989 physical_unit Unit,
990 validator_for<ValueSpace> Validator=typename Unit::validator_type
991 >
992 requires has_consistent_validator<ValueSpace, Validator>
993 using quantity = physical_value<ValueSpace, Unit, canonical_right_handed_basis<free_module_type_of_t<ValueSpace>>, to_origin_type_t<ValueSpace, Unit>, Validator>;
994
995
996 template<std::floating_point Rep, class Arena=implicit_common_arena>
997 using euclidean_1d_vector_quantity = quantity<euclidean_vector_space<Rep, 1, Arena>, no_unit_t, std::identity>;
998
999 template<std::floating_point Rep, class Arena=implicit_common_arena>
1000 using euclidean_half_line_quantity = quantity<euclidean_half_space<Rep, Arena>, no_unit_t>;
1001}
1002
1003// TO DO: extend this
1004template<
1008>
1009 requires (sequoia::maths::dimension_of<ValueSpace> == 1)
1011{
1012 constexpr auto parse(auto& ctx)
1013 {
1014 return ctx.begin();
1015 }
1016
1017 auto format(const sequoia::physics::quantity<ValueSpace, Unit, Validator>& q, auto& ctx) const
1018 {
1019 if constexpr(sequoia::physics::has_symbol_v<Unit>)
1020 return std::format_to(ctx.out(), "{} {}", q.value(), Unit::symbol);
1021 else
1022 return std::format_to(ctx.out(), "{}", q.value());
1023 }
1024};
1025
Class designed for inheritance by concerete coordinate types.
Definition: Spaces.hpp:1076
Definition: PhysicalValues.hpp:451
concept for convex spaces
Definition: Spaces.hpp:517
concept to check if a validator is compatible with a convex space.
Definition: Spaces.hpp:676
Definition: PhysicalValuesDetails.hpp:33
Right-handed bases for arbitrary D, build recursively from 1D.
Definition: Spaces.hpp:1531
Definition: Spaces.hpp:774
Definition: Spaces.hpp:763
Type to indicate a distinguished origin, relevant for free modules.
Definition: Spaces.hpp:1010
Specialization for units, such as degrees Celsius, for which the corresponding quantity cannot be inv...
Definition: PhysicalValues.hpp:37
Primary class template for defining duals.
Definition: Spaces.hpp:896
A validator the the half line.
Definition: Spaces.hpp:703
Definition: PhysicalValues.hpp:768
Definition: PhysicalValues.hpp:97
Definition: PhysicalValues.hpp:690
Definition: PhysicalValues.hpp:131
Definition: PhysicalValues.hpp:87
Definition: PhysicalValues.hpp:361
Definition: PhysicalValues.hpp:761
Definition: PhysicalValues.hpp:790
Definition: PhysicalValues.hpp:789
Definition: PhysicalValues.hpp:255
Definition: PhysicalValues.hpp:812
Definition: PhysicalValues.hpp:17
Definition: PhysicalValues.hpp:776
Definition: PhysicalValues.hpp:745
Definition: PhysicalValues.hpp:79
Definition: PhysicalValues.hpp:723
Definition: PhysicalValues.hpp:712
Definition: PhysicalValues.hpp:374
Definition: PhysicalValues.hpp:734
Definition: PhysicalValues.hpp:808
Definition: PhysicalValues.hpp:61
Definition: PhysicalValues.hpp:125
Definition: PhysicalValues.hpp:677
Definition: PhysicalValues.hpp:683
Definition: PhysicalValues.hpp:671
Definition: PhysicalValues.hpp:635
Definition: PhysicalValues.hpp:665
Definition: PhysicalValues.hpp:641
Definition: PhysicalValues.hpp:659
Definition: PhysicalValues.hpp:653
Definition: PhysicalValues.hpp:825
Definition: PhysicalValues.hpp:870
Definition: PhysicalValues.hpp:868
Definition: PhysicalValues.hpp:855
Definition: PhysicalValues.hpp:849
Definition: PhysicalValues.hpp:831
Definition: PhysicalValues.hpp:837
Definition: PhysicalValues.hpp:861
Definition: PhysicalValues.hpp:843
Definition: PhysicalValues.hpp:753
Definition: PhysicalValues.hpp:796
Definition: PhysicalValues.hpp:802
Definition: PhysicalValues.hpp:300
Definition: PhysicalValues.hpp:342
Definition: PhysicalValues.hpp:258
Definition: PhysicalValues.hpp:252
Definition: PhysicalValues.hpp:784
Definition: PhysicalValues.hpp:783