1use crate::units::AmountOfSubstanceUnit;
18use crate::units::ElectricCurrentUnit;
19use crate::units::IsEngUnitType;
20use crate::units::LengthUnit;
21use crate::units::LuminousIntensityUnit;
22use crate::units::MassUnit;
23use crate::units::TimeUnit;
24
25#[macro_export]
26macro_rules! temperature {
27 ($value:literal, $unit:expr) => {{
28 let mut unit = EngUnit::new();
29 unit.value = $value;
30 unit.temperature_count = 1;
31 if $unit == TemperatureDeltaUnit::None {
32 unit.temperature_count = 0;
33 }
34 unit.temperature_unit = $unit;
35 unit
36 }};
37}
38
39#[derive(Copy, Clone, Debug, PartialEq)]
40pub enum TemperatureDeltaUnit {
41 C,
42 R,
43 F,
44 K,
45 None,
46}
47
48impl<
49 T: IsEngUnitType
50 + Into<AmountOfSubstanceUnit>
51 + Into<ElectricCurrentUnit>
52 + Into<LengthUnit>
53 + Into<LuminousIntensityUnit>
54 + Into<MassUnit>
55 + Into<TemperatureDeltaUnit>
56 + Into<TimeUnit>,
57 > From<&T> for TemperatureDeltaUnit
58{
59 fn from(value: &T) -> Self {
60 if T::is_amount_unit() {
61 value.into()
62 } else {
63 Self::None
64 }
65 }
66}
67impl IsEngUnitType for TemperatureDeltaUnit {
68 fn is_temperature_unit() -> bool {
69 true
70 }
71}
72impl From<AmountOfSubstanceUnit> for TemperatureDeltaUnit {
73 fn from(_: AmountOfSubstanceUnit) -> Self {
74 TemperatureDeltaUnit::None
75 }
76}
77impl From<ElectricCurrentUnit> for TemperatureDeltaUnit {
78 fn from(_: ElectricCurrentUnit) -> Self {
79 TemperatureDeltaUnit::None
80 }
81}
82impl From<LengthUnit> for TemperatureDeltaUnit {
83 fn from(_: LengthUnit) -> Self {
84 TemperatureDeltaUnit::None
85 }
86}
87impl From<LuminousIntensityUnit> for TemperatureDeltaUnit {
88 fn from(_: LuminousIntensityUnit) -> Self {
89 TemperatureDeltaUnit::None
90 }
91}
92impl From<MassUnit> for TemperatureDeltaUnit {
93 fn from(_: MassUnit) -> Self {
94 TemperatureDeltaUnit::None
95 }
96}
97impl From<TimeUnit> for TemperatureDeltaUnit {
98 fn from(_: TimeUnit) -> Self {
99 TemperatureDeltaUnit::None
100 }
101}
102
103impl TemperatureDeltaUnit {
104 pub fn to_string(&self) -> &'static str {
105 match self {
106 TemperatureDeltaUnit::R => "R",
107 TemperatureDeltaUnit::K => "K",
108 TemperatureDeltaUnit::C => "°C",
109 TemperatureDeltaUnit::F => "°F",
110 TemperatureDeltaUnit::None => "",
111 }
112 }
113
114 pub fn to_latex(&self) -> &'static str {
115 match self {
116 TemperatureDeltaUnit::R => "R",
117 TemperatureDeltaUnit::K => "K",
118 TemperatureDeltaUnit::C => "^\\circ C",
119 TemperatureDeltaUnit::F => "^\\circ F",
120 TemperatureDeltaUnit::None => "",
121 }
122 }
123
124 pub fn conversion_factor(from: &TemperatureDeltaUnit, to: &TemperatureDeltaUnit) -> f64 {
125 match from {
126 TemperatureDeltaUnit::R => match to {
127 TemperatureDeltaUnit::R => 1.0,
128 TemperatureDeltaUnit::K => 5.0 / 9.0,
129 TemperatureDeltaUnit::F => 1.0,
130 TemperatureDeltaUnit::C => 5.0 / 9.0,
131 TemperatureDeltaUnit::None => 1.0,
132 },
133 TemperatureDeltaUnit::F => match to {
134 TemperatureDeltaUnit::R => 1.0,
135 TemperatureDeltaUnit::K => 5.0 / 9.0,
136 TemperatureDeltaUnit::F => 1.0,
137 TemperatureDeltaUnit::C => 5.0 / 9.0,
138 TemperatureDeltaUnit::None => 1.0,
139 },
140 TemperatureDeltaUnit::K => match to {
141 TemperatureDeltaUnit::R => 9.0 / 5.0,
142 TemperatureDeltaUnit::K => 1.0,
143 TemperatureDeltaUnit::F => 9.0 / 5.0,
144 TemperatureDeltaUnit::C => 1.0,
145 TemperatureDeltaUnit::None => 1.0,
146 },
147 TemperatureDeltaUnit::C => match to {
148 TemperatureDeltaUnit::R => 9.0 / 5.0,
149 TemperatureDeltaUnit::K => 1.0,
150 TemperatureDeltaUnit::F => 9.0 / 5.0,
151 TemperatureDeltaUnit::C => 1.0,
152 TemperatureDeltaUnit::None => 1.0,
153 },
154 TemperatureDeltaUnit::None => 1.0,
155 }
156 }
157}
158
159#[cfg(test)]
160mod tests {
161 use crate::units::amount_of_substance_unit::AmountOfSubstanceUnit;
162 use crate::units::electric_current_unit::ElectricCurrentUnit;
163 use crate::units::length_unit::LengthUnit;
164 use crate::units::luminous_intensity_unit::LuminousIntensityUnit;
165 use crate::units::mass_unit::MassUnit;
166 use crate::units::temperature_unit::TemperatureDeltaUnit;
167 use crate::units::time_unit::TimeUnit;
168 use crate::units::EngUnit;
169
170 #[test]
171 fn conversion_r_to_r() {
172 let val = TemperatureDeltaUnit::conversion_factor(
173 &TemperatureDeltaUnit::R,
174 &TemperatureDeltaUnit::R,
175 );
176 assert_eq!(1.0, val);
177 }
178
179 #[test]
180 fn conversion_f_to_f() {
181 let val = TemperatureDeltaUnit::conversion_factor(
182 &TemperatureDeltaUnit::F,
183 &TemperatureDeltaUnit::F,
184 );
185 assert_eq!(1.0, val);
186 }
187
188 #[test]
189 fn conversion_k_to_k() {
190 let val = TemperatureDeltaUnit::conversion_factor(
191 &TemperatureDeltaUnit::K,
192 &TemperatureDeltaUnit::K,
193 );
194 assert_eq!(1.0, val);
195 }
196
197 #[test]
198 fn conversion_k_to_f() {
199 let val = TemperatureDeltaUnit::conversion_factor(
200 &TemperatureDeltaUnit::K,
201 &TemperatureDeltaUnit::F,
202 );
203 assert_eq!(9.0 / 5.0, val);
204 }
205
206 #[test]
207 fn conversion_r_to_c() {
208 let val = TemperatureDeltaUnit::conversion_factor(
209 &TemperatureDeltaUnit::R,
210 &TemperatureDeltaUnit::C,
211 );
212 assert_eq!(5.0 / 9.0, val);
213 }
214
215 #[test]
216 fn conversion_r_to_none() {
217 let val = TemperatureDeltaUnit::conversion_factor(
218 &TemperatureDeltaUnit::R,
219 &TemperatureDeltaUnit::None,
220 );
221 assert_eq!(1.0, val);
222 }
223
224 #[test]
225 fn conversion_f_to_none() {
226 let val = TemperatureDeltaUnit::conversion_factor(
227 &TemperatureDeltaUnit::F,
228 &TemperatureDeltaUnit::None,
229 );
230 assert_eq!(1.0, val);
231 }
232
233 #[test]
234 fn conversion_c_to_none() {
235 let val = TemperatureDeltaUnit::conversion_factor(
236 &TemperatureDeltaUnit::C,
237 &TemperatureDeltaUnit::None,
238 );
239 assert_eq!(1.0, val);
240 }
241
242 #[test]
243 fn conversion_c_to_f() {
244 let val = TemperatureDeltaUnit::conversion_factor(
245 &TemperatureDeltaUnit::C,
246 &TemperatureDeltaUnit::F,
247 );
248 assert_eq!(9.0 / 5.0, val);
249 }
250
251 #[test]
252 fn conversion_f_to_c() {
253 let val = TemperatureDeltaUnit::conversion_factor(
254 &TemperatureDeltaUnit::F,
255 &TemperatureDeltaUnit::C,
256 );
257 assert_eq!(5.0 / 9.0, val);
258 }
259
260 #[test]
261 fn conversion_c_to_k() {
262 let val = TemperatureDeltaUnit::conversion_factor(
263 &TemperatureDeltaUnit::C,
264 &TemperatureDeltaUnit::K,
265 );
266 assert_eq!(1.0, val);
267 }
268
269 #[test]
270 fn conversion_k_to_c() {
271 let val = TemperatureDeltaUnit::conversion_factor(
272 &TemperatureDeltaUnit::K,
273 &TemperatureDeltaUnit::C,
274 );
275 assert_eq!(1.0, val);
276 }
277
278 #[test]
279 fn conversion_k_to_r() {
280 let val = TemperatureDeltaUnit::conversion_factor(
281 &TemperatureDeltaUnit::K,
282 &TemperatureDeltaUnit::R,
283 );
284 assert_eq!(9.0 / 5.0, val);
285 }
286
287 #[test]
288 fn conversion_r_to_k() {
289 let val = TemperatureDeltaUnit::conversion_factor(
290 &TemperatureDeltaUnit::R,
291 &TemperatureDeltaUnit::K,
292 );
293 assert_eq!(5.0 / 9.0, val);
294 }
295
296 #[test]
297 fn conversion_c_to_r() {
298 let val = TemperatureDeltaUnit::conversion_factor(
299 &TemperatureDeltaUnit::C,
300 &TemperatureDeltaUnit::R,
301 );
302 assert_eq!(9.0 / 5.0, val);
303 }
304
305 #[test]
306 fn conversion_f_to_k() {
307 let val = TemperatureDeltaUnit::conversion_factor(
308 &TemperatureDeltaUnit::F,
309 &TemperatureDeltaUnit::K,
310 );
311 assert_eq!(5.0 / 9.0, val);
312 }
313
314 #[test]
315 fn conversion_f_to_r() {
316 let val = TemperatureDeltaUnit::conversion_factor(
317 &TemperatureDeltaUnit::F,
318 &TemperatureDeltaUnit::R,
319 );
320 assert_eq!(1.0, val);
321 }
322
323 #[test]
324 fn conversion_r_to_f() {
325 let val = TemperatureDeltaUnit::conversion_factor(
326 &TemperatureDeltaUnit::R,
327 &TemperatureDeltaUnit::F,
328 );
329 assert_eq!(1.0, val);
330 }
331
332 #[test]
333 fn from_is_none() {
334 let val = TemperatureDeltaUnit::conversion_factor(
335 &TemperatureDeltaUnit::None,
336 &TemperatureDeltaUnit::K,
337 );
338 assert_eq!(1.0, val);
339 }
340
341 #[test]
342 fn to_is_none() {
343 let val = TemperatureDeltaUnit::conversion_factor(
344 &TemperatureDeltaUnit::K,
345 &TemperatureDeltaUnit::None,
346 );
347 assert_eq!(1.0, val);
348 }
349
350 #[test]
351 fn both_are_none() {
352 let val = TemperatureDeltaUnit::conversion_factor(
353 &TemperatureDeltaUnit::None,
354 &TemperatureDeltaUnit::None,
355 );
356 assert_eq!(1.0, val);
357 }
358
359 #[test]
360 fn macro_create_temperature_1() {
361 let unit = temperature!(123.45, TemperatureDeltaUnit::C);
362 assert_eq!(123.45, unit.value);
363 assert_eq!("123.45 °C", unit.to_string());
364 assert_eq!(TimeUnit::None, unit.time_unit);
365 assert_eq!(AmountOfSubstanceUnit::None, unit.amount_of_substance_unit);
366 assert_eq!(ElectricCurrentUnit::None, unit.electric_current_unit);
367 assert_eq!(LengthUnit::None, unit.length_unit);
368 assert_eq!(LuminousIntensityUnit::None, unit.luminous_intensity_unit);
369 assert_eq!(MassUnit::None, unit.mass_unit);
370 assert_eq!(TemperatureDeltaUnit::C, unit.temperature_unit);
371 assert_eq!(TimeUnit::None, unit.time_unit);
372 assert_eq!(1, unit.temperature_count);
373 assert_eq!(0, unit.time_count);
374 assert_eq!(0, unit.length_count);
375 assert_eq!(0, unit.mass_count);
376 assert_eq!(0, unit.luminous_intensity_count);
377 assert_eq!(0, unit.amount_of_substance_count);
378 assert_eq!(0, unit.electric_current_count);
379 }
380
381 #[test]
382 fn macro_create_temperature_2() {
383 let unit = temperature!(123.45, TemperatureDeltaUnit::K);
384 assert_eq!(123.45, unit.value);
385 assert_eq!("123.45 K", unit.to_string());
386 assert_eq!(TimeUnit::None, unit.time_unit);
387 assert_eq!(AmountOfSubstanceUnit::None, unit.amount_of_substance_unit);
388 assert_eq!(ElectricCurrentUnit::None, unit.electric_current_unit);
389 assert_eq!(LengthUnit::None, unit.length_unit);
390 assert_eq!(LuminousIntensityUnit::None, unit.luminous_intensity_unit);
391 assert_eq!(MassUnit::None, unit.mass_unit);
392 assert_eq!(TemperatureDeltaUnit::K, unit.temperature_unit);
393 assert_eq!(TimeUnit::None, unit.time_unit);
394 assert_eq!(1, unit.temperature_count);
395 assert_eq!(0, unit.time_count);
396 assert_eq!(0, unit.length_count);
397 assert_eq!(0, unit.mass_count);
398 assert_eq!(0, unit.luminous_intensity_count);
399 assert_eq!(0, unit.amount_of_substance_count);
400 assert_eq!(0, unit.electric_current_count);
401 }
402
403 #[test]
404 fn macro_create_temperature_3() {
405 let unit = temperature!(123.45, TemperatureDeltaUnit::F);
406 assert_eq!(123.45, unit.value);
407 assert_eq!("123.45 °F", unit.to_string());
408 assert_eq!(TimeUnit::None, unit.time_unit);
409 assert_eq!(AmountOfSubstanceUnit::None, unit.amount_of_substance_unit);
410 assert_eq!(ElectricCurrentUnit::None, unit.electric_current_unit);
411 assert_eq!(LengthUnit::None, unit.length_unit);
412 assert_eq!(LuminousIntensityUnit::None, unit.luminous_intensity_unit);
413 assert_eq!(MassUnit::None, unit.mass_unit);
414 assert_eq!(TemperatureDeltaUnit::F, unit.temperature_unit);
415 assert_eq!(TimeUnit::None, unit.time_unit);
416 assert_eq!(1, unit.temperature_count);
417 assert_eq!(0, unit.time_count);
418 assert_eq!(0, unit.length_count);
419 assert_eq!(0, unit.mass_count);
420 assert_eq!(0, unit.luminous_intensity_count);
421 assert_eq!(0, unit.amount_of_substance_count);
422 assert_eq!(0, unit.electric_current_count);
423 }
424
425 #[test]
426 fn macro_create_temperature_4() {
427 let unit = temperature!(123.45, TemperatureDeltaUnit::R);
428 assert_eq!(123.45, unit.value);
429 assert_eq!("123.45 R", unit.to_string());
430 assert_eq!(TimeUnit::None, unit.time_unit);
431 assert_eq!(AmountOfSubstanceUnit::None, unit.amount_of_substance_unit);
432 assert_eq!(ElectricCurrentUnit::None, unit.electric_current_unit);
433 assert_eq!(LengthUnit::None, unit.length_unit);
434 assert_eq!(LuminousIntensityUnit::None, unit.luminous_intensity_unit);
435 assert_eq!(MassUnit::None, unit.mass_unit);
436 assert_eq!(TemperatureDeltaUnit::R, unit.temperature_unit);
437 assert_eq!(TimeUnit::None, unit.time_unit);
438 assert_eq!(1, unit.temperature_count);
439 assert_eq!(0, unit.time_count);
440 assert_eq!(0, unit.length_count);
441 assert_eq!(0, unit.mass_count);
442 assert_eq!(0, unit.luminous_intensity_count);
443 assert_eq!(0, unit.amount_of_substance_count);
444 assert_eq!(0, unit.electric_current_count);
445 }
446
447 #[test]
448 fn macro_create_temperature_5() {
449 let unit = temperature!(123.45, TemperatureDeltaUnit::None);
450 assert_eq!(123.45, unit.value);
451 assert_eq!("123.45", unit.to_string());
452 assert_eq!(TimeUnit::None, unit.time_unit);
453 assert_eq!(AmountOfSubstanceUnit::None, unit.amount_of_substance_unit);
454 assert_eq!(ElectricCurrentUnit::None, unit.electric_current_unit);
455 assert_eq!(LengthUnit::None, unit.length_unit);
456 assert_eq!(LuminousIntensityUnit::None, unit.luminous_intensity_unit);
457 assert_eq!(MassUnit::None, unit.mass_unit);
458 assert_eq!(TemperatureDeltaUnit::None, unit.temperature_unit);
459 assert_eq!(TimeUnit::None, unit.time_unit);
460 assert_eq!(0, unit.temperature_count);
461 assert_eq!(0, unit.time_count);
462 assert_eq!(0, unit.length_count);
463 assert_eq!(0, unit.mass_count);
464 assert_eq!(0, unit.luminous_intensity_count);
465 assert_eq!(0, unit.amount_of_substance_count);
466 assert_eq!(0, unit.electric_current_count);
467 }
468
469 #[test]
470 fn test_unit_strings() {
471 let unit = temperature!(123.45, TemperatureDeltaUnit::C);
472 assert_eq!("°C", unit.unit_to_string());
473 let unit = temperature!(123.45, TemperatureDeltaUnit::K);
474 assert_eq!("K", unit.unit_to_string());
475 let unit = temperature!(123.45, TemperatureDeltaUnit::R);
476 assert_eq!("R", unit.unit_to_string());
477 let unit = temperature!(123.45, TemperatureDeltaUnit::F);
478 assert_eq!("°F", unit.unit_to_string());
479 let unit = temperature!(123.45, TemperatureDeltaUnit::None);
480 assert_eq!("", unit.unit_to_string());
481 }
482
483 #[test]
484 fn test_unit_strings_2() {
485 assert_eq!("°C", TemperatureDeltaUnit::C.to_string());
486 assert_eq!("°F", TemperatureDeltaUnit::F.to_string());
487 assert_eq!("R", TemperatureDeltaUnit::R.to_string());
488 assert_eq!("K", TemperatureDeltaUnit::K.to_string());
489 assert_eq!("", TemperatureDeltaUnit::None.to_string());
490 }
491
492 #[test]
493 fn unit_clone() {
494 let unit = temperature!(123.45, TemperatureDeltaUnit::R);
495 let unit_2 = unit.clone();
496 assert_eq!(123.45, unit_2.value);
497 assert_eq!("123.45 R", unit_2.to_string());
498 assert_eq!(TimeUnit::None, unit_2.time_unit);
499 assert_eq!(AmountOfSubstanceUnit::None, unit_2.amount_of_substance_unit);
500 assert_eq!(ElectricCurrentUnit::None, unit_2.electric_current_unit);
501 assert_eq!(LengthUnit::None, unit_2.length_unit);
502 assert_eq!(LuminousIntensityUnit::None, unit_2.luminous_intensity_unit);
503 assert_eq!(MassUnit::None, unit_2.mass_unit);
504 assert_eq!(TemperatureDeltaUnit::R, unit_2.temperature_unit);
505 assert_eq!(TimeUnit::None, unit_2.time_unit);
506 assert_eq!(1, unit_2.temperature_count);
507 assert_eq!(0, unit_2.time_count);
508 assert_eq!(0, unit_2.length_count);
509 assert_eq!(0, unit_2.mass_count);
510 assert_eq!(0, unit_2.luminous_intensity_count);
511 assert_eq!(0, unit_2.amount_of_substance_count);
512 assert_eq!(0, unit_2.electric_current_count);
513 }
514
515 #[test]
516 fn test_equality() {
517 let a = temperature!(123.45, TemperatureDeltaUnit::K);
518 let b = temperature!(123.45, TemperatureDeltaUnit::K);
519 assert_eq!(a.temperature_unit, b.temperature_unit);
520
521 let a = temperature!(123.45, TemperatureDeltaUnit::C);
522 let b = temperature!(123.45, TemperatureDeltaUnit::C);
523 assert_eq!(a.temperature_unit, b.temperature_unit);
524
525 let a = temperature!(123.45, TemperatureDeltaUnit::R);
526 let b = temperature!(123.45, TemperatureDeltaUnit::R);
527 assert_eq!(a.temperature_unit, b.temperature_unit);
528
529 let a = temperature!(123.45, TemperatureDeltaUnit::F);
530 let b = temperature!(123.45, TemperatureDeltaUnit::F);
531 assert_eq!(a.temperature_unit, b.temperature_unit);
532 }
533
534 #[test]
535 fn test_debug() {
536 let a = temperature!(123.45, TemperatureDeltaUnit::K);
537 let s = format!("{a:?}");
538 assert!(!s.is_empty())
539 }
540
541 #[test]
542 fn test_latex_1() {
543 let a = temperature!(123.45, TemperatureDeltaUnit::K);
544 assert_eq!("$123.45\\ K$", a.to_latex());
545 }
546
547 #[test]
548 fn test_latex_2() {
549 let a = temperature!(123.45, TemperatureDeltaUnit::R);
550 assert_eq!("$123.45\\ R$", a.to_latex());
551 }
552
553 #[test]
554 fn test_latex_3() {
555 let a = temperature!(123.45, TemperatureDeltaUnit::C);
556 assert_eq!("$123.45\\ ^\\circ C$", a.to_latex());
557 }
558
559 #[test]
560 fn test_latex_4() {
561 let a = temperature!(123.45, TemperatureDeltaUnit::F);
562 assert_eq!("$123.45\\ ^\\circ F$", a.to_latex());
563 }
564
565 #[test]
566 fn test_latex_5() {
567 let a = temperature!(123.45, TemperatureDeltaUnit::None);
568 assert_eq!("$123.45$", a.to_latex());
569 }
570}