1use crate::dimension::{DimDiv, DimMul, Dimension, Dimensionless};
4use crate::scalar::Scalar;
5use crate::Quantity;
6use core::fmt::{Debug, Display, Formatter, Result};
7use core::marker::PhantomData;
8
9pub trait Unit: Copy + PartialEq + Debug + 'static {
24 const RATIO: f64;
26
27 type Dim: Dimension;
29
30 const SYMBOL: &'static str;
32}
33
34#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
42pub struct Per<N: Unit, D: Unit>(PhantomData<(N, D)>);
43
44impl<N: Unit, D: Unit> Unit for Per<N, D>
45where
46 N::Dim: DimDiv<D::Dim>,
47 <N::Dim as DimDiv<D::Dim>>::Output: Dimension,
48{
49 const RATIO: f64 = N::RATIO / D::RATIO;
50 type Dim = <N::Dim as DimDiv<D::Dim>>::Output;
51 const SYMBOL: &'static str = "";
52}
53
54impl<N: Unit, D: Unit, S: Scalar + Display> Display for Quantity<Per<N, D>, S>
55where
56 N::Dim: DimDiv<D::Dim>,
57 <N::Dim as DimDiv<D::Dim>>::Output: Dimension,
58{
59 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
60 write!(f, "{} {}/{}", self.value(), N::SYMBOL, D::SYMBOL)
61 }
62}
63
64#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
70pub struct Prod<A: Unit, B: Unit>(PhantomData<(A, B)>);
71
72impl<A: Unit, B: Unit> Unit for Prod<A, B>
73where
74 A::Dim: DimMul<B::Dim>,
75 <A::Dim as DimMul<B::Dim>>::Output: Dimension,
76{
77 const RATIO: f64 = A::RATIO * B::RATIO;
78 type Dim = <A::Dim as DimMul<B::Dim>>::Output;
79 const SYMBOL: &'static str = "";
80}
81
82impl<A: Unit, B: Unit, S: Scalar + Display> Display for Quantity<Prod<A, B>, S>
83where
84 A::Dim: DimMul<B::Dim>,
85 <A::Dim as DimMul<B::Dim>>::Output: Dimension,
86{
87 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
88 write!(f, "{} {}ยท{}", self.value(), A::SYMBOL, B::SYMBOL)
89 }
90}
91
92#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
102pub struct Unitless;
103
104impl Unit for Unitless {
105 const RATIO: f64 = 1.0;
106 type Dim = Dimensionless;
107 const SYMBOL: &'static str = "";
108}
109
110impl<S: Scalar + Display> Display for Quantity<Unitless, S> {
111 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
112 write!(f, "{}", self.value())
113 }
114}
115
116pub trait Simplify {
121 type Scalar: Scalar;
123 type Out: Unit;
125 fn simplify(self) -> Quantity<Self::Out, Self::Scalar>;
127}
128
129impl<U: Unit, S: Scalar> Simplify for Quantity<Per<U, U>, S>
130where
131 U::Dim: DimDiv<U::Dim>,
132 <U::Dim as DimDiv<U::Dim>>::Output: Dimension,
133{
134 type Scalar = S;
135 type Out = Unitless;
136 fn simplify(self) -> Quantity<Unitless, S> {
145 Quantity::new(self.value())
146 }
147}
148
149impl<N: Unit, D: Unit, S: Scalar> Simplify for Quantity<Per<N, Per<N, D>>, S>
150where
151 N::Dim: DimDiv<D::Dim>,
152 <N::Dim as DimDiv<D::Dim>>::Output: Dimension,
153 N::Dim: DimDiv<<N::Dim as DimDiv<D::Dim>>::Output>,
154 <N::Dim as DimDiv<<N::Dim as DimDiv<D::Dim>>::Output>>::Output: Dimension,
155{
156 type Scalar = S;
157 type Out = D;
158 fn simplify(self) -> Quantity<D, S> {
159 Quantity::new(self.value())
160 }
161}