1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// ---------------------------------------------------------------------------
// Copyright: (c) 2022 ff. Michael Amrhein (michael@adrhinum.de)
// License: This program is part of a larger application. For license
// details please read the file LICENSE.TXT provided together
// with the application.
// ---------------------------------------------------------------------------
// $Source: src/rate.rs $
// $Revision: 2022-07-07T15:40:07+02:00 $
use core::{
fmt,
ops::{Div, Mul},
};
use crate::{AmountT, Quantity, Unit, AMNT_ONE};
/// The ratio between two related quantity values.
#[derive(Copy, Clone, Debug)]
pub struct Rate<TQ: Quantity, PQ: Quantity> {
term_amount: AmountT,
term_unit: TQ::UnitType,
per_unit_multiple: AmountT,
per_unit: PQ::UnitType,
}
impl<TQ: Quantity, PQ: Quantity> Rate<TQ, PQ> {
/// Returns a new instance of `Rate` with attributes equal to given params.
#[inline(always)]
pub const fn new(
term_amount: AmountT,
term_unit: TQ::UnitType,
per_unit_multiple: AmountT,
per_unit: PQ::UnitType,
) -> Self {
Self {
term_amount,
term_unit,
per_unit_multiple,
per_unit,
}
}
/// Returns a new instance of `Rate` with attributes extracted from the
/// given quantity values.
#[inline(always)]
pub fn from_qty_vals(term: TQ, per: PQ) -> Self {
Self {
term_amount: term.amount(),
term_unit: term.unit(),
per_unit_multiple: per.amount(),
per_unit: per.unit(),
}
}
/// Returns the term amount of `self`.
#[inline(always)]
pub const fn term_amount(&self) -> AmountT {
self.term_amount
}
/// Returns the term unit of `self`.
#[inline(always)]
pub const fn term_unit(&self) -> TQ::UnitType {
self.term_unit
}
/// Returns the per unit multiple of `self`.
#[inline(always)]
pub const fn per_unit_multiple(&self) -> AmountT {
self.per_unit_multiple
}
/// Returns the per unit of `self`.
#[inline(always)]
pub const fn per_unit(&self) -> PQ::UnitType {
self.per_unit
}
/// Returns the multiplicative inverse of `self`
pub const fn reciprocal(&self) -> Rate<PQ, TQ> {
Rate::<PQ, TQ>::new(
self.per_unit_multiple(),
self.per_unit(),
self.term_amount(),
self.term_unit(),
)
}
}
impl<TQ: Quantity, PQ: Quantity> fmt::Display for Rate<TQ, PQ> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.term_unit().symbol() == "" {
write!(f, "{} / ", self.term_amount())?;
} else {
write!(
f,
"{} {} / ",
self.term_amount(),
self.term_unit().symbol()
)?;
};
if self.per_unit().symbol() == "" {
write!(f, "{}", self.per_unit_multiple())
} else if self.per_unit_multiple() == AMNT_ONE {
write!(f, "{}", self.per_unit().symbol())
} else {
write!(
f,
"{} {}",
self.per_unit_multiple(),
self.per_unit().symbol()
)
}
}
}
impl<TQ: Quantity, PQ: Quantity> Mul<PQ> for Rate<TQ, PQ>
where
PQ: Div<PQ, Output = AmountT>,
{
type Output = TQ;
fn mul(self, rhs: PQ) -> Self::Output {
let amnt: AmountT =
(rhs / self.per_unit().as_qty()) / self.per_unit_multiple();
Self::Output::new(amnt * self.term_amount(), self.term_unit())
}
}