measures/
define_measure_types.rs

1#[macro_export]
2macro_rules! if_all_true {
3    ( { } $( $fragment:item )* ) => { $( $fragment )* };
4    ( { false $($rest:tt)* } $( $fragment:item )* ) => { };
5    ( { true $($rest:tt)* } $( $fragment:item )* ) => { measures::if_all_true! { { $($rest)* } $( $fragment )* } };
6}
7
8#[macro_export]
9macro_rules! define_scalar_property {
10    ( $scalar_property:tt ) => {};
11}
12
13#[macro_export]
14macro_rules! define_vector_property {
15    // ( $vector_property:tt ) => {};
16    ( $property_name:ident [ $( $unit:tt )* ]) => {};
17}
18
19#[macro_export]
20macro_rules! define_measure_types_aux {
21    // Empty case
22    {
23        ,
24
25        with_points: $with_points:tt,
26        with_directions: $with_directions:tt,
27        with_2d: $with_2d:tt,
28        with_3d: $with_3d:tt,
29        with_transformations: $with_transformations:tt,
30        exact: $exact:tt,
31        with_approx: $with_approx:tt,
32        with_correlation: $with_correlation:tt;
33
34        $(
35            scalar_properties [
36                $(
37                    $scalar_prop:ident [
38                        $(
39                            $scalar_unit:ident {
40                                $($scalar_key:ident : $scalar_val:expr),* $(,)?
41                            }
42                        )*
43                    ]
44                )*
45            ]
46        )?
47
48        $(
49            vector_properties [
50                $(
51                    $vector_prop:ident [
52                        $(
53                            $vector_unit:ident {
54                                $($vector_key:ident : $vector_val:expr),* $(,)?
55                            }
56                        )*
57                    ]
58                )*
59            ]
60        )?
61
62        $(
63            angle_measurement_units [
64                $(
65                    $angle_unit:ident {
66                        $($angle_key:ident : $angle_val:expr),* $(,)?
67                    }
68                )*
69            ]
70        )?
71
72        $(
73            relationships [
74                $(
75                    $unit1:ident $dim1:tt == $unit2:ident $dim2:tt $op:tt $unit3:ident $dim3:tt $(,)?
76                )*
77            ]
78        )?
79    } => {
80        use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
81        use measures::{
82            dimensionless::{Dimensionless, One},
83            angle::{Angle, Radian},
84            traits::{
85                AngleMeasurementUnit, ArithmeticOps, LossyFrom, MeasurementUnit, Sqrt, VectorProperty, Trigonometry,
86            },
87        };
88        use core::fmt;
89        use core::marker::PhantomData;
90
91        measures::inner_define_measure! { $with_approx }
92        measures::if_all_true! { { $with_approx }
93            measures::inner_define_approx_measure! { $exact }
94        }
95        measures::if_all_true! { { $with_points }
96            measures::inner_define_measure_point! { $with_approx }
97        }
98        measures::if_all_true! { { $with_approx $with_points }
99            measures::inner_define_approx_measure_point ! { $exact }
100        }
101        measures::if_all_true! { { $exact $with_directions }
102            measures::inner_define_unsigned_direction! { $with_points }
103        }
104        measures::if_all_true! { { $exact $with_directions }
105            measures::inner_define_signed_direction! { $with_points }
106        }
107        measures::if_all_true! { { $with_2d }
108            measures::inner_define_measure_2d! { $with_points $with_directions $with_approx }
109        }
110        measures::if_all_true! { { $with_2d $with_points $exact }
111            measures::inner_define_measure_point_2d! { $with_approx }
112        }
113        measures::if_all_true! { { $with_3d }
114            measures::inner_define_measure_3d! { $with_approx }
115        }
116        measures::if_all_true! { { $with_points $with_3d }
117            measures::inner_define_measure_point_3d! { $with_approx }
118        }
119        measures::if_all_true! { { $with_2d $with_transformations }
120            measures::inner_define_linear_map_2d! {}
121        }
122        measures::if_all_true! { { $with_3d $with_transformations }
123            measures::inner_define_linear_map_3d! {}
124        }
125        measures::if_all_true! { { $with_2d $with_transformations $with_points }
126            measures::inner_define_affine_map_2d! {}
127        }
128        measures::if_all_true! { { $with_3d $with_transformations $with_points }
129            measures::inner_define_affine_map_3d! {}
130        }
131
132        measures::if_all_true! { { $with_approx $with_2d }
133            measures::inner_define_approx_measure_2d! { $exact }
134        }
135        measures::if_all_true! { { $with_approx $with_points $with_2d }
136            measures::inner_define_approx_measure_point_2d! { $exact }
137        }
138        measures::if_all_true! { { $with_approx $with_3d }
139            measures::inner_define_approx_measure_3d! { $exact }
140        }
141        measures::if_all_true! { { $with_approx $with_points $with_3d }
142            measures::inner_define_approx_measure_point_3d! { $exact }
143        }
144
145        // `scalar_properties` section
146        $(
147            $(
148                measures::measurement_scalar_property! { $scalar_prop }
149                $(
150                    measures::measurement_unit! {
151                        name: $scalar_unit,
152                        property: $scalar_prop,
153                        $(
154                            $scalar_key: $scalar_val,
155                        )*
156                        with_2d: $with_2d,
157                        with_3d: $with_3d,
158                        vector: false,
159                    }
160                )*
161            )*
162        )?
163
164        // `vector_properties` section
165        $(
166            $(
167                measures::measurement_vector_property! { $vector_prop }
168                $(
169                    measures::measurement_unit! {
170                        name: $vector_unit,
171                        property: $vector_prop,
172                        $(
173                            $vector_key: $vector_val,
174                        )*
175                        with_2d: $with_2d,
176                        with_3d: $with_3d,
177                        vector: true,
178                    }
179                )*
180            )*
181        )?
182
183        // `angle_measurement_units` section
184        $(
185            $(
186                measures::angle_measurement_unit! {
187                    name: $angle_unit,
188                    $(
189                        $angle_key: $angle_val,
190                    )*
191                }
192            )*
193        )?
194
195        // `relationships` section
196        $(
197            $(
198                measures::define_units_relationship! {
199                    $exact $with_approx $with_correlation,
200                    $unit1 $dim1 == $unit2 $dim2 $op $unit3 $dim3
201                }
202            )*
203        )?
204    };
205
206    // First option is "with_points"
207    {
208        with_points $( $flag:ident )*,
209
210        with_points: false,
211        with_directions: $with_directions:tt,
212        with_2d: $with_2d:tt,
213        with_3d: $with_3d:tt,
214        with_transformations: $with_transformations:tt,
215        exact: $exact:tt,
216        with_approx: $with_approx:tt,
217        with_correlation: $with_correlation:tt;
218
219        $(
220            scalar_properties [
221                $(
222                    $scalar_prop:ident [
223                        $(
224                            $scalar_unit:ident {
225                                $($scalar_key:ident : $scalar_val:expr),* $(,)?
226                            }
227                        )*
228                    ]
229                )*
230            ]
231        )?
232
233        $(
234            vector_properties [
235                $(
236                    $vector_prop:ident [
237                        $(
238                            $vector_unit:ident {
239                                $($vector_key:ident : $vector_val:expr),* $(,)?
240                            }
241                        )*
242                    ]
243                )*
244            ]
245        )?
246
247        $(
248            angle_measurement_units [
249                $(
250                    $angle_unit:ident {
251                        $($angle_key:ident : $angle_val:expr),* $(,)?
252                    }
253                )*
254            ]
255        )?
256
257        $(
258            relationships [
259                $(
260                    $unit1:ident $dim1:tt == $unit2:ident $dim2:tt $op:tt $unit3:ident $dim3:tt $(,)?
261                )*
262            ]
263        )?
264    } => {
265        measures::define_measure_types_aux!{
266            $( $flag ) *,
267
268            with_points: true,
269            with_directions: $with_directions,
270            with_2d: $with_2d,
271            with_3d: $with_3d,
272            with_transformations: $with_transformations,
273            exact: $exact,
274            with_approx: $with_approx,
275            with_correlation: $with_correlation;
276
277            $(
278                scalar_properties [
279                    $(
280                        $scalar_prop [
281                            $(
282                                $scalar_unit {
283                                    $($scalar_key : $scalar_val),*
284                                }
285                            )*
286                        ]
287                    )*
288                ]
289            )?
290
291            $(
292                vector_properties [
293                    $(
294                        $vector_prop [
295                            $(
296                                $vector_unit {
297                                    $($vector_key : $vector_val),*
298                                }
299                            )*
300                        ]
301                    )*
302                ]
303            )?
304
305            $(
306                angle_measurement_units [
307                    $(
308                        $angle_unit {
309                            $($angle_key : $angle_val),*
310                        }
311                    )*
312                ]
313            )?
314
315            $(
316                relationships [
317                    $(
318                        $unit1 $dim1 == $unit2 $dim2 $op $unit3 $dim3
319                    )*
320                ]
321            )?
322        }
323    };
324
325    // First option is "with_directions"
326    {
327        with_directions $( $flag:ident )*,
328
329        with_points: $with_points:tt,
330        with_directions: false,
331        with_2d: $with_2d:tt,
332        with_3d: $with_3d:tt,
333        with_transformations: $with_transformations:tt,
334        exact: $exact:tt,
335        with_approx: $with_approx:tt,
336        with_correlation: $with_correlation:tt;
337
338        $(
339            scalar_properties [
340                $(
341                    $scalar_prop:ident [
342                        $(
343                            $scalar_unit:ident {
344                                $($scalar_key:ident : $scalar_val:expr),* $(,)?
345                            }
346                        )*
347                    ]
348                )*
349            ]
350        )?
351
352        $(
353            vector_properties [
354                $(
355                    $vector_prop:ident [
356                        $(
357                            $vector_unit:ident {
358                                $($vector_key:ident : $vector_val:expr),* $(,)?
359                            }
360                        )*
361                    ]
362                )*
363            ]
364        )?
365
366        $(
367            angle_measurement_units [
368                $(
369                    $angle_unit:ident {
370                        $($angle_key:ident : $angle_val:expr),* $(,)?
371                    }
372                )*
373            ]
374        )?
375
376        $(
377            relationships [
378                $(
379                    $unit1:ident $dim1:tt == $unit2:ident $dim2:tt $op:tt $unit3:ident $dim3:tt $(,)?
380                )*
381            ]
382        )?
383    } => {
384        measures::define_measure_types_aux!{
385            $( $flag ) *,
386
387            with_points: $with_points,
388            with_directions: true,
389            with_2d: $with_2d,
390            with_3d: $with_3d,
391            with_transformations: $with_transformations,
392            exact: $exact,
393            with_approx: $with_approx,
394            with_correlation: $with_correlation;
395
396            $(
397                scalar_properties [
398                    $(
399                        $scalar_prop [
400                            $(
401                                $scalar_unit {
402                                    $($scalar_key : $scalar_val),*
403                                }
404                            )*
405                        ]
406                    )*
407                ]
408            )?
409
410            $(
411                vector_properties [
412                    $(
413                        $vector_prop [
414                            $(
415                                $vector_unit {
416                                    $($vector_key : $vector_val),*
417                                }
418                            )*
419                        ]
420                    )*
421                ]
422            )?
423
424            $(
425                angle_measurement_units [
426                    $(
427                        $angle_unit {
428                            $($angle_key : $angle_val),*
429                        }
430                    )*
431                ]
432            )?
433
434            $(
435                relationships [
436                    $(
437                        $unit1 $dim1 == $unit2 $dim2 $op $unit3 $dim3
438                    )*
439                ]
440            )?
441        }
442    };
443
444    // First option is "with_2d"
445    {
446        with_2d $( $flag:ident )*,
447
448        with_points: $with_points:tt,
449        with_directions: $with_directions:tt,
450        with_2d: false,
451        with_3d: $with_3d:tt,
452        with_transformations: $with_transformations:tt,
453        exact: $exact:tt,
454        with_approx: $with_approx:tt,
455        with_correlation: $with_correlation:tt;
456
457        $(
458            scalar_properties [
459                $(
460                    $scalar_prop:ident [
461                        $(
462                            $scalar_unit:ident {
463                                $($scalar_key:ident : $scalar_val:expr),* $(,)?
464                            }
465                        )*
466                    ]
467                )*
468            ]
469        )?
470
471        $(
472            vector_properties [
473                $(
474                    $vector_prop:ident [
475                        $(
476                            $vector_unit:ident {
477                                $($vector_key:ident : $vector_val:expr),* $(,)?
478                            }
479                        )*
480                    ]
481                )*
482            ]
483        )?
484
485        $(
486            angle_measurement_units [
487                $(
488                    $angle_unit:ident {
489                        $($angle_key:ident : $angle_val:expr),* $(,)?
490                    }
491                )*
492            ]
493        )?
494
495        $(
496            relationships [
497                $(
498                    $unit1:ident $dim1:tt == $unit2:ident $dim2:tt $op:tt $unit3:ident $dim3:tt $(,)?
499                )*
500            ]
501        )?
502    } => {
503        measures::define_measure_types_aux!{
504            $( $flag ) *,
505
506            with_points: $with_points,
507            with_directions: $with_directions,
508            with_2d: true,
509            with_3d: $with_3d,
510            with_transformations: $with_transformations,
511            exact: $exact,
512            with_approx: $with_approx,
513            with_correlation: $with_correlation;
514
515            $(
516                scalar_properties [
517                    $(
518                        $scalar_prop [
519                            $(
520                                $scalar_unit {
521                                    $($scalar_key : $scalar_val),*
522                                }
523                            )*
524                        ]
525                    )*
526                ]
527            )?
528
529            $(
530                vector_properties [
531                    $(
532                        $vector_prop [
533                            $(
534                                $vector_unit {
535                                    $($vector_key : $vector_val),*
536                                }
537                            )*
538                        ]
539                    )*
540                ]
541            )?
542
543            $(
544                angle_measurement_units [
545                    $(
546                        $angle_unit {
547                            $($angle_key : $angle_val),*
548                        }
549                    )*
550                ]
551            )?
552
553            $(
554                relationships [
555                    $(
556                        $unit1 $dim1 == $unit2 $dim2 $op $unit3 $dim3
557                    )*
558                ]
559            )?
560        }
561    };
562
563    // First option is "with_3d"
564    {
565        with_3d $( $flag:ident )*,
566
567        with_points: $with_points:tt,
568        with_directions: $with_directions:tt,
569        with_2d: $with_2d:tt,
570        with_3d: false,
571        with_transformations: $with_transformations:tt,
572        exact: $exact:tt,
573        with_approx: $with_approx:tt,
574        with_correlation: $with_correlation:tt;
575
576        $(
577            scalar_properties [
578                $(
579                    $scalar_prop:ident [
580                        $(
581                            $scalar_unit:ident {
582                                $($scalar_key:ident : $scalar_val:expr),* $(,)?
583                            }
584                        )*
585                    ]
586                )*
587            ]
588        )?
589
590        $(
591            vector_properties [
592                $(
593                    $vector_prop:ident [
594                        $(
595                            $vector_unit:ident {
596                                $($vector_key:ident : $vector_val:expr),* $(,)?
597                            }
598                        )*
599                    ]
600                )*
601            ]
602        )?
603
604        $(
605            angle_measurement_units [
606                $(
607                    $angle_unit:ident {
608                        $($angle_key:ident : $angle_val:expr),* $(,)?
609                    }
610                )*
611            ]
612        )?
613
614        $(
615            relationships [
616                $(
617                    $unit1:ident $dim1:tt == $unit2:ident $dim2:tt $op:tt $unit3:ident $dim3:tt $(,)?
618                )*
619            ]
620        )?
621    } => {
622        measures::define_measure_types_aux!{
623            $( $flag ) *,
624
625            with_points: $with_points,
626            with_directions: $with_directions,
627            with_2d: $with_2d,
628            with_3d: true,
629            with_transformations: $with_transformations,
630            exact: $exact,
631            with_approx: $with_approx,
632            with_correlation: $with_correlation;
633
634            $(
635                scalar_properties [
636                    $(
637                        $scalar_prop [
638                            $(
639                                $scalar_unit {
640                                    $($scalar_key : $scalar_val),*
641                                }
642                            )*
643                        ]
644                    )*
645                ]
646            )?
647
648            $(
649                vector_properties [
650                    $(
651                        $vector_prop [
652                            $(
653                                $vector_unit {
654                                    $($vector_key : $vector_val),*
655                                }
656                            )*
657                        ]
658                    )*
659                ]
660            )?
661
662            $(
663                angle_measurement_units [
664                    $(
665                        $angle_unit {
666                            $($angle_key : $angle_val),*
667                        }
668                    )*
669                ]
670            )?
671
672            $(
673                relationships [
674                    $(
675                        $unit1 $dim1 == $unit2 $dim2 $op $unit3 $dim3
676                    )*
677                ]
678            )?
679        }
680    };
681
682    // First option is "with_transformations"
683    {
684        with_transformations $( $flag:ident )*,
685
686        with_points: $with_points:tt,
687        with_directions: $with_directions:tt,
688        with_2d: $with_2d:tt,
689        with_3d: $with_3d:tt,
690        with_transformations: false,
691        exact: $exact:tt,
692        with_approx: $with_approx:tt,
693        with_correlation: $with_correlation:tt;
694
695        $(
696            scalar_properties [
697                $(
698                    $scalar_prop:ident [
699                        $(
700                            $scalar_unit:ident {
701                                $($scalar_key:ident : $scalar_val:expr),* $(,)?
702                            }
703                        )*
704                    ]
705                )*
706            ]
707        )?
708
709        $(
710            vector_properties [
711                $(
712                    $vector_prop:ident [
713                        $(
714                            $vector_unit:ident {
715                                $($vector_key:ident : $vector_val:expr),* $(,)?
716                            }
717                        )*
718                    ]
719                )*
720            ]
721        )?
722
723        $(
724            angle_measurement_units [
725                $(
726                    $angle_unit:ident {
727                        $($angle_key:ident : $angle_val:expr),* $(,)?
728                    }
729                )*
730            ]
731        )?
732
733        $(
734            relationships [
735                $(
736                    $unit1:ident $dim1:tt == $unit2:ident $dim2:tt $op:tt $unit3:ident $dim3:tt $(,)?
737                )*
738            ]
739        )?
740    } => {
741        measures::define_measure_types_aux!{
742            $( $flag ) *,
743
744            with_points: $with_points,
745            with_directions: $with_directions,
746            with_2d: $with_2d,
747            with_3d: $with_3d,
748            with_transformations: true,
749            exact: $exact,
750            with_approx: $with_approx,
751            with_correlation: $with_correlation;
752
753            $(
754                scalar_properties [
755                    $(
756                        $scalar_prop [
757                            $(
758                                $scalar_unit {
759                                    $($scalar_key : $scalar_val),*
760                                }
761                            )*
762                        ]
763                    )*
764                ]
765            )?
766
767            $(
768                vector_properties [
769                    $(
770                        $vector_prop [
771                            $(
772                                $vector_unit {
773                                    $($vector_key : $vector_val),*
774                                }
775                            )*
776                        ]
777                    )*
778                ]
779            )?
780
781            $(
782                angle_measurement_units [
783                    $(
784                        $angle_unit {
785                            $($angle_key : $angle_val),*
786                        }
787                    )*
788                ]
789            )?
790
791            $(
792                relationships [
793                    $(
794                        $unit1 $dim1 == $unit2 $dim2 $op $unit3 $dim3
795                    )*
796                ]
797            )?
798        }
799    };
800
801    // First option is "exact"
802    {
803        exact $( $flag:ident )*,
804
805        with_points: $with_points:tt,
806        with_directions: $with_directions:tt,
807        with_2d: $with_2d:tt,
808        with_3d: $with_3d:tt,
809        with_transformations: $with_transformations:tt,
810        exact: false,
811        with_approx: $with_approx:tt,
812        with_correlation: $with_correlation:tt;
813
814        $(
815            scalar_properties [
816                $(
817                    $scalar_prop:ident [
818                        $(
819                            $scalar_unit:ident {
820                                $($scalar_key:ident : $scalar_val:expr),* $(,)?
821                            }
822                        )*
823                    ]
824                )*
825            ]
826        )?
827
828        $(
829            vector_properties [
830                $(
831                    $vector_prop:ident [
832                        $(
833                            $vector_unit:ident {
834                                $($vector_key:ident : $vector_val:expr),* $(,)?
835                            }
836                        )*
837                    ]
838                )*
839            ]
840        )?
841
842        $(
843            angle_measurement_units [
844                $(
845                    $angle_unit:ident {
846                        $($angle_key:ident : $angle_val:expr),* $(,)?
847                    }
848                )*
849            ]
850        )?
851
852        $(
853            relationships [
854                $(
855                    $unit1:ident $dim1:tt == $unit2:ident $dim2:tt $op:tt $unit3:ident $dim3:tt $(,)?
856                )*
857            ]
858        )?
859    } => {
860        measures::define_measure_types_aux!{
861            $( $flag ) *,
862
863            with_points: $with_points,
864            with_directions: $with_directions,
865            with_2d: $with_2d,
866            with_3d: $with_3d,
867            with_transformations: $with_transformations,
868            exact: true,
869            with_approx: $with_approx,
870            with_correlation: $with_correlation;
871
872            $(
873                scalar_properties [
874                    $(
875                        $scalar_prop [
876                            $(
877                                $scalar_unit {
878                                    $($scalar_key : $scalar_val),*
879                                }
880                            )*
881                        ]
882                    )*
883                ]
884            )?
885
886            $(
887                vector_properties [
888                    $(
889                        $vector_prop [
890                            $(
891                                $vector_unit {
892                                    $($vector_key : $vector_val),*
893                                }
894                            )*
895                        ]
896                    )*
897                ]
898            )?
899
900            $(
901                angle_measurement_units [
902                    $(
903                        $angle_unit {
904                            $($angle_key : $angle_val),*
905                        }
906                    )*
907                ]
908            )?
909
910            $(
911                relationships [
912                    $(
913                        $unit1 $dim1 == $unit2 $dim2 $op $unit3 $dim3
914                    )*
915                ]
916            )?
917        }
918    };
919
920    // First option is "with_approx"
921    {
922        with_approx $( $flag:ident )*,
923
924        with_points: $with_points:tt,
925        with_directions: $with_directions:tt,
926        with_2d: $with_2d:tt,
927        with_3d: $with_3d:tt,
928        with_transformations: $with_transformations:tt,
929        exact: $exact:tt,
930        with_approx: false,
931        with_correlation: $with_correlation:tt;
932
933        $(
934            scalar_properties [
935                $(
936                    $scalar_prop:ident [
937                        $(
938                            $scalar_unit:ident {
939                                $($scalar_key:ident : $scalar_val:expr),* $(,)?
940                            }
941                        )*
942                    ]
943                )*
944            ]
945        )?
946
947        $(
948            vector_properties [
949                $(
950                    $vector_prop:ident [
951                        $(
952                            $vector_unit:ident {
953                                $($vector_key:ident : $vector_val:expr),* $(,)?
954                            }
955                        )*
956                    ]
957                )*
958            ]
959        )?
960
961        $(
962            angle_measurement_units [
963                $(
964                    $angle_unit:ident {
965                        $($angle_key:ident : $angle_val:expr),* $(,)?
966                    }
967                )*
968            ]
969        )?
970
971        $(
972            relationships [
973                $(
974                    $unit1:ident $dim1:tt == $unit2:ident $dim2:tt $op:tt $unit3:ident $dim3:tt $(,)?
975                )*
976            ]
977        )?
978    } => {
979        measures::define_measure_types_aux!{
980            $( $flag ) *,
981
982            with_points: $with_points,
983            with_directions: $with_directions,
984            with_2d: $with_2d,
985            with_3d: $with_3d,
986            with_transformations: $with_transformations,
987            exact: $exact,
988            with_approx: true,
989            with_correlation: $with_correlation;
990
991            $(
992                scalar_properties [
993                    $(
994                        $scalar_prop [
995                            $(
996                                $scalar_unit {
997                                    $($scalar_key : $scalar_val),*
998                                }
999                            )*
1000                        ]
1001                    )*
1002                ]
1003            )?
1004
1005            $(
1006                vector_properties [
1007                    $(
1008                        $vector_prop [
1009                            $(
1010                                $vector_unit {
1011                                    $($vector_key : $vector_val),*
1012                                }
1013                            )*
1014                        ]
1015                    )*
1016                ]
1017            )?
1018
1019            $(
1020                angle_measurement_units [
1021                    $(
1022                        $angle_unit {
1023                            $($angle_key : $angle_val),*
1024                        }
1025                    )*
1026                ]
1027            )?
1028
1029            $(
1030                relationships [
1031                    $(
1032                        $unit1 $dim1 == $unit2 $dim2 $op $unit3 $dim3
1033                    )*
1034                ]
1035            )?
1036        }
1037    };
1038
1039    // First option is "with_correlation"
1040    {
1041        with_correlation $( $flag:ident )*,
1042
1043        with_points: $with_points:tt,
1044        with_directions: $with_directions:tt,
1045        with_2d: $with_2d:tt,
1046        with_3d: $with_3d:tt,
1047        with_transformations: $with_transformations:tt,
1048        exact: $exact:tt,
1049        with_approx: $with_approx:tt,
1050        with_correlation: false;
1051
1052        $(
1053            scalar_properties [
1054                $(
1055                    $scalar_prop:ident [
1056                        $(
1057                            $scalar_unit:ident {
1058                                $($scalar_key:ident : $scalar_val:expr),* $(,)?
1059                            }
1060                        )*
1061                    ]
1062                )*
1063            ]
1064        )?
1065
1066        $(
1067            vector_properties [
1068                $(
1069                    $vector_prop:ident [
1070                        $(
1071                            $vector_unit:ident {
1072                                $($vector_key:ident : $vector_val:expr),* $(,)?
1073                            }
1074                        )*
1075                    ]
1076                )*
1077            ]
1078        )?
1079
1080        $(
1081            angle_measurement_units [
1082                $(
1083                    $angle_unit:ident {
1084                        $($angle_key:ident : $angle_val:expr),* $(,)?
1085                    }
1086                )*
1087            ]
1088        )?
1089
1090        $(
1091            relationships [
1092                $(
1093                    $unit1:ident $dim1:tt == $unit2:ident $dim2:tt $op:tt $unit3:ident $dim3:tt $(,)?
1094                )*
1095            ]
1096        )?
1097    } => {
1098        measures::define_measure_types_aux!{
1099            $( $flag ) *,
1100            with_points: $with_points,
1101            with_directions: $with_directions,
1102            with_2d: $with_2d,
1103            with_3d: $with_3d,
1104            with_transformations: $with_transformations,
1105            exact: $exact,
1106            with_approx: $with_approx,
1107            with_correlation: true;
1108
1109            $(
1110                scalar_properties [
1111                    $(
1112                        $scalar_prop [
1113                            $(
1114                                $scalar_unit {
1115                                    $($scalar_key : $scalar_val),*
1116                                }
1117                            )*
1118                        ]
1119                    )*
1120                ]
1121            )?
1122
1123            $(
1124                vector_properties [
1125                    $(
1126                        $vector_prop [
1127                            $(
1128                                $vector_unit {
1129                                    $($vector_key : $vector_val),*
1130                                }
1131                            )*
1132                        ]
1133                    )*
1134                ]
1135            )?
1136
1137            $(
1138                angle_measurement_units [
1139                    $(
1140                        $angle_unit {
1141                            $($angle_key : $angle_val),*
1142                        }
1143                    )*
1144                ]
1145            )?
1146
1147            $(
1148                relationships [
1149                    $(
1150                        $unit1 $dim1 == $unit2 $dim2 $op $unit3 $dim3
1151                    )*
1152                ]
1153            )?
1154        }
1155    };
1156}
1157
1158#[macro_export]
1159macro_rules! define_measure_types {
1160    (
1161        $( $flag:ident )* ,
1162
1163        $(
1164            scalar_properties [
1165                $(
1166                    $scalar_prop:ident [
1167                        $(
1168                            $scalar_unit:ident {
1169                                $($scalar_key:ident : $scalar_val:expr),* $(,)?
1170                            }
1171                        )*
1172                    ]
1173                )*
1174            ]
1175        )?
1176
1177        $(
1178            vector_properties [
1179                $(
1180                    $vector_prop:ident [
1181                        $(
1182                            $vector_unit:ident {
1183                                $($vector_key:ident : $vector_val:expr),* $(,)?
1184                            }
1185                        )*
1186                    ]
1187                )*
1188            ]
1189        )?
1190
1191        $(
1192            angle_measurement_units [
1193                $(
1194                    $angle_unit:ident {
1195                        $($angle_key:ident : $angle_val:expr),* $(,)?
1196                    }
1197                )*
1198            ]
1199        )?
1200
1201        $(
1202            relationships [
1203                $(
1204                    $unit1:ident $dim1:tt == $unit2:ident $dim2:tt $op:tt $unit3:ident $dim3:tt $(,)?
1205                )*
1206            ]
1207        )?
1208    ) => {
1209        measures::define_measure_types_aux! {
1210            $( $flag )* ,
1211
1212            with_points: false,
1213            with_directions: false,
1214            with_2d: false,
1215            with_3d: false,
1216            with_transformations: false,
1217            exact: false,
1218            with_approx: false,
1219            with_correlation: false;
1220
1221            $(
1222                scalar_properties [
1223                    $(
1224                        $scalar_prop [
1225                            $(
1226                                $scalar_unit {
1227                                    $($scalar_key : $scalar_val),*
1228                                }
1229                            )*
1230                        ]
1231                    )*
1232                ]
1233            )?
1234
1235            $(
1236                vector_properties [
1237                    $(
1238                        $vector_prop [
1239                            $(
1240                                $vector_unit {
1241                                    $($vector_key : $vector_val),*
1242                                }
1243                            )*
1244                        ]
1245                    )*
1246                ]
1247            )?
1248
1249            $(
1250                angle_measurement_units [
1251                    $(
1252                        $angle_unit {
1253                            $($angle_key : $angle_val),*
1254                        }
1255                    )*
1256                ]
1257            )?
1258
1259            $(
1260                relationships [
1261                    $(
1262                        $unit1 $dim1 == $unit2 $dim2 $op $unit3 $dim3
1263                    )*
1264                ]
1265            )?
1266        }
1267    };
1268}
1269
1270#[macro_export]
1271macro_rules! measurement_scalar_property {
1272    ($name:ident) => {
1273        /// A scalar measure property.
1274        pub struct $name;
1275        impl $crate::traits::MeasurementProperty for $name {}
1276        impl $crate::traits::ScalarProperty for $name {}
1277    };
1278}
1279
1280#[macro_export]
1281macro_rules! measurement_vector_property {
1282    ($name:ident) => {
1283        /// A vector measure property.
1284        pub struct $name;
1285        impl $crate::traits::MeasurementProperty for $name {}
1286        impl $crate::traits::VectorProperty for $name {}
1287    };
1288}
1289
1290#[macro_export]
1291macro_rules! angle_measurement_unit {
1292    {
1293        name: $name:ident,
1294        suffix: $suffix:expr,
1295        cycle_fraction: $cycle_fraction:expr,
1296    } => {
1297        $crate::angle_measurement_unit! {
1298            name: $name,
1299            suffix: $suffix,
1300            offset: 0.,
1301            cycle_fraction: $cycle_fraction,
1302        }
1303    };
1304    {
1305        name: $name:ident,
1306        suffix: $suffix:expr,
1307        offset: $offset:expr,
1308        cycle_fraction: $cycle_fraction:expr,
1309    } => {
1310        /// An `Angle` unit of measurement.
1311        pub struct $name;
1312        impl measures::traits::MeasurementUnit for $name {
1313            type Property = $crate::angle::Angle;
1314            const RATIO: f64 = core::f64::consts::TAU / ($cycle_fraction);
1315            const OFFSET: f64 = $offset;
1316            const SUFFIX: &'static str = $suffix;
1317        }
1318
1319        impl measures::traits::AngleMeasurementUnit for $name {
1320            const CYCLE_FRACTION: f64 = $cycle_fraction;
1321        }
1322
1323        impl<Number> core::ops::Mul<Measure<$name, Number>> for Measure<measures::dimensionless::One, Number>
1324        where
1325            Number: measures::traits::ArithmeticOps,
1326        {
1327            type Output = Measure<$name, Number>;
1328
1329            /// Measure<One> * AngleMeasure -> AngleMeasure
1330            fn mul(self, other: Measure<$name, Number>) -> Measure<$name, Number> {
1331                Measure::<$name, Number>::new(self.value * other.value)
1332            }
1333        }
1334
1335        impl<Number> core::ops::Div<Measure<measures::dimensionless::One, Number>> for Measure<$name, Number>
1336        where
1337            Number: measures::traits::ArithmeticOps,
1338        {
1339            type Output = Self;
1340
1341            /// AngleMeasure / Measure<One> -> AngleMeasure
1342            fn div(self, other: Measure<measures::dimensionless::One, Number>) -> Self::Output {
1343                Self::new(self.value / other.value)
1344            }
1345        }
1346    };
1347}
1348
1349#[macro_export]
1350macro_rules! measurement_unit_aux {
1351    {
1352        name: $name:ident,
1353        property: $property:ident,
1354        suffix: $suffix:expr,
1355        ratio: $ratio:expr,
1356        offset: $offset:expr,
1357        with_2d: $with_2d:tt,
1358        with_3d: $with_3d:tt,
1359        vector: $vector:tt,
1360    } => {
1361        /// A unit of measurement.
1362        pub struct $name;
1363        impl measures::traits::MeasurementUnit for $name {
1364            type Property = $property;
1365            const RATIO: f64 = $ratio;
1366            const OFFSET: f64 = $offset;
1367            const SUFFIX: &'static str = $suffix;
1368        }
1369
1370        impl<Number> core::ops::Mul<Measure<$name, Number>> for Measure<measures::dimensionless::One, Number>
1371        where
1372            Number: measures::traits::ArithmeticOps,
1373        {
1374            type Output = Measure<$name, Number>;
1375
1376            /// Measure<One> * Measure -> Measure
1377            fn mul(self, other: Measure<$name, Number>) -> Measure<$name, Number> {
1378                Measure::<$name, Number>::new(self.value * other.value)
1379            }
1380        }
1381
1382        impl<Number> core::ops::Div<Measure<measures::dimensionless::One, Number>> for Measure<$name, Number>
1383        where
1384            Number: measures::traits::ArithmeticOps,
1385        {
1386            type Output = Self;
1387
1388            /// Measure / Measure<One> -> Measure
1389            fn div(self, other: Measure<measures::dimensionless::One, Number>) -> Self::Output {
1390                Self::new(self.value / other.value)
1391            }
1392        }
1393
1394        measures::if_all_true! { { $with_2d $vector }
1395            impl<Number> core::ops::Mul<Measure<$name, Number>> for Measure2d<measures::dimensionless::One, Number>
1396            where
1397                Number: measures::traits::ArithmeticOps,
1398            {
1399                type Output = Measure2d<$name, Number>;
1400
1401                /// Measure2d<One> * Measure -> Measure2d
1402                fn mul(self, other: Measure<$name, Number>) -> Self::Output {
1403                    Measure2d::<$name, Number>::new([
1404                        self.values[0] * other.value,
1405                        self.values[1] * other.value,
1406                    ])
1407                }
1408            }
1409
1410            impl<Number> core::ops::Mul<Measure2d<One, Number>> for Measure<$name, Number>
1411            where
1412                Number: measures::traits::ArithmeticOps,
1413            {
1414                type Output = Measure2d<$name, Number>;
1415
1416                /// Measure * Measure2d<One> -> Measure2d
1417                fn mul(self, other: Measure2d<One, Number>) -> Self::Output {
1418                    Measure2d::<$name, Number>::new([
1419                        self.value * other.values[0],
1420                        self.value * other.values[1],
1421                    ])
1422                }
1423            }
1424
1425            impl<Number> core::ops::Div<Measure<measures::dimensionless::One, Number>> for Measure2d<$name, Number>
1426            where
1427                Number: measures::traits::ArithmeticOps,
1428            {
1429                type Output = Self;
1430
1431                /// Measure2d / Measure<One> -> Measure2d
1432                fn div(self, other: Measure<measures::dimensionless::One, Number>) -> Self::Output {
1433                    Self::new([
1434                        self.values[0] / other.value,
1435                        self.values[1] / other.value,
1436                    ])
1437                }
1438            }
1439        }
1440
1441        measures::if_all_true! { { $with_3d $vector }
1442            impl<Number> core::ops::Mul<Measure<$name, Number>> for Measure3d<measures::dimensionless::One, Number>
1443            where
1444                Number: measures::traits::ArithmeticOps,
1445            {
1446                type Output = Measure3d<$name, Number>;
1447
1448                /// Measure3d<One> * Measure -> Measure3d
1449                fn mul(self, other: Measure<$name, Number>) -> Self::Output {
1450                    Measure3d::<$name, Number>::new([
1451                        self.values[0] * other.value,
1452                        self.values[1] * other.value,
1453                        self.values[2] * other.value,
1454                    ])
1455                }
1456            }
1457
1458            impl<Number> core::ops::Mul<Measure3d<One, Number>> for Measure<$name, Number>
1459            where
1460                Number: measures::traits::ArithmeticOps,
1461            {
1462                type Output = Measure3d<$name, Number>;
1463
1464                /// Measure * Measure3d<One> -> Measure3d
1465                fn mul(self, other: Measure3d<One, Number>) -> Self::Output {
1466                    Measure3d::<$name, Number>::new([
1467                        self.value * other.values[0],
1468                        self.value * other.values[1],
1469                        self.value * other.values[2],
1470                    ])
1471                }
1472            }
1473
1474            impl<Number> core::ops::Div<Measure<measures::dimensionless::One, Number>> for Measure3d<$name, Number>
1475            where
1476                Number: measures::traits::ArithmeticOps,
1477            {
1478                type Output = Self;
1479
1480                /// Measure3d / Measure<One> -> Measure2d
1481                fn div(self, other: Measure<measures::dimensionless::One, Number>) -> Self::Output {
1482                    Self::new([
1483                        self.values[0] / other.value,
1484                        self.values[1] / other.value,
1485                        self.values[2] / other.value,
1486                    ])
1487                }
1488            }
1489        }
1490    };
1491}
1492
1493#[macro_export]
1494macro_rules! measurement_unit {
1495    {
1496        name: $name:ident,
1497        property: $property:ident,
1498        suffix: $suffix:expr,
1499        with_2d: $with_2d:tt,
1500        with_3d: $with_3d:tt,
1501        vector: $vector:tt,
1502    } => {
1503        $crate::measurement_unit! {
1504            name: $name,
1505            property: $property,
1506            suffix: $suffix,
1507            ratio: 1.,
1508            with_2d: $with_2d,
1509            with_3d: $with_3d,
1510            vector: $vector,
1511        }
1512    };
1513    {
1514        name: $name:ident,
1515        property: $property:ident,
1516        suffix: $suffix:expr,
1517        ratio: $ratio:expr,
1518        with_2d: $with_2d:tt,
1519        with_3d: $with_3d:tt,
1520        vector: true,
1521    } => {
1522        $crate::measurement_unit_aux! {
1523            name: $name,
1524            property: $property,
1525            suffix: $suffix,
1526            ratio: $ratio,
1527            offset: 0.,
1528            with_2d: $with_2d,
1529            with_3d: $with_3d,
1530            vector: true,
1531        }
1532    };
1533    {
1534        name: $name:ident,
1535        property: $property:ident,
1536        suffix: $suffix:expr,
1537        ratio: $ratio:expr,
1538        with_2d: $with_2d:tt,
1539        with_3d: $with_3d:tt,
1540        vector: false,
1541    } => {
1542        $crate::measurement_unit_aux! {
1543            name: $name,
1544            property: $property,
1545            suffix: $suffix,
1546            ratio: $ratio,
1547            offset: 0.,
1548            with_2d: $with_2d,
1549            with_3d: $with_3d,
1550            vector: false,
1551        }
1552    };
1553    {
1554        name: $name:ident,
1555        property: $property:ident,
1556        suffix: $suffix:expr,
1557        ratio: $ratio:expr,
1558        offset: $offset:expr,
1559        with_2d: $with_2d:tt,
1560        with_3d: $with_3d:tt,
1561        vector: false,
1562    } => {
1563        $crate::measurement_unit_aux! {
1564            name: $name,
1565            property: $property,
1566            suffix: $suffix,
1567            ratio: $ratio,
1568            offset: $offset,
1569            with_2d: $with_2d,
1570            with_3d: $with_3d,
1571            vector: false,
1572        }
1573    };
1574}