diff --git a/src/si/illuminance.rs b/src/si/illuminance.rs new file mode 100644 index 00000000..ddab7e2f --- /dev/null +++ b/src/si/illuminance.rs @@ -0,0 +1,61 @@ +//! Illuminance (base unit lux, lx, cd · sr / m²). + +quantity! { + /// Illuminance (base unit lux, lx, cd · sr / m²). + quantity: Illuminance; "illuminance"; + /// Dimension of illuminance, E (base unit lux, lx, cd · sr / m²). + dimension: ISQ< + N2, // length + Z0, // mass + Z0, // time + Z0, // electric current + Z0, // thermodynamic temperature + Z0, // amount of substance + P1>; // luminous intensity + kind: dyn (crate::si::marker::IlluminanceKind); + units { + @yottalux: prefix!(yotta); "Ylm", "yottalux", "yottaluxs"; + @zettalux: prefix!(zetta); "Zlm", "zettalux", "zettaluxs"; + @exalux: prefix!(exa); "Elm", "exalux", "exaluxs"; + @petalux: prefix!(peta); "Plm", "petalux", "petaluxs"; + @teralux: prefix!(tera); "Tlm", "teralux", "teraluxs"; + @gigalux: prefix!(giga); "Glm", "gigalux", "gigaluxs"; + @megalux: prefix!(mega); "Mlm", "megalux", "megaluxs"; + @kilolux: prefix!(kilo); "klm", "kilolux", "kiloluxs"; + @hectolux: prefix!(hecto); "hlm", "hectolux", "hectoluxs"; + @decalux: prefix!(deca); "dalm", "decalux", "decaluxs"; + /// The lux is defined to be 1 lumen per square meter, + /// or 1 candela steradian per square meter. + @lux: prefix!(none); "lm", "lux", "luxs"; + @decilux: prefix!(deci); "dlm", "decilux", "deciluxs"; + @centilux: prefix!(centi); "clm", "centilux", "centiluxs"; + @millilux: prefix!(milli); "mlm", "millilux", "milliluxs"; + @microlux: prefix!(micro); "µlm", "microlux", "microluxs"; + @nanolux: prefix!(nano); "nlm", "nanolux", "nanoluxs"; + @picolux: prefix!(pico); "plm", "picolux", "picoluxs"; + @femtolux: prefix!(femto); "flm", "femtolux", "femtoluxs"; + @attolux: prefix!(atto); "alm", "attolux", "attoluxs"; + @zeptolux: prefix!(zepto); "zlm", "zeptolux", "zeptoluxs"; + @yoctolux: prefix!(yocto); "ylm", "yoctolux", "yoctoluxs"; + } +} + +#[cfg(test)] +mod tests { + storage_types! { + use crate::si::quantities::*; + use crate::si::luminous_flux as lf; + use crate::si::area as a; + use crate::si::illuminance as i; + use crate::tests::{A, Test}; + + quickcheck! { + #[allow(trivial_casts)] + fn add(l: A, r: A) -> bool { + Test::eq(&Illuminance::::new::(&*l / &*r), + &(LuminousFlux::::new::((*l).clone()) + / Area::::new::((*r).clone())).into()) + } + } + } +} diff --git a/src/si/luminous_flux.rs b/src/si/luminous_flux.rs new file mode 100644 index 00000000..87dc8f82 --- /dev/null +++ b/src/si/luminous_flux.rs @@ -0,0 +1,114 @@ +//! Luminous flux (base unit lumen, lm, cd · sr). + +use crate::si::luminous_intensity::LuminousIntensity; +use crate::si::solid_angle::SolidAngle; + +quantity! { + /// Luminous flux (base unit lumen, lm, cd · sr). + quantity: LuminousFlux; "luminous flux"; + /// Dimension of luminous flux, Φ (base unit lumen, lm, cd · sr). + dimension: ISQ< + Z0, // length + Z0, // mass + Z0, // time + Z0, // electric current + Z0, // thermodynamic temperature + Z0, // amount of substance + P1>; // luminous intensity + kind: dyn (crate::si::marker::LuminousFluxKind); + units { + @yottalumen: prefix!(yotta); "Ylm", "yottalumen", "yottalumens"; + @zettalumen: prefix!(zetta); "Zlm", "zettalumen", "zettalumens"; + @exalumen: prefix!(exa); "Elm", "exalumen", "exalumens"; + @petalumen: prefix!(peta); "Plm", "petalumen", "petalumens"; + @teralumen: prefix!(tera); "Tlm", "teralumen", "teralumens"; + @gigalumen: prefix!(giga); "Glm", "gigalumen", "gigalumens"; + @megalumen: prefix!(mega); "Mlm", "megalumen", "megalumens"; + @kilolumen: prefix!(kilo); "klm", "kilolumen", "kilolumens"; + @hectolumen: prefix!(hecto); "hlm", "hectolumen", "hectolumens"; + @decalumen: prefix!(deca); "dalm", "decalumen", "decalumens"; + /// The lumen is defined to be 1 candela steradian. + @lumen: prefix!(none); "lm", "lumen", "lumens"; + @decilumen: prefix!(deci); "dlm", "decilumen", "decilumens"; + @centilumen: prefix!(centi); "clm", "centilumen", "centilumens"; + @millilumen: prefix!(milli); "mlm", "millilumen", "millilumens"; + @microlumen: prefix!(micro); "µlm", "microlumen", "microlumens"; + @nanolumen: prefix!(nano); "nlm", "nanolumen", "nanolumens"; + @picolumen: prefix!(pico); "plm", "picolumen", "picolumens"; + @femtolumen: prefix!(femto); "flm", "femtolumen", "femtolumens"; + @attolumen: prefix!(atto); "alm", "attolumen", "attolumens"; + @zeptolumen: prefix!(zepto); "zlm", "zeptolumen", "zeptolumens"; + @yoctolumen: prefix!(yocto); "ylm", "yoctolumen", "yoctolumens"; + } +} + +// TODO: Explicitly allow luminous flux = luminous intensity * solid angle using +// trait implementations such as the below. +#[doc(hidden)] +macro_rules! impl_ops { + ( + $MulDivTrait:ident, $muldiv_fun:ident, $muldiv_op:tt + ) => { + #[cfg(feature = "autoconvert")] + impl $crate::lib::ops::$MulDivTrait> + for LuminousIntensity + where + Ul: super::Units + ?Sized, + Ur: super::Units + ?Sized, + V: $crate::num::Num + $crate::Conversion, + { + type Output = LuminousFlux; + + #[inline(always)] + fn $muldiv_fun(self, rhs: SolidAngle) -> Self::Output { + super::Quantity { + dimension: $crate::lib::marker::PhantomData, + units: $crate::lib::marker::PhantomData, + value: self.value + $muldiv_op super::change_base::(&rhs.value), + } + } + } + + #[cfg(not(feature = "autoconvert"))] + impl $crate::lib::ops::$MulDivTrait> + for LuminousIntensity + where + U: super::Units + ?Sized, + V: $crate::num::Num + $crate::Conversion, + { + type Output = LuminousFlux; + + #[inline(always)] + fn $muldiv_fun(self, rhs: SolidAngle) -> Self::Output { + super::Quantity { + dimension: $crate::lib::marker::PhantomData, + units: $crate::lib::marker::PhantomData, + value: self.value $muldiv_op rhs.value, + } + } + } + }; +} + +//impl_ops!(Mul, mul, *); + +#[cfg(test)] +mod tests { + storage_types! { + use crate::si::quantities::*; + use crate::si::luminous_flux as lf; + use crate::si::luminous_intensity as li; + use crate::si::solid_angle as sa; + use crate::tests::{A, Test}; + + quickcheck! { + #[allow(trivial_casts)] + fn add(l: A, r: A) -> bool { + Test::eq(&LuminousFlux::::new::(&*l * &*r), + &(LuminousIntensity::::new::((*l).clone()) + * SolidAngle::::new::((*r).clone())).into()) + } + } + } +} diff --git a/src/si/mod.rs b/src/si/mod.rs index 3ba55e67..1b675842 100644 --- a/src/si/mod.rs +++ b/src/si/mod.rs @@ -69,12 +69,14 @@ system! { heat_capacity::HeatCapacity, heat_flux_density::HeatFluxDensity, heat_transfer::HeatTransfer, + illuminance::Illuminance, inductance::Inductance, information::Information, information_rate::InformationRate, jerk::Jerk, length::Length, luminance::Luminance, + luminous_flux::LuminousFlux, luminous_intensity::LuminousIntensity, magnetic_flux::MagneticFlux, magnetic_flux_density::MagneticFluxDensity, @@ -148,6 +150,36 @@ pub mod marker { /// ``` pub trait SolidAngleKind: Kind {} + /// `IlluminanceKind` is a `Kind` for separating quantities of illuminance from other + /// identically dimensioned quantities. Conversions to and from `IlluminanceKind` quantities are + /// supported through implementations of the `From` trait. + /// + #[cfg_attr(feature = "f32", doc = " ```rust")] + #[cfg_attr(not(feature = "f32"), doc = " ```rust,ignore")] + /// # use uom::si::f32::*; + /// # use uom::si::luminous_flux::lumen; + /// # use uom::si::area::square_meter; + /// let a: LuminousFlux = LuminousFlux::new::(1.0); + /// let b: Area = Area::new::(1.0); + /// let r: Illuminance = (a / b).into(); + /// ``` + pub trait IlluminanceKind: Kind {} + + /// `LuminousFluxKind` is a `Kind` for separating quantities of luminous flux from other + /// identically dimensioned quantities. Conversions to and from `LuminousFluxKind` quantities are + /// supported through implementations of the `From` trait. + /// + #[cfg_attr(feature = "f32", doc = " ```rust")] + #[cfg_attr(not(feature = "f32"), doc = " ```rust,ignore")] + /// # use uom::si::f32::*; + /// # use uom::si::luminous_intensity::candela; + /// # use uom::si::solid_angle::steradian; + /// let a: LuminousIntensity = LuminousIntensity::new::(1.0); + /// let b: SolidAngle = SolidAngle::new::(1.0); + /// let r: LuminousFlux = (a * b).into(); + /// ``` + pub trait LuminousFluxKind: Kind {} + /// `InformationKind` is a `Kind` for separating information quantities from their identically /// dimensioned non-information quantity counterparts. Conversions to and from `InformationKind` /// quantities are supported through implementations of the `From` trait. @@ -332,6 +364,10 @@ pub mod marker { impl_from!(Kind, AngleKind); impl_from!(SolidAngleKind, Kind); impl_from!(Kind, SolidAngleKind); + impl_from!(IlluminanceKind, Kind); + impl_from!(Kind, IlluminanceKind); + impl_from!(LuminousFluxKind, Kind); + impl_from!(Kind, LuminousFluxKind); impl_from!(InformationKind, Kind); impl_from!(Kind, InformationKind); impl_from!(ConstituentConcentrationKind, Kind);