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
|
use std::fmt::{Display, Formatter, Result};
use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
use crate::metric::Unit;
use crate::metric::Primitive;
use crate::declare_unit_basics;
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
pub enum ThermodynamicTemperature {
Base(f64, fn(f64) -> f64, &'static str),
Canonical(f64),
Kelvin(f64),
}
impl Unit<ThermodynamicTemperature> for ThermodynamicTemperature {
fn to_si_unit(&self) -> ThermodynamicTemperature {
match self {
ThermodynamicTemperature::Base(_, _, _) => self.clone(),
ThermodynamicTemperature::Canonical(value) => ThermodynamicTemperature::Base(value.clone(), |x| x, "K"),
ThermodynamicTemperature::Kelvin(value) => ThermodynamicTemperature::Base(value.clone(), |x| x, "K"),
}
}
}
declare_unit_basics!(ThermodynamicTemperature);
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
pub enum CelsiusTemperature {
Base(f64, fn(f64) -> f64, &'static str),
Canonical(f64),
Celsius(f64),
Fahrenheit(f64),
}
impl Unit<CelsiusTemperature> for CelsiusTemperature {
fn to_si_unit(&self) -> CelsiusTemperature {
match self {
CelsiusTemperature::Base(_, _, _) => self.clone(),
CelsiusTemperature::Canonical(value) => CelsiusTemperature::Base(value.clone(), |x| x, "K"),
CelsiusTemperature::Celsius(value) => CelsiusTemperature::Base(value.clone(), |x| x, "°C"),
CelsiusTemperature::Fahrenheit(value) => CelsiusTemperature::Base((value - 32.0) / 1.8 , |x| x * 1.8 + 32.0, "°F"),
}
}
}
declare_unit_basics!(CelsiusTemperature);
/* --- temperature interoperability: C +/- K --- */
impl Add<ThermodynamicTemperature> for CelsiusTemperature {
type Output = CelsiusTemperature;
fn add(self, rhs: ThermodynamicTemperature) -> Self::Output {
match self.to_si_unit() {
CelsiusTemperature::Base(value, from_si, symbol) => CelsiusTemperature::Base(value + rhs.to_si_primitive(), from_si, symbol),
_ => panic!("non si unit post to_si_unit() call")
}
}
}
impl AddAssign<ThermodynamicTemperature> for CelsiusTemperature {
fn add_assign(&mut self, rhs: ThermodynamicTemperature) {
match self.to_si_unit() {
CelsiusTemperature::Base(value, from_si, symbol) => *self = CelsiusTemperature::Base(value + rhs.to_si_primitive(), from_si, symbol),
_ => panic!("non si unit post to_si_unit() call")
}
}
}
impl Sub<ThermodynamicTemperature> for CelsiusTemperature {
type Output = CelsiusTemperature;
fn sub(self, rhs: ThermodynamicTemperature) -> Self::Output {
match self.to_si_unit() {
CelsiusTemperature::Base(value, from_si, symbol) => CelsiusTemperature::Base(value + rhs.to_si_primitive(), from_si, symbol),
_ => panic!("non si unit post to_si_unit() call")
}
}
}
impl SubAssign<ThermodynamicTemperature> for CelsiusTemperature {
fn sub_assign(&mut self, rhs: ThermodynamicTemperature) {
match self.to_si_unit() {
CelsiusTemperature::Base(value, from_si, symbol) => *self = CelsiusTemperature::Base(value - rhs.to_si_primitive(), from_si, symbol),
_ => panic!("non si unit post to_si_unit() call")
}
}
}
|