1use crate::{Quantity, Unit};
19use qtty_derive::Unit;
20
21pub use crate::dimension::Power;
23
24pub trait PowerUnit: Unit<Dim = Power> {}
26impl<T: Unit<Dim = Power>> PowerUnit for T {}
27
28#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
30#[unit(symbol = "W", dimension = Power, ratio = 1.0)]
31pub struct Watt;
32pub type W = Watt;
34pub type Watts = Quantity<W>;
36pub const WATT: Watts = Watts::new(1.0);
38
39macro_rules! si_watt {
40 ($name:ident, $sym:literal, $ratio:expr, $alias:ident, $qty:ident, $one:ident) => {
41 #[doc = concat!("SI-prefixed watt unit (", stringify!($ratio), " W).")]
42 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
43 #[unit(symbol = $sym, dimension = Power, ratio = $ratio)]
44 pub struct $name;
45 #[doc = concat!("Type alias shorthand for [`", stringify!($name), "`].")]
46 pub type $alias = $name;
47 #[doc = concat!("A quantity measured in ", stringify!($name), "s.")]
48 pub type $qty = Quantity<$alias>;
49 #[doc = concat!("One ", stringify!($name), ".")]
50 pub const $one: $qty = $qty::new(1.0);
51 };
52}
53
54si_watt!(Yoctowatt, "yW", 1e-24, Yw, Yoctowatts, YW);
56si_watt!(Zeptowatt, "zW", 1e-21, Zw, Zeptowatts, ZW);
57si_watt!(Attowatt, "aW", 1e-18, Aw, Attowatts, AW);
58si_watt!(Femtowatt, "fW", 1e-15, Fw, Femtowatts, FW);
59si_watt!(Picowatt, "pW", 1e-12, Pw, Picowatts, PW);
60si_watt!(Nanowatt, "nW", 1e-9, Nw, Nanowatts, NW);
61si_watt!(Microwatt, "µW", 1e-6, Uw, Microwatts, UW);
62si_watt!(Milliwatt, "mW", 1e-3, Mw, Milliwatts, MW_1);
63
64si_watt!(Deciwatt, "dW", 1e-1, Dw, Deciwatts, DW);
65si_watt!(Decawatt, "daW", 1e1, Daw, Decawatts, DAW);
66si_watt!(Hectowatt, "hW", 1e2, Hw, Hectowatts, HW);
67si_watt!(Kilowatt, "kW", 1e3, Kw, Kilowatts, KW);
68si_watt!(Megawatt, "MW", 1e6, MW, Megawatts, MEGAWATT);
69si_watt!(Gigawatt, "GW", 1e9, GW, Gigawatts, GW_1);
70si_watt!(Terawatt, "TW", 1e12, TW, Terawatts, TW_1);
71si_watt!(Petawatt, "PW", 1e15, PW, Petawatts, PETAWATT);
72si_watt!(Exawatt, "EW", 1e18, EW, Exawatts, EW_1);
73si_watt!(Zettawatt, "ZW", 1e21, ZW, Zettawatts, ZW_1);
74si_watt!(Yottawatt, "YW", 1e24, YW, Yottawatts, YW_1);
75
76#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
80#[unit(symbol = "erg/s", dimension = Power, ratio = 1e-7)]
81pub struct ErgPerSecond;
82pub const ERG_PER_S: Quantity<ErgPerSecond> = Quantity::new(1.0);
84
85#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
87#[unit(symbol = "PS", dimension = Power, ratio = 73_549_875.0 / 100_000.0)]
88pub struct HorsepowerMetric;
89pub type HorsepowerMetrics = Quantity<HorsepowerMetric>;
91pub const PS: HorsepowerMetrics = HorsepowerMetrics::new(1.0);
93
94#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
96#[unit(symbol = "hp_e", dimension = Power, ratio = 746.0)]
97pub struct HorsepowerElectric;
98pub type HorsepowerElectrics = Quantity<HorsepowerElectric>;
100pub const HP_E: HorsepowerElectrics = HorsepowerElectrics::new(1.0);
102
103#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
107#[unit(symbol = "L☉", dimension = Power, ratio = 3.828e26)]
108pub struct SolarLuminosity;
109pub type SolarLuminosities = Quantity<SolarLuminosity>;
111pub const L_SUN: SolarLuminosities = SolarLuminosities::new(1.0);
113
114crate::impl_unit_conversions!(
116 Watt,
117 Yoctowatt,
118 Zeptowatt,
119 Attowatt,
120 Femtowatt,
121 Picowatt,
122 Nanowatt,
123 Microwatt,
124 Milliwatt,
125 Deciwatt,
126 Decawatt,
127 Hectowatt,
128 Kilowatt,
129 Megawatt,
130 Gigawatt,
131 Terawatt,
132 Petawatt,
133 Exawatt,
134 Zettawatt,
135 Yottawatt,
136 ErgPerSecond,
137 HorsepowerMetric,
138 HorsepowerElectric,
139 SolarLuminosity
140);
141
142#[cfg(test)]
143mod tests {
144 use super::*;
145 use approx::assert_relative_eq;
146 use proptest::prelude::*;
147
148 #[test]
153 fn solar_luminosity_to_watts() {
154 let sol = SolarLuminosities::new(1.0);
155 let w = sol.to::<Watt>();
156 assert_relative_eq!(w.value(), 3.828e26, max_relative = 1e-9);
158 }
159
160 #[test]
161 fn watts_to_solar_luminosity() {
162 let w = Watts::new(3.828e26);
163 let sol = w.to::<SolarLuminosity>();
164 assert_relative_eq!(sol.value(), 1.0, max_relative = 1e-9);
165 }
166
167 #[test]
168 fn multiple_solar_luminosities() {
169 let sol = SolarLuminosities::new(3.0);
170 let w = sol.to::<Watt>();
171 assert_relative_eq!(w.value(), 3.0 * 3.828e26, max_relative = 1e-9);
172 }
173
174 #[test]
179 fn solar_luminosity_ratio_sanity() {
180 assert_relative_eq!(SolarLuminosity::RATIO, 3.828e26, max_relative = 1e-9);
182 }
183
184 #[test]
185 fn solar_luminosity_order_of_magnitude() {
186 let sun = SolarLuminosities::new(1.0);
187 let w = sun.to::<Watt>();
188 assert!(w.value() > 1e26);
190 assert!(w.value() < 1e27);
191 }
192
193 #[test]
198 fn roundtrip_w_sol() {
199 let original = Watts::new(1e26);
200 let converted = original.to::<SolarLuminosity>();
201 let back = converted.to::<Watt>();
202 assert_relative_eq!(back.value(), original.value(), max_relative = 1e-12);
203 }
204
205 proptest! {
210 #[test]
211 fn prop_roundtrip_w_sol(w in 1e20..1e30f64) {
212 let original = Watts::new(w);
213 let converted = original.to::<SolarLuminosity>();
214 let back = converted.to::<Watt>();
215 prop_assert!((back.value() - original.value()).abs() / original.value() < 1e-12);
216 }
217 }
218}