1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#[macro_export]
macro_rules! make_units { ($System:ident, $Unitless:ident, $one:ident; base { $($Type:ident, $constant:ident, $print_as:ident;)+ } derived {$($derived_constant:ident: $Derived:ident = $e:expr;)*} ) => (
make_units_adv!{
$System, $Unitless, $one, f64;
base {
$(One, $Type, $constant, $print_as;)*
}
derived {
$($derived_constant: $Derived = $e;)*
}
}
);
}
#[macro_export]
macro_rules! make_units_adv { ($System:ident, $Unitless:ident, $one:ident, $OneType:ident; base { $($Root:ident, $Type:ident, $constant:ident, $print_as:ident;)+ } derived {$($derived_constant:ident: $Derived:ident = $e: expr; )*} ) => (
#[allow(unused_imports)]
use $crate::peano::{Zero, One, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten};
use $crate::peano::{Peano, KeepPeano, AddPeano, SubPeano, MulPeano, DivPeano, Negate, ToInt};
use $crate::dimensioned::{Dimension, Dimensionless, Dim, KeepDim, MulDim, DivDim, PowerDim, RootDim, InvertDim, DimToString};
use std::marker::PhantomData;
#[derive(Copy, Clone)]
pub struct $System<$($Type: Peano = Zero),*> {
$($constant: PhantomData<$Type>),*
}
impl<$($Type: Peano),*> Dimension for $System<$($Type),*> {}
#[allow(non_camel_case_types)]
impl<$($Type),*, $($constant),*> KeepDim<$System<$($constant),*>> for $System<$($Type),*> where
$($Type: Peano + KeepPeano<$constant>),*, $($constant: Peano),* {
type Output = $System<$(<$Type as KeepPeano<$constant>>::Output),*>;
}
#[allow(non_camel_case_types)]
impl<$($Type),*, $($constant),*> MulDim<$System<$($constant),*>> for $System<$($Type),*> where
$($Type: Peano + AddPeano<$constant>),*, $($constant: Peano),* {
type Output = $System<$(<$Type as AddPeano<$constant>>::Output),*>;
}
#[allow(non_camel_case_types)]
impl<$($Type),*, $($constant),*> DivDim<$System<$($constant),*>> for $System<$($Type),*> where
$($Type: Peano + SubPeano<$constant>),*, $($constant: Peano),* {
type Output = $System<$(<$Type as SubPeano<$constant>>::Output),*>;
}
impl<$($Type),*, RHS> PowerDim<RHS> for $System<$($Type),*> where
$($Type: Peano + MulPeano<RHS>),*, RHS: Peano {
type Output = $System<$(<$Type as MulPeano<RHS>>::Output),*>;
}
impl<$($Type),*, RHS> RootDim<RHS> for $System<$($Type),*> where
$($Type: Peano + DivPeano<RHS>),*, RHS: Peano {
type Output = $System<$(<$Type as DivPeano<RHS>>::Output),*>;
}
impl<$($Type),*> InvertDim for $System<$($Type),*> where
$($Type: Peano + Negate),* {
type Output = $System<$(<$Type as Negate>::Output),*>;
}
fn pretty_dim(roots: [i32; count_args!($($Type),*)], exps: [i32; count_args!($($Type),*)], tokens: [&'static str; count_args!($($Type),*)]) -> String {
let mut __string = String::new();
for ((&root, &exp), &token) in roots.iter().zip(exps.iter()).zip(tokens.iter()) {
let __temp: (&'static str, String) = match exp {
0 => ("", "".to_string()),
1 => (token, "*".to_string()),
_ => (token, format!("^{}*", exp/root)),
};
__string = format!("{}{}{}", __string, __temp.0, __temp.1);
}
__string.pop();
__string
}
impl<$($Type),*> DimToString for $System<$($Type),*>
where $($Type: ToInt),* {
fn to_string() -> String {
let allowed_roots = [$($Root::to_int()),*];
let exponents = [$($Type::to_int()),*];
let print_tokens = [$(stringify!($print_as)),*];
pretty_dim(allowed_roots, exponents, print_tokens)
}
}
pub type $Unitless = $System;
impl Dimensionless for $Unitless {}
#[allow(non_upper_case_globals)]
pub const $one: Dim<$Unitless, $OneType> = Dim(1.0, PhantomData);
__make_types!($System, $($Type, $Root),+ |);
$(#[allow(non_upper_case_globals)] pub const $constant: Dim<$Type, $OneType> = Dim(1.0, PhantomData));*;
);
}
#[macro_export]
macro_rules! count_args {
($arg:ident, $($args:ident),+) => (
1 + count_args!($($args),+);
);
($arg:ident) => (
1
);
}
#[doc_hidden]
#[macro_export]
macro_rules! __make_types {
($System:ident, $Type:ident, $Root:ident, $($Types:ident, $Roots:ident),+ | $($Zeros:ident),*) => (
pub type $Type = $System< $($Zeros,)* $Root>;
__make_types!($System, $($Types, $Roots),+ | Zero $(, $Zeros)*);
);
($System:ident, $Type:ident, $Root:ident | $($Zeros:ident),*) => (
pub type $Type = $System<$($Zeros,)* $Root>;
);
}