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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
macro_rules! define_none_scale_common {
() => {
/// The zero value.
pub const ZERO: Self = Self(I::ZERO);
/// The largest value, (2<sup>b</sup> - 1) / 10<sup>S</sup>, where `b`
/// is the bits of `I`.
pub const MAX: Self = Self(I::MAX);
/// The smallest value, -(2<sup>b</sup> / 10<sup>S</sup>), where `b`
/// is the bits of `I`.
pub const MIN: Self = Self(I::MIN);
/// The smallest difference value, 10<sup>-S</sup> .
pub const EPSILON: Self = Self(I::ONE);
/// The largest powers of 10.
pub const MAX_POWERS: Self = Self(I::MAX_POWERS);
/// Approximate number of significant digits in base 10.
pub const DIGITS: u32 = I::DIGITS;
/// Checked addition. Computes `self + rhs`, returning `None` if overflow occurred.
///
/// The right operand must have the same scale with self.
pub fn checked_add(self, rhs: Self) -> Option<Self> {
self.0.checked_add(&rhs.0).map(Self)
}
/// Checked subtraction. Computes `self - rhs`, returning `None` if overflow occurred.
///
/// The right operand must have the same scale with self.
pub fn checked_sub(self, rhs: Self) -> Option<Self> {
self.0.checked_sub(&rhs.0).map(Self)
}
/// Checked multiplication with integer. Computes `self * n`, returning
/// `None` if overflow occurred.
pub fn checked_mul_int(self, n: impl Into<I>) -> Option<Self> {
self.0.checked_mul(&n.into()).map(Self)
}
/// Computes `self * a/b`, returning `None` if overflow occurred.
///
/// Equivalent to [`Self::checked_mul_ratio_ext`] with `Rounding::Round`.
pub fn checked_mul_ratio<R>(self, a: R, b: R) -> Option<Self>
where
R: IntoRatioInt<I>,
{
self.checked_mul_ratio_ext(a, b, Rounding::Round, None)
}
/// Computes `self * a/b`, returning `None` if overflow occurred.
///
/// The arguments `a` and `b` could be primitive integers,
/// `ConstScaleFpdec` or `OobScaleFpdec` with same scale.
///
/// Compared to calling [`Self::checked_mul_int`] and [`Self::checked_div_int`]
/// separately, this can avoid some potential overflow.
///
/// Examples:
///
/// ```
/// use primitive_fixed_point_decimal::{ConstScaleFpdec, fpdec};
/// type Balance = ConstScaleFpdec<i64, 2>;
/// type Quantity = ConstScaleFpdec<i32, 4>; // type for `a` and `b`
///
/// let margin: Balance = fpdec!(30000);
/// let deal: Quantity = fpdec!(0.2);
/// let total: Quantity = fpdec!(0.3);
/// assert_eq!(margin.checked_mul_ratio(deal, total).unwrap(), fpdec!(20000));
///
/// // integer
/// assert_eq!(margin.checked_mul_ratio(200, 300).unwrap(), fpdec!(20000));
/// ```
pub fn checked_mul_ratio_ext<R>(
self,
a: R,
b: R,
rounding: Rounding,
cum_err: Option<&mut CumErr<I>>,
) -> Option<Self>
where
R: IntoRatioInt<I>,
{
self.0
.calc_mul_div(a.to_int(), b.to_int(), rounding, cum_err)
.map(Self)
}
/// Checked division by integer, with `Rounding::Round`.
///
/// Computes `self / n`, returning `None` if `n == 0` or overflow occurres.
pub fn checked_div_int(self, n: impl Into<I>) -> Option<Self> {
self.checked_div_int_ext(n, Rounding::Round, None)
}
/// Checked division by integer with rounding and cumulative-error.
///
/// Computes `self / n`, returning `None` if `n == 0` or overflow occurres.
///
/// See the [cumulative error section](index.html#cumulative-error)
/// for more information and examples.
pub fn checked_div_int_ext(
self,
n: impl Into<I>,
rounding: Rounding,
cum_err: Option<&mut CumErr<I>>,
) -> Option<Self> {
self.0
.checked_div_with_opt_cum_err(n.into(), rounding, cum_err)
.map(Self)
}
/// Return if zero.
pub fn is_zero(&self) -> bool {
self.0.is_zero()
}
/// Create a decimal from the underlying integer representation.
///
/// You must take care of the scale yourself.
pub const fn from_mantissa(i: I) -> Self {
Self(i)
}
/// Return the underlying integer representation.
///
/// You must take care of the scale yourself.
pub const fn mantissa(self) -> I {
self.0
}
};
}
macro_rules! define_none_scale_common_signed {
() => {
/// Computes the absolute value of self.
///
/// # Overflow behavior
///
/// The absolute value of `MIN` cannot be represented as this type,
/// and attempting to calculate it will cause an overflow. This means that
/// code in debug mode will trigger a panic on this case and optimized code
/// will return `MIN` without a panic.
pub fn abs(self) -> Self {
Self(self.0.abs())
}
/// Checked absolute value. Computes `self.abs()`, returning `None` if `self == MIN`.
pub fn checked_abs(self) -> Option<Self> {
if self == Self::MIN {
None
} else {
Some(self.abs())
}
}
/// Return if negative.
pub fn is_neg(&self) -> bool {
self.0.is_negative()
}
/// Return if positive.
pub fn is_pos(&self) -> bool {
self.0.is_positive()
}
};
}
pub(crate) use define_none_scale_common;
pub(crate) use define_none_scale_common_signed;