Sequoia
Loading...
Searching...
No Matches
PhysicalValuesDetails.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
14
15namespace sequoia::physics
16{
17 using namespace maths;
18
19 template<class Space>
20 struct associated_displacement_space;
21
22 template<class Space>
23 struct is_associated_displacement_space : std::false_type {};
24
25 template<class Space>
27
28 template<class Space>
29 using is_associated_displacement_space_t = is_associated_displacement_space<Space>::type;
30
31 template<class Space>
32 inline constexpr bool is_associated_displacement_space_v{is_associated_displacement_space<Space>::value};
33
34 template<class T>
35 inline constexpr bool identifies_as_unit_v{
36 requires {
37 typename T::is_unit;
38 requires std::convertible_to<typename T::is_unit, std::true_type>;
39 }
40 };
41
42 template<class T>
44 = identifies_as_unit_v<T>
45 && requires { typename T::validator_type; };
46
47 template<class... Ts>
48 struct composite_space;
49
50 template<physical_unit... Ts>
51 struct composite_unit;
52
53 template<class T>
54 struct reduction;
55
56 struct no_unit_t;
57}
58
59namespace sequoia::meta
60{
61 template<class T, class U>
62 requires (!std::is_same_v<T, U>)
63 struct type_comparator<maths::dual<T>, U> : std::bool_constant<type_name<T>() < type_name<U>()>
64 {};
65
66 template<class T, class U>
67 requires (!std::is_same_v<T, U>) && (!physics::is_associated_displacement_space_v<T>) && (!physics::is_associated_displacement_space_v<U>)
68 struct type_comparator<T, maths::dual<U>> : std::bool_constant<type_name<T>() < type_name<U>()>
69 {};
70
71 template<class T, class U>
72 struct type_comparator<maths::dual<T>, maths::dual<U>> : std::bool_constant<type_name<T>() < type_name<U>()>
73 {};
74
75 template<class T, class U>
76 requires (!maths::is_dual_v<U>)
77 struct type_comparator<physics::associated_displacement_space<T>, U> : std::bool_constant<type_name<T>() < type_name<U>()>
78 {};
79
80 template<class T, class U>
81 requires (!maths::is_dual_v<T>)
82 struct type_comparator<T, physics::associated_displacement_space<U>> : std::bool_constant<type_name<T>() < type_name<U>()>
83 {};
84
85 template<class T, class U>
86 requires (!std::is_same_v<physics::associated_displacement_space<T>, U>) && (!physics::is_associated_displacement_space_v<U>)
87 struct type_comparator<physics::associated_displacement_space<T>, maths::dual<U>> : std::bool_constant<type_name<T>() < type_name<U>()>
88 {};
89
90 template<class T, class U>
91 requires (!std::is_same_v<T, physics::associated_displacement_space<U>>)
92 struct type_comparator<maths::dual<T>, physics::associated_displacement_space<U>> : std::bool_constant<type_name<T>() < type_name<U>()>
93 {};
94
95 template<class T, class U>
96 requires (!std::is_same_v<physics::associated_displacement_space<T>, U>)
97 struct type_comparator<maths::dual<physics::associated_displacement_space<T>>, U>
98 : std::bool_constant<type_name<T>() < type_name<U>()>
99 {};
100
101 template<class T, class U>
102 requires (!std::is_same_v<T, physics::associated_displacement_space<U>>) && (!physics::is_associated_displacement_space_v<T>)
103 struct type_comparator<T, maths::dual<physics::associated_displacement_space<U>>>
104 : std::bool_constant<type_name<T>() < type_name<U>()>
105 {};
106
107 template<class T, class U>
108 struct type_comparator<physics::associated_displacement_space<T>, physics::associated_displacement_space<U>>
109 : std::bool_constant<type_name<T>() < type_name<U>()>
110 {};
111
112 template<class T, class U>
113 struct type_comparator<maths::dual<physics::associated_displacement_space<T>>, maths::dual<physics::associated_displacement_space<U>>>
114 : std::bool_constant<type_name<T>() < type_name<U>()>
115 {};
116
117 // Ordering is T, associated_displacement_space<T>, dual<T>, dual<associated_displacement_space<T>>
118 template<class T>
119 struct type_comparator<T, maths::dual<T>> : std::true_type
120 {};
121
122 template<class T>
123 struct type_comparator<maths::dual<T>, T> : std::false_type
124 {};
125
126 template<class T>
127 struct type_comparator<T, physics::associated_displacement_space<T>> : std::true_type
128 {};
129
130 template<class T>
131 struct type_comparator<physics::associated_displacement_space<T>, T> : std::false_type
132 {};
133
134 template<class T>
135 struct type_comparator<T, maths::dual<physics::associated_displacement_space<T>>> : std::true_type
136 {};
137
138 template<class T>
139 struct type_comparator<maths::dual<physics::associated_displacement_space<T>>, T> : std::false_type
140 {};
141
142 template<class T>
143 struct type_comparator<physics::associated_displacement_space<T>, maths::dual<T>> : std::true_type
144 {};
145
146 template<class T>
147 struct type_comparator<maths::dual<T>, physics::associated_displacement_space<T>> : std::false_type
148 {};
149
150 template<class T>
151 struct type_comparator<maths::dual<T>, maths::dual<physics::associated_displacement_space<T>>> : std::true_type
152 {};
153
154 template<class T>
155 struct type_comparator<maths::dual<physics::associated_displacement_space<T>>, maths::dual<T>> : std::false_type
156 {};
157}
158
159namespace sequoia::physics::impl
160{
161 using namespace maths;
162
163 template<class T, int I>
164 struct type_counter {};
165
167 template<class...>
168 struct count_and_combine {};
169
170 template<class... Ts>
171 using count_and_combine_t = count_and_combine<Ts...>::type;
172
173 template<>
174 struct count_and_combine<direct_product<>>
175 {
176 using type = direct_product<>;
177 };
178
179 template<class T>
180 struct count_and_combine<T>
181 {
182 using type = direct_product<type_counter<T, 1>>;
183 };
184
185 template<class T>
186 struct count_and_combine<direct_product<T>>
187 {
188 using type = direct_product<type_counter<T, 1>>;
189 };
190
191 template<class T, class... Ts>
192 struct count_and_combine<direct_product<T, Ts...>>
193 : count_and_combine<direct_product<Ts...>, count_and_combine_t<T>>
194 {};
195
196 template<class T, class... Us, int... Is>
197 struct count_and_combine<direct_product<T>, direct_product<type_counter<Us, Is>...>>
198 : count_and_combine<T, direct_product<type_counter<Us, Is>...>>
199 {};
200
201 template<class T, class... Ts, class... Us, int... Is>
202 requires (sizeof...(Ts) > 0)
203 struct count_and_combine<direct_product<T, Ts...>, direct_product<type_counter<Us, Is>...>>
204 : count_and_combine<direct_product<Ts...>, count_and_combine_t<T, direct_product<type_counter<Us, Is>...>>>
205 {};
206
207 template<class S, class T, int I, class... Ts, int... Is>
208 requires (!is_direct_product_v<S> && !is_dual_v<S> && !std::is_same_v<S, T> && !std::is_same_v<S, associated_displacement_space<T>>)
209 struct count_and_combine<S, direct_product<type_counter<T, I>, type_counter<Ts, Is>...>>
210 {
211 using type = direct_product<type_counter<S, 1>, type_counter<T, I>, type_counter<Ts, Is>...>;
212 };
213
214 template<class S, class T, int I, class... Ts, int... Is>
215 requires (!std::is_same_v<S, T> && !std::is_same_v<S, dual_of_t<T>> && !std::is_same_v<S, associated_displacement_space<T>> && !std::is_same_v<S, dual_of_t<associated_displacement_space<T>>> && !std::is_same_v<S, associated_displacement_space<dual_of_t<T>>>
216 && !std::is_same_v<T, dual_of_t<S>> && !std::is_same_v<T, associated_displacement_space<S>> && !std::is_same_v<T, dual_of_t<associated_displacement_space<S>>> && !std::is_same_v<T, associated_displacement_space<dual_of_t<S>>>)
217 struct count_and_combine<dual<S>, direct_product<type_counter<T, I>, type_counter<Ts, Is>...>>
218 {
219 using type = direct_product<type_counter<dual<S>, 1>, type_counter<T, I>, type_counter<Ts, Is>...>;
220 };
221
222 template<class T, int I, class... Ts, int... Is>
223 struct count_and_combine<T, direct_product<type_counter<T, I>, type_counter<Ts, Is>...>>
224 {
225 using type = direct_product<type_counter<T, I+1>, type_counter<Ts, Is>...>;
226 };
227
228 template<class T, int I, class... Ts, int... Is>
229 struct count_and_combine<dual<T>, direct_product<type_counter<T, I>, type_counter<Ts, Is>...>>
230 {
231 using type = direct_product<type_counter<T, I-1>, type_counter<Ts, Is>...>;
232 };
233
234 // TO DO: associated_displacement_space is specific to physical quantities so
235 // doesn't recognize euc_vec as the displacement space of euc_half
236
238 template<class T, int I, class... Ts, int... Is>
239 struct count_and_combine<associated_displacement_space<T>, direct_product<type_counter<T, I>, type_counter<Ts, Is>...>>
240 {
241 using type = direct_product<type_counter<associated_displacement_space<T>, I+1>, type_counter<Ts, Is>...>;
242 };
243
245 template<class T, int I, class... Ts, int... Is>
246 struct count_and_combine<dual<associated_displacement_space<T>>, direct_product<type_counter<T, I>, type_counter<Ts, Is>...>>
247 {
248 using type = direct_product<type_counter<associated_displacement_space<T>, I-1>, type_counter<Ts, Is>...>;
249 };
250
252 template<class T, int I, class... Ts, int... Is>
253 struct count_and_combine<dual<T>, direct_product<type_counter<associated_displacement_space<T>, I>, type_counter<Ts, Is>...>>
254 {
255 using type = direct_product<type_counter<associated_displacement_space<T>, I-1>, type_counter<Ts, Is>...>;
256 };
257
259 template<class T, int I, class... Ts, int... Is>
260 struct count_and_combine<dual<associated_displacement_space<T>>, direct_product<type_counter<dual<T>, I>, type_counter<Ts, Is>...>>
261 {
262 using type = direct_product<type_counter<dual<associated_displacement_space<T>>, I+1>, type_counter<Ts, Is>...>;
263 };
264
268 template<class...>
269 struct unpack {};
270
271 template<class... Ts>
272 using unpack_t = unpack<Ts...>::type;
273
274 template<class T, int I>
275 requires (I > 0)
276 struct unpack<type_counter<T, I>> : unpack<type_counter<T, I - 1>, direct_product<T>>
277 {};
278
279 template<class T, int I>
280 requires (I < 0)
281 struct unpack<type_counter<T, I>> : unpack<type_counter<T, I + 1>, direct_product<dual<T>>>
282 {};
283
284 template<class T, int I, class... Ts>
285 requires (I > 0)
286 struct unpack<type_counter<T, I>, direct_product<Ts...>> : unpack<type_counter<T, I - 1>, direct_product<T, Ts...>>
287 {};
288
289 template<class T, int I, class... Ts>
290 requires (I < 0)
291 struct unpack<type_counter<T, I>, direct_product<Ts...>> : unpack<type_counter<T, I + 1>, direct_product<dual<T>, Ts...>>
292 {};
293
294 template<class T, class... Ts>
295 struct unpack<type_counter<T, 0>, direct_product<Ts...>>
296 {
297 using type = direct_product<Ts...>;
298 };
299
300 template<class... Ts, int... Is>
301 struct unpack<direct_product<type_counter<Ts, Is>...>>
302 : meta::flatten<direct_product<unpack_t<type_counter<Ts, Is>>...>>
303 {
304 };
305
306 template<class>
307 struct potentially_prunable : std::false_type {};
308
309 template<class T>
310 inline constexpr bool potentially_prunable_v{potentially_prunable<T>::value};
311
312 template<class T>
313 struct potentially_prunable<type_counter<T, 0>> : std::true_type
314 {
315 };
316
317 template<class T, class Arena, int I>
318 requires (I != 0)
319 struct potentially_prunable<type_counter<euclidean_vector_space<T, 1, Arena>, I>> : std::true_type
320 {
321 };
322
323 template<class T, class Arena, int I>
324 requires (I != 0)
325 struct potentially_prunable<type_counter<dual<euclidean_vector_space<T, 1, Arena>>, I>> : std::true_type
326 {
327 };
328
329 template<class T, class Arena, int I>
330 requires (I != 0)
331 struct potentially_prunable<type_counter<euclidean_half_space<T, Arena>, I>> : std::true_type
332 {
333 };
334
335 template<class T, class Arena, int I>
336 requires (I != 0)
337 struct potentially_prunable<type_counter<dual<euclidean_half_space<T, Arena>>, I>> : std::true_type
338 {
339 };
340
341 template<physics::physical_unit U, int I>
342 requires std::derived_from<U, no_unit_t> && (I != 0)
343 struct potentially_prunable<type_counter<U, I>> : std::true_type
344 {
345 };
346
347 template<class T>
348 struct not_potentially_prunable : std::negation<potentially_prunable<T>> {};
349
351 template<class...>
352 struct reduce;
353
354 template<class... Ts>
355 using reduce_t = reduce<Ts...>::type;
356
357 template<physical_unit U>
358 struct reduce<direct_product<type_counter<U, 0>>>
359 {
360 using type = direct_product<no_unit_t>;
361 };
362
363 template<physical_unit U, int I>
364 requires std::derived_from<U, no_unit_t> && (I > 0)
365 struct reduce<direct_product<type_counter<U, I>>>
366 {
367 using type = direct_product<U>;
368 };
369
370 template<physics::physical_unit... Ts, int... Is>
371 struct reduce<direct_product<type_counter<Ts, Is>...>>
372 {
373 using type = unpack_t<meta::filter_by_trait_t<direct_product<type_counter<Ts, Is>...>, not_potentially_prunable>>;
374 };
375
376 template<convex_space... Ts, int... Is>
377 struct reduce<direct_product<type_counter<Ts, Is>...>>
378 {
379 // TO DO; potential problem here if reducible modules are floating-point but everything else is integral
380 // Depends where we do any arithmetic promotions; ideally below using common_type
381 // TO DO: At some point this may need generalizing to finite segments with a distinguished origin
382 constexpr static bool anyOfNotReducibleFreeModule {(( free_module<Ts> && !potentially_prunable_v<type_counter<Ts, Is>>) || ...)};
383 constexpr static bool anyOfNotReducibleHalfLine {(( is_non_negative_orthant_v<Ts> && !potentially_prunable_v<type_counter<Ts, Is>>) || ...)};
384 constexpr static bool allOfNotReducibleOrNotFreeModule{((!free_module<Ts> || !potentially_prunable_v<type_counter<Ts, Is>>) && ...)};
385 constexpr static bool allOfNotReducibleOrNotHalfLine {((!is_non_negative_orthant_v<Ts> || !potentially_prunable_v<type_counter<Ts, Is>>) && ...)};
386
387 using filtered_t = meta::filter_by_trait_t<direct_product<type_counter<Ts, Is>...>, not_potentially_prunable>;
388
389 using unpacked_t = unpack_t<filtered_t>;
390
391 constexpr static bool anyFreeModule{(free_module<Ts> || ...)};
392
393 using root_space_t =
394 std::conditional_t<
395 anyFreeModule,
396 direct_product<euclidean_vector_space<std::common_type_t<commutative_ring_type_of_t<Ts>...>, 1, std::common_type_t<arena_type_of_t<Ts>...>>>,
397 direct_product<euclidean_half_space<std::common_type_t<commutative_ring_type_of_t<Ts>...>, std::common_type_t<arena_type_of_t<Ts>...>>>
398 >;
399
400 using type
401 = std::conditional_t<
402 anyOfNotReducibleFreeModule || (allOfNotReducibleOrNotFreeModule && (anyOfNotReducibleHalfLine || allOfNotReducibleOrNotHalfLine)),
403 unpacked_t,
404 meta::merge_t<unpacked_t, root_space_t, meta::type_comparator>
405 >;
406 };
407
409 template<class...>
410 struct simplify;
411
412 template<class... Ts>
413 using simplify_t = simplify<Ts...>::type;
414
415 template<class... Ts>
416 struct simplify<direct_product<Ts...>>
417 {
418 using type = reduction<meta::reverse_t<reduce_t<count_and_combine_t<meta::stable_sort_t<direct_product<Ts...>, meta::type_comparator>>>>>;
419 };
420
421 // Assume direct_products are already sorted
422 template<class... Ts, class... Us>
423 struct simplify<direct_product<Ts...>, direct_product<Us...>>
424 {
425 using type = reduction<meta::reverse_t<reduce_t<count_and_combine_t<meta::merge_t<direct_product<Ts...>, direct_product<Us...>, meta::type_comparator>>>>>;
426 };
427
428 template<class T>
429 struct to_composite_space;
430
431 template<convex_space... Ts>
432 struct to_composite_space<reduction<direct_product<Ts...>>>
433 {
434 using type = composite_space<Ts...>;
435 };
436
437 template<physical_unit... Ts>
438 struct to_composite_space<reduction<direct_product<Ts...>>>
439 {
440 using type = composite_unit<Ts...>;
441 };
442
443 template<class T>
444 struct to_composite_space<reduction<direct_product<T>>>
445 {
446 using type = T;
447 };
448
449 template<class T>
450 using to_composite_space_t = to_composite_space<T>::type;
451}
452
453namespace sequoia::maths
454{
455 template<convex_space... Ts>
456 struct dual_of<physics::composite_space<Ts...>>
457 {
458 using type = physics::composite_space<dual_of_t<Ts>...>;
459 };
460
461 template<physics::physical_unit... Ts>
462 struct dual_of<physics::composite_unit<Ts...>>
463 {
464 using type = physics::composite_unit<dual_of_t<Ts>...>;
465 };
466}
Abstractions pertaining to vector spaces, affine spaces and their generalizations.
Definition: PhysicalValuesDetails.hpp:44
Primary class template for defining duals.
Definition: Spaces.hpp:1041
Definition: PhysicalValues.hpp:769
Definition: PhysicalValues.hpp:142
Definition: PhysicalValues.hpp:129
Definition: PhysicalValuesDetails.hpp:23
Definition: PhysicalValues.hpp:53
Definition: PhysicalValues.hpp:136