concision_traits/math/percentages.rs
1/*
2 Appellation: difference <module>
3 Created At: 2025.11.26:12:09:51
4 Contrib: @FL03
5*/
6/// The [`PercentChange`] trait establishes a binary operator for computing the percent change
7/// between two values where the caller is considered the original value.
8pub trait PercentChange<Rhs = Self> {
9 type Output;
10
11 fn percent_change(self, rhs: Rhs) -> Self::Output;
12}
13/// Compute the percentage difference between two values.
14/// The percentage difference is defined as:
15///
16/// ```math
17/// \text{PercentDifference}(x, y) = 2\cdot\frac{|x - y|}{|x| + |y|}
18/// ```
19pub trait PercentDiff<Rhs = Self> {
20 type Output;
21
22 fn percent_diff(self, rhs: Rhs) -> Self::Output;
23}
24
25/*
26 ************* Implementations *************
27*/
28use num_traits::{FromPrimitive, NumOps, Signed, Zero};
29
30impl<T> PercentDiff for T
31where
32 T: Copy + Signed + Zero + FromPrimitive + NumOps<T, T>,
33{
34 type Output = T;
35
36 fn percent_diff(self, rhs: T) -> Self::Output {
37 T::from_u8(2).unwrap() * (self - rhs).abs() / (self.abs() + rhs.abs())
38 }
39}
40
41impl<A, B, C> PercentChange<B> for A
42where
43 C: core::ops::Div<B, Output = C>,
44 for<'b> A: core::ops::Sub<&'b B, Output = C>,
45{
46 type Output = C;
47
48 fn percent_change(self, rhs: B) -> Self::Output {
49 (self - &rhs) / rhs
50 }
51}
52
53// macro_rules! impl_percent_change {
54// ($($T:ty),* $(,)?) => {
55// $(impl_percent_change! { @impl $T })*
56// };
57// (@impl $T:ty) => {
58// impl PercentChange<$T> for $T {
59// type Output = $T;
60
61// fn percent_change(self, rhs: $T) -> Self::Output {
62// (self - rhs) / rhs
63// }
64// }
65// };
66// }