use crate::{Quantity, Unit};
use qtty_derive::Unit;
pub use crate::dimension::Energy;
pub trait EnergyUnit: Unit<Dim = Energy> {}
impl<T: Unit<Dim = Energy>> EnergyUnit for T {}
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "J", dimension = Energy, ratio = 1.0)]
pub struct Joule;
pub type Joules = Quantity<Joule>;
pub const JOULE: Joules = Joules::new(1.0);
macro_rules! si_joule {
($name:ident, $sym:literal, $ratio:expr, $qty:ident, $one:ident) => {
#[doc = concat!("SI-prefixed joule unit (", stringify!($ratio), " J).")]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = $sym, dimension = Energy, ratio = $ratio)]
pub struct $name;
#[doc = concat!("A quantity measured in ", stringify!($name), "s.")]
pub type $qty = Quantity<$name>;
#[doc = concat!("One ", stringify!($name), ".")]
pub const $one: $qty = $qty::new(1.0);
};
}
si_joule!(Nanojoule, "nJ", 1e-9, Nanojoules, NANOJOULE);
si_joule!(Picojoule, "pJ", 1e-12, Picojoules, PICOJOULE);
si_joule!(Microjoule, "µJ", 1e-6, Microjoules, MICROJOULE);
si_joule!(Millijoule, "mJ", 1e-3, Millijoules, MILLIJOULE);
si_joule!(Kilojoule, "kJ", 1e3, Kilojoules, KILOJOULE);
si_joule!(Megajoule, "MJ", 1e6, Megajoules, MEGAJOULE);
si_joule!(Gigajoule, "GJ", 1e9, Gigajoules, GIGAJOULE);
si_joule!(Terajoule, "TJ", 1e12, Terajoules, TERAJOULE);
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "Wh", dimension = Energy, ratio = 3_600.0)]
pub struct WattHour;
pub type WattHours = Quantity<WattHour>;
pub const WATT_HOUR: WattHours = WattHours::new(1.0);
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "kWh", dimension = Energy, ratio = 3_600_000.0)]
pub struct KilowattHour;
pub type KilowattHours = Quantity<KilowattHour>;
pub const KILOWATT_HOUR: KilowattHours = KilowattHours::new(1.0);
#[cfg(feature = "fundamental-physics")]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "erg", dimension = Energy, ratio = 1e-7)]
pub struct Erg;
#[cfg(feature = "fundamental-physics")]
pub type Ergs = Quantity<Erg>;
#[cfg(feature = "fundamental-physics")]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "eV", dimension = Energy, ratio = 1.602_176_634e-19)]
pub struct Electronvolt;
#[cfg(feature = "fundamental-physics")]
pub type Electronvolts = Quantity<Electronvolt>;
#[cfg(feature = "fundamental-physics")]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "keV", dimension = Energy, ratio = 1.602_176_634e-16)]
pub struct Kiloelectronvolt;
#[cfg(feature = "fundamental-physics")]
pub type Kiloelectronvolts = Quantity<Kiloelectronvolt>;
#[cfg(feature = "fundamental-physics")]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "MeV", dimension = Energy, ratio = 1.602_176_634e-13)]
pub struct Megaelectronvolt;
#[cfg(feature = "fundamental-physics")]
pub type Megaelectronvolts = Quantity<Megaelectronvolt>;
#[cfg(feature = "customary")]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "cal", dimension = Energy, ratio = 4.184)]
pub struct Calorie;
#[cfg(feature = "customary")]
pub type Calories = Quantity<Calorie>;
#[cfg(feature = "customary")]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "kcal", dimension = Energy, ratio = 4184.0)]
pub struct Kilocalorie;
#[cfg(feature = "customary")]
pub type Kilocalories = Quantity<Kilocalorie>;
#[cfg(feature = "customary")]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "BTU", dimension = Energy, ratio = 1_055.05585262)]
pub struct BritishThermalUnit;
#[cfg(feature = "customary")]
pub type BritishThermalUnits = Quantity<BritishThermalUnit>;
#[cfg(feature = "customary")]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "therm", dimension = Energy, ratio = 105_505_585.262)]
pub struct Therm;
#[cfg(feature = "customary")]
pub type Therms = Quantity<Therm>;
#[macro_export]
#[doc(hidden)]
macro_rules! energy_units {
($cb:path) => {
$cb!(
Joule,
Picojoule,
Nanojoule,
Microjoule,
Millijoule,
Kilojoule,
Megajoule,
Gigajoule,
Terajoule,
WattHour,
KilowattHour
);
};
}
energy_units!(crate::impl_unit_from_conversions);
#[cfg(feature = "cross-unit-ops")]
energy_units!(crate::impl_unit_cross_unit_ops);
#[cfg(all(feature = "customary", feature = "fundamental-physics"))]
crate::__impl_from_each_extra_to_bases!(
{Calorie, Kilocalorie, BritishThermalUnit, Therm}
Erg, Electronvolt, Kiloelectronvolt, Megaelectronvolt
);
#[cfg(all(
feature = "customary",
feature = "fundamental-physics",
feature = "cross-unit-ops"
))]
crate::__impl_cross_ops_each_extra_to_bases!(
{Calorie, Kilocalorie, BritishThermalUnit, Therm}
Erg, Electronvolt, Kiloelectronvolt, Megaelectronvolt
);
#[cfg(test)]
energy_units!(crate::assert_units_are_builtin);
#[cfg(feature = "fundamental-physics")]
#[macro_export]
#[doc(hidden)]
macro_rules! energy_fundamental_physics_units {
($cb:path) => {
$cb!(Erg, Electronvolt, Kiloelectronvolt, Megaelectronvolt);
};
}
#[cfg(feature = "customary")]
#[macro_export]
#[doc(hidden)]
macro_rules! energy_customary_units {
($cb:path) => {
$cb!(Calorie, Kilocalorie, BritishThermalUnit, Therm);
};
}
#[cfg(all(test, feature = "std"))]
mod tests {
use super::*;
use approx::assert_abs_diff_eq;
#[test]
fn kilojoule_to_joule() {
let kj = Kilojoules::new(1.0);
let j: Joules = kj.to();
assert_abs_diff_eq!(j.value(), 1_000.0, epsilon = 1e-12);
}
#[test]
fn joule_to_millijoule() {
let j = Joules::new(1.0);
let mj: Millijoules = j.to();
assert_abs_diff_eq!(mj.value(), 1_000.0, epsilon = 1e-12);
}
#[test]
fn megajoule_to_kilojoule() {
let mj = Megajoules::new(1.0);
let kj: Kilojoules = mj.to();
assert_abs_diff_eq!(kj.value(), 1_000.0, epsilon = 1e-12);
}
#[test]
#[cfg(feature = "fundamental-physics")]
fn joule_to_erg() {
let j = Joules::new(1.0);
let e: Ergs = j.to();
assert_abs_diff_eq!(e.value(), 1e7, epsilon = 1e-5);
}
#[test]
#[cfg(feature = "fundamental-physics")]
fn ev_to_joule() {
let ev = Electronvolts::new(1.0);
let j: Joules = ev.to();
assert_abs_diff_eq!(j.value(), 1.602_176_634e-19, epsilon = 1e-30);
}
#[test]
#[cfg(feature = "customary")]
fn calorie_to_joule() {
let cal = Calories::new(1.0);
let j: Joules = cal.to();
assert_abs_diff_eq!(j.value(), 4.184, epsilon = 1e-12);
}
#[test]
#[cfg(feature = "customary")]
fn kilocalorie_to_joule() {
let kcal = Kilocalories::new(1.0);
let j: Joules = kcal.to();
assert_abs_diff_eq!(j.value(), 4184.0, epsilon = 1e-9);
}
#[test]
fn watt_hour_to_joule() {
let wh = WattHours::new(1.0);
let j: Joules = wh.to();
assert_abs_diff_eq!(j.value(), 3_600.0, epsilon = 1e-10);
}
#[test]
fn kilowatt_hour_to_joule() {
let kwh = KilowattHours::new(1.0);
let j: Joules = kwh.to();
assert_abs_diff_eq!(j.value(), 3_600_000.0, epsilon = 1e-6);
}
#[test]
fn nanojoule_to_picojoule() {
let nj = Nanojoules::new(1.0);
let pj: Picojoules = nj.to();
assert_abs_diff_eq!(pj.value(), 1_000.0, epsilon = 1e-9);
}
#[test]
#[cfg(feature = "customary")]
fn btu_to_joule() {
let btu = BritishThermalUnits::new(1.0);
let j: Joules = btu.to();
assert_abs_diff_eq!(j.value(), 1_055.05585262, epsilon = 1e-6);
}
#[test]
#[cfg(feature = "customary")]
fn therm_to_btu() {
let therm = Therms::new(1.0);
let btu: BritishThermalUnits = therm.to();
assert_abs_diff_eq!(btu.value(), 100_000.0, epsilon = 1e-3);
}
}