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_from_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(feature = "cross-unit-ops")]
144crate::impl_unit_cross_unit_ops!(
145 Watt,
146 Yoctowatt,
147 Zeptowatt,
148 Attowatt,
149 Femtowatt,
150 Picowatt,
151 Nanowatt,
152 Microwatt,
153 Milliwatt,
154 Deciwatt,
155 Decawatt,
156 Hectowatt,
157 Kilowatt,
158 Megawatt,
159 Gigawatt,
160 Terawatt,
161 Petawatt,
162 Exawatt,
163 Zettawatt,
164 Yottawatt,
165 ErgPerSecond,
166 HorsepowerMetric,
167 HorsepowerElectric,
168 SolarLuminosity
169);
170
171#[cfg(test)]
172mod tests {
173 use super::*;
174 use approx::assert_relative_eq;
175 use proptest::prelude::*;
176
177 #[test]
182 fn solar_luminosity_to_watts() {
183 let sol = SolarLuminosities::new(1.0);
184 let w = sol.to::<Watt>();
185 assert_relative_eq!(w.value(), 3.828e26, max_relative = 1e-9);
187 }
188
189 #[test]
190 fn watts_to_solar_luminosity() {
191 let w = Watts::new(3.828e26);
192 let sol = w.to::<SolarLuminosity>();
193 assert_relative_eq!(sol.value(), 1.0, max_relative = 1e-9);
194 }
195
196 #[test]
197 fn multiple_solar_luminosities() {
198 let sol = SolarLuminosities::new(3.0);
199 let w = sol.to::<Watt>();
200 assert_relative_eq!(w.value(), 3.0 * 3.828e26, max_relative = 1e-9);
201 }
202
203 #[test]
208 fn solar_luminosity_ratio_sanity() {
209 assert_relative_eq!(SolarLuminosity::RATIO, 3.828e26, max_relative = 1e-9);
211 }
212
213 #[test]
214 fn solar_luminosity_order_of_magnitude() {
215 let sun = SolarLuminosities::new(1.0);
216 let w = sun.to::<Watt>();
217 assert!(w.value() > 1e26);
219 assert!(w.value() < 1e27);
220 }
221
222 #[test]
227 fn roundtrip_w_sol() {
228 let original = Watts::new(1e26);
229 let converted = original.to::<SolarLuminosity>();
230 let back = converted.to::<Watt>();
231 assert_relative_eq!(back.value(), original.value(), max_relative = 1e-12);
232 }
233
234 proptest! {
239 #[test]
240 fn prop_roundtrip_w_sol(w in 1e20..1e30f64) {
241 let original = Watts::new(w);
242 let converted = original.to::<SolarLuminosity>();
243 let back = converted.to::<Watt>();
244 prop_assert!((back.value() - original.value()).abs() / original.value() < 1e-12);
245 }
246 }
247}