1#[cfg(test)]
19mod test;
20
21use super::{
22 Action, Amount, Area, Charge, Dimensionless, Energy, Entropy, Force, ForcePerLength, Length,
23 MolarEnergy, MolarEntropy, PowerPerLengthTemperature, Rate, ReciprocalAmount,
24 ReciprocalTemperature, Stress, StressPerLength, Temperature, Time, Velocity, Viscosity, Volume,
25};
26use crate::math::{Quantity, TensorRank0};
27
28const ZERO_CELSIUS: TensorRank0 = 273.15;
30
31pub type Scale<U> = fn(TensorRank0) -> Quantity<U>;
33
34pub fn length_scale(label: &str) -> Option<Scale<Length>> {
43 Some(match label.trim().to_lowercase().as_str() {
44 "m" | "meter" | "meters" | "metre" | "metres" => Length::meters,
45 "mm" | "millimeter" | "millimeters" | "millimetre" | "millimetres" => Length::millimeters,
46 "cm" | "centimeter" | "centimeters" | "centimetre" | "centimetres" => Length::centimeters,
47 "um" | "\u{b5}m" | "\u{3bc}m" | "micrometer" | "micrometers" | "micrometre"
48 | "micrometres" | "micron" | "microns" => Length::micrometers,
49 "nm" | "nanometer" | "nanometers" | "nanometre" | "nanometres" => Length::nanometers,
50 "km" | "kilometer" | "kilometers" | "kilometre" | "kilometres" => Length::kilometers,
51 "in" | "inch" | "inches" => Length::inches,
52 "ft" | "foot" | "feet" => Length::feet,
53 _ => return None,
54 })
55}
56
57macro_rules! scales {
63 ($($unit:ident { $($name:ident / $reader:ident = $factor:expr, $doc:expr),+ $(,)? })+) => {
64 $(
65 impl $unit {
66 $(
67 #[doc = concat!("A quantity of ", $doc, ".")]
68 pub const fn $name(value: TensorRank0) -> Quantity<$unit> {
69 Quantity::new(value * $factor)
70 }
71 )+
72 }
73 impl Quantity<$unit> {
74 $(
75 #[doc = concat!("How many ", $doc, " the quantity is.")]
76 pub const fn $reader(&self) -> TensorRank0 {
77 self.value() / $factor
78 }
79 )+
80 }
81 )+
82 };
83}
84
85scales!(
86 Length {
87 meters / in_meters = 1.0, "metres",
88 millimeters / in_millimeters = 1e-3, "millimetres",
89 micrometers / in_micrometers = 1e-6, "micrometres",
90 nanometers / in_nanometers = 1e-9, "nanometres",
91 centimeters / in_centimeters = 1e-2, "centimetres",
92 kilometers / in_kilometers = 1e3, "kilometres",
93 inches / in_inches = 2.54e-2, "inches",
94 feet / in_feet = 3.048e-1, "feet",
95 }
96 Area {
97 square_meters / in_square_meters = 1.0, "square metres",
98 square_millimeters / in_square_millimeters = 1e-6, "square millimetres",
99 square_centimeters / in_square_centimeters = 1e-4, "square centimetres",
100 }
101 Volume {
102 cubic_meters / in_cubic_meters = 1.0, "cubic metres",
103 cubic_millimeters / in_cubic_millimeters = 1e-9, "cubic millimetres",
104 cubic_centimeters / in_cubic_centimeters = 1e-6, "cubic centimetres",
105 liters / in_liters = 1e-3, "litres",
106 }
107 Time {
108 seconds / in_seconds = 1.0, "seconds",
109 milliseconds / in_milliseconds = 1e-3, "milliseconds",
110 microseconds / in_microseconds = 1e-6, "microseconds",
111 minutes / in_minutes = 6e1, "minutes",
112 hours / in_hours = 3.6e3, "hours",
113 }
114 Rate {
115 per_second / in_per_second = 1.0, "reciprocal seconds",
116 per_minute / in_per_minute = 1.0 / 6e1, "reciprocal minutes",
117 per_hour / in_per_hour = 1.0 / 3.6e3, "reciprocal hours",
118 hertz / in_hertz = 1.0, "hertz",
119 }
120 Stress {
121 pascals / in_pascals = 1.0, "pascals",
122 kilopascals / in_kilopascals = 1e3, "kilopascals",
123 megapascals / in_megapascals = 1e6, "megapascals",
124 gigapascals / in_gigapascals = 1e9, "gigapascals",
125 bars / in_bars = 1e5, "bars",
126 psi / in_psi = 6.894_757_293_168_361e3, "pounds per square inch",
127 ksi / in_ksi = 6.894_757_293_168_361e6, "kips per square inch",
128 }
129 Force {
130 newtons / in_newtons = 1.0, "newtons",
131 millinewtons / in_millinewtons = 1e-3, "millinewtons",
132 kilonewtons / in_kilonewtons = 1e3, "kilonewtons",
133 meganewtons / in_meganewtons = 1e6, "meganewtons",
134 pounds_force / in_pounds_force = 4.448_221_615_260_5, "pounds force",
135 }
136 Energy {
137 joules / in_joules = 1.0, "joules",
138 millijoules / in_millijoules = 1e-3, "millijoules",
139 kilojoules / in_kilojoules = 1e3, "kilojoules",
140 electronvolts / in_electronvolts = 1.602_176_634e-19, "electronvolts",
141 }
142 Entropy {
143 joules_per_kelvin / in_joules_per_kelvin = 1.0, "joules per kelvin",
144 }
145 Action {
146 joule_seconds / in_joule_seconds = 1.0, "joule seconds",
147 }
148 Amount {
149 moles / in_moles = 1.0, "moles",
150 millimoles / in_millimoles = 1e-3, "millimoles",
151 }
152 ReciprocalAmount {
153 per_mole / in_per_mole = 1.0, "reciprocal moles",
154 }
155 MolarEntropy {
156 joules_per_mole_kelvin / in_joules_per_mole_kelvin = 1.0, "joules per mole kelvin",
157 }
158 MolarEnergy {
159 joules_per_mole / in_joules_per_mole = 1.0, "joules per mole",
160 kilojoules_per_mole / in_kilojoules_per_mole = 1e3, "kilojoules per mole",
161 }
162 ForcePerLength {
163 newtons_per_meter / in_newtons_per_meter = 1.0, "newtons per metre",
164 piconewtons_per_nanometer / in_piconewtons_per_nanometer = 1e-3,
165 "piconewtons per nanometre",
166 }
167 Velocity {
168 meters_per_second / in_meters_per_second = 1.0, "metres per second",
169 millimeters_per_second / in_millimeters_per_second = 1e-3, "millimetres per second",
170 kilometers_per_hour / in_kilometers_per_hour = 1.0 / 3.6, "kilometres per hour",
171 }
172 Charge {
173 coulombs / in_coulombs = 1.0, "coulombs",
174 }
175 Viscosity {
176 pascal_seconds / in_pascal_seconds = 1.0, "pascal seconds",
177 poise / in_poise = 1e-1, "poise",
178 centipoise / in_centipoise = 1e-3, "centipoise",
179 }
180 Temperature {
181 kelvin / in_kelvin = 1.0, "kelvin",
182 }
183 ReciprocalTemperature {
184 per_kelvin / in_per_kelvin = 1.0, "reciprocal kelvin",
185 per_celsius / in_per_celsius = 1.0, "reciprocal degrees celsius",
186 }
187 StressPerLength {
188 pascals_per_meter / in_pascals_per_meter = 1.0, "pascals per metre",
189 megapascals_per_millimeter / in_megapascals_per_millimeter = 1e9,
190 "megapascals per millimetre",
191 }
192 PowerPerLengthTemperature {
193 watts_per_meter_kelvin / in_watts_per_meter_kelvin = 1.0, "watts per metre kelvin",
194 }
195 Dimensionless {
196 percent / in_percent = 1e-2, "percent",
197 }
198);
199
200impl Dimensionless {
201 pub const fn of(value: TensorRank0) -> Quantity<Dimensionless> {
207 Quantity::new(value)
208 }
209}
210
211impl Temperature {
212 pub const fn celsius(value: TensorRank0) -> Quantity<Temperature> {
218 Quantity::new(value + ZERO_CELSIUS)
219 }
220 pub const fn fahrenheit(value: TensorRank0) -> Quantity<Temperature> {
225 Quantity::new((value - 32.0) * 5.0 / 9.0 + ZERO_CELSIUS)
226 }
227}
228
229impl Quantity<Temperature> {
230 pub const fn in_celsius(&self) -> TensorRank0 {
232 self.value() - ZERO_CELSIUS
233 }
234 pub const fn in_fahrenheit(&self) -> TensorRank0 {
236 (self.value() - ZERO_CELSIUS) * 9.0 / 5.0 + 32.0
237 }
238}