Skip to main content

uom/si/
thermodynamic_temperature.rs

1//! Thermodynamic temperature (base unit kelvin, K).
2//!
3//! Thermodynamic temperature has the same dimensions as [temperature
4//! interval](../temperature_interval/index.html) but is not directly comparable. Thermodynamic
5//! temperature is the absolute measure of temperature and is one of the [base quantities][base] in
6//! the [ISQ][isq]. Temperature interval is the measure of relative temperature difference between
7//! thermodynamic temperatures.
8//!
9#![cfg_attr(feature = "f32", doc = " ```rust,compile_fail")]
10#![cfg_attr(not(feature = "f32"), doc = " ```rust,ignore")]
11//! # use uom::si::{temperature_interval, thermodynamic_temperature};
12//! # use uom::si::f32::*;
13//! let tt = ThermodynamicTemperature::new::<thermodynamic_temperature::kelvin>(1.0);
14//! let ti = TemperatureInterval::new::<temperature_interval::kelvin>(1.0);
15//!
16//! // error[E0308]: mismatched types
17//! let err = tt == ti;
18//! ```
19//!
20//! Additionally, addition and subtraction are not implemented for thermodynamic temperature.
21//!
22#![cfg_attr(feature = "f32", doc = " ```rust,compile_fail")]
23#![cfg_attr(not(feature = "f32"), doc = " ```rust,ignore")]
24//! # use uom::si::{temperature_interval, thermodynamic_temperature};
25//! # use uom::si::f32::*;
26//! let t1 = ThermodynamicTemperature::new::<thermodynamic_temperature::kelvin>(1.0);
27//! let t2 = ThermodynamicTemperature::new::<thermodynamic_temperature::kelvin>(1.0);
28//!
29//! // error[E0308]: mismatched types
30//! let err = t1 + t2;
31//! ```
32//!
33//! A temperature interval can be added to or subtracted from a thermodynamic temperature.
34//!
35#![cfg_attr(all(feature = "si", feature = "f32"), doc = " ```rust")]
36#![cfg_attr(not(all(feature = "si", feature = "f32")), doc = " ```rust,ignore")]
37//! # use uom::si::{temperature_interval, thermodynamic_temperature};
38//! # use uom::si::f32::*;
39//! let tt = ThermodynamicTemperature::new::<thermodynamic_temperature::kelvin>(1.0);
40//! let ti = TemperatureInterval::new::<temperature_interval::kelvin>(1.0);
41//!
42//! let result = tt + ti;
43//! ```
44//!
45//! [base]: https://jcgm.bipm.org/vim/en/1.4.html
46//! [isq]: https://jcgm.bipm.org/vim/en/1.6.html
47
48use crate::si::temperature_interval::TemperatureInterval;
49
50quantity! {
51    /// Thermodynamic temperature (base unit kelvin, K).
52    quantity: ThermodynamicTemperature; "thermodynamic temperature";
53    /// Dimension of thermodynamic temperature, Th (base unit kelvin, K).
54    dimension: ISQ<
55        Z0,     // length
56        Z0,     // mass
57        Z0,     // time
58        Z0,     // electric current
59        P1,     // thermodynamic temperature
60        Z0,     // amount of substance
61        Z0>;    // luminous intensity
62    kind: dyn crate::si::marker::TemperatureKind;
63    units {
64        @yottakelvin: prefix!(yotta); "YK", "yottakelvin", "yottakelvins";
65        @zettakelvin: prefix!(zetta); "ZK", "zettakelvin", "zettakelvins";
66        @exakelvin: prefix!(exa); "EK", "exakelvin", "exakelvins";
67        @petakelvin: prefix!(peta); "PK", "petakelvin", "petakelvins";
68        @terakelvin: prefix!(tera); "TK", "terakelvin", "terakelvins";
69        @gigakelvin: prefix!(giga); "GK", "gigakelvin", "gigakelvins";
70        @megakelvin: prefix!(mega); "MK", "megakelvin", "megakelvins";
71        @kilokelvin: prefix!(kilo); "kK", "kilokelvin", "kilokelvins";
72        @hectokelvin: prefix!(hecto); "hK", "hectokelvin", "hectokelvins";
73        @decakelvin: prefix!(deca); "daK", "decakelvin", "decakelvins";
74        /// The kelvin is the SI unit of thermodynamic temperature. It is defined by taking the
75        /// fixed numerical value of the Boltzmann constant *k* to be 1.380 649 × 10⁻²³ when
76        /// expressed in the unit J K⁻¹, which is equal to kg m² s⁻² K⁻¹, where the kilogram, meter,
77        /// and second are defined in terms of *h*, *c*, and ∆*ν*<sub>Cs</sub>.
78        @kelvin: prefix!(none); "K", "kelvin", "kelvins";
79        @decikelvin: prefix!(deci); "dK", "decikelvin", "decikelvins";
80        @centikelvin: prefix!(centi); "cK", "centikelvin", "centikelvins";
81        @millikelvin: prefix!(milli); "mK", "millikelvin", "millikelvins";
82        @microkelvin: prefix!(micro); "µK", "microkelvin", "microkelvins";
83        @nanokelvin: prefix!(nano); "nK", "nanokelvin", "nanokelvins";
84        @picokelvin: prefix!(pico); "pK", "picokelvin", "picokelvins";
85        @femtokelvin: prefix!(femto); "fK", "femtokelvin", "femtokelvins";
86        @attokelvin: prefix!(atto); "aK", "attokelvin", "attokelvins";
87        @zeptokelvin: prefix!(zepto); "zK", "zeptokelvin", "zeptokelvins";
88        @yoctokelvin: prefix!(yocto); "yK", "yoctokelvin", "yoctokelvins";
89
90        @degree_celsius: 1.0_E0, 273.15_E0; "°C", "degree Celsius", "degrees Celsius";
91        @degree_fahrenheit: 5.0_E0 / 9.0_E0, 459.67_E0; "°F", "degree Fahrenheit",
92            "degrees Fahrenheit";
93        @degree_rankine: 5.0_E0 / 9.0_E0; "°R", "degree Rankine", "degrees Rankine";
94    }
95}
96
97#[doc(hidden)]
98macro_rules! impl_ops {
99    (
100        $AddSubTrait:ident, $addsub_fun:ident, $addsub_op:tt,
101        $AddSubAssignTrait:ident, $addsubassign_fun:ident, $addsubassign_op:tt,
102        $AddSubAlias:ident
103    ) => {
104        #[cfg(feature = "autoconvert")]
105        impl<Ul, Ur, V> $crate::lib::ops::$AddSubTrait<TemperatureInterval<Ur, V>>
106            for ThermodynamicTemperature<Ul, V>
107        where
108            Ul: super::Units<V> + ?Sized,
109            Ur: super::Units<V> + ?Sized,
110            V: $crate::num::Num + $crate::Conversion<V>,
111        {
112            type Output = ThermodynamicTemperature<Ul, V>;
113
114            #[inline(always)]
115            fn $addsub_fun(self, rhs: TemperatureInterval<Ur, V>) -> Self::Output {
116                super::Quantity {
117                    dimension: $crate::lib::marker::PhantomData,
118                    units: $crate::lib::marker::PhantomData,
119                    value: self.value
120                        $addsub_op super::change_base::<Dimension, Ul, Ur, V>(&rhs.value),
121                }
122            }
123        }
124
125        #[cfg(not(feature = "autoconvert"))]
126        impl<U, V> $crate::lib::ops::$AddSubTrait<TemperatureInterval<U, V>>
127            for ThermodynamicTemperature<U, V>
128        where
129            U: super::Units<V> + ?Sized,
130            V: $crate::num::Num + $crate::Conversion<V>,
131        {
132            type Output = ThermodynamicTemperature<U, V>;
133
134            #[inline(always)]
135            fn $addsub_fun(self, rhs: TemperatureInterval<U, V>) -> Self::Output {
136                super::Quantity {
137                    dimension: $crate::lib::marker::PhantomData,
138                    units: $crate::lib::marker::PhantomData,
139                    value: self.value $addsub_op rhs.value,
140                }
141            }
142        }
143
144        #[cfg(feature = "autoconvert")]
145        impl<Ul, Ur, V> $crate::lib::ops::$AddSubAssignTrait<TemperatureInterval<Ur, V>>
146            for ThermodynamicTemperature<Ul, V>
147        where
148            Ul: super::Units<V> + ?Sized,
149            Ur: super::Units<V> + ?Sized,
150            V: $crate::num::Num + $crate::Conversion<V> + $crate::lib::ops::$AddSubAssignTrait<V>,
151        {
152            #[inline(always)]
153            fn $addsubassign_fun(&mut self, rhs: TemperatureInterval<Ur, V>) {
154                self.value $addsubassign_op super::change_base::<Dimension, Ul, Ur, V>(&rhs.value);
155            }
156        }
157
158        #[cfg(not(feature = "autoconvert"))]
159        impl<U, V> $crate::lib::ops::$AddSubAssignTrait<TemperatureInterval<U, V>>
160            for ThermodynamicTemperature<U, V>
161        where
162            U: super::Units<V> + ?Sized,
163            V: $crate::num::Num + $crate::Conversion<V> + $crate::lib::ops::$AddSubAssignTrait<V>,
164        {
165            #[inline(always)]
166            fn $addsubassign_fun(&mut self, rhs: TemperatureInterval<U, V>) {
167                self.value $addsubassign_op rhs.value;
168            }
169        }
170    };
171}
172
173impl_ops!(Add, add, +, AddAssign, add_assign, +=, Sum);
174impl_ops!(Sub, sub, -, SubAssign, sub_assign, -=, Diff);
175
176#[cfg(test)]
177mod tests {
178    use crate::si::quantities::*;
179    use crate::si::temperature_interval as ti;
180    use crate::si::thermodynamic_temperature as tt;
181
182    storage_types! {
183        use crate::tests::*;
184        use super::*;
185
186        quickcheck! {
187            #[allow(trivial_casts)]
188            fn add(l: A<V>, r: A<V>) -> bool {
189                Test::eq(&ThermodynamicTemperature::<V>::new::<tt::kelvin>(&*l + &*r),
190                    &(ThermodynamicTemperature::<V>::new::<tt::kelvin>((*l).clone())
191                        + TemperatureInterval::<V>::new::<ti::kelvin>((*r).clone())))
192            }
193
194            #[allow(trivial_casts)]
195            fn sub(l: A<V>, r: A<V>) -> bool {
196                Test::eq(&ThermodynamicTemperature::<V>::new::<tt::kelvin>(&*l - &*r),
197                    &(ThermodynamicTemperature::<V>::new::<tt::kelvin>((*l).clone())
198                        - TemperatureInterval::<V>::new::<ti::kelvin>((*r).clone())))
199            }
200        }
201    }
202
203    mod non_big {
204        storage_types! {
205            types: PrimInt, Rational, Rational32, Rational64, Float;
206
207            use crate::tests::*;
208            use super::super::*;
209
210            quickcheck! {
211                #[allow(trivial_casts)]
212                fn add_assign(l: A<V>, r: A<V>) -> bool {
213                    let mut f = *l;
214                    let mut v = ThermodynamicTemperature::<V>::new::<tt::kelvin>(*l);
215
216                    f += *r;
217                    v += TemperatureInterval::<V>::new::<ti::kelvin>(*r);
218
219                    Test::approx_eq(&ThermodynamicTemperature::<V>::new::<tt::kelvin>(f), &v)
220                }
221
222                #[allow(trivial_casts)]
223                fn sub_assign(l: A<V>, r: A<V>) -> bool {
224                    let mut f = *l;
225                    let mut v = ThermodynamicTemperature::<V>::new::<tt::kelvin>(*l);
226
227                    f -= *r;
228                    v -= TemperatureInterval::<V>::new::<ti::kelvin>(*r);
229
230                    Test::approx_eq(&ThermodynamicTemperature::<V>::new::<tt::kelvin>(f), &v)
231                }
232            }
233        }
234    }
235}