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
//! Macro-generated sign-aware inherent methods (`abs`, `signum`,
//! `is_positive`, `is_negative`) for the decimal widths.
//!
//! The native arm delegates to the primitive integer intrinsics. The
//! `wide` arm delegates to the wide integer's equivalents: `signum` on a wide
//! integer returns the storage type (not a primitive `i32`), and
//! integer literals cannot be compared against wide-integer values, so the
//! bodies are spelled with `is_positive()` / `is_negative()` instead.
/// Emits `abs`, `signum`, `is_positive`, `is_negative` for a decimal
/// type with the given storage.
macro_rules! decl_decimal_sign_methods {
// Wide storage.
(wide $Type:ident, $Storage:ty) => {
impl<const SCALE: u32> $Type<SCALE> {
/// Returns the absolute value of `self`.
///
/// Note: `abs(MIN)` overflows (because |MIN| has no positive
/// counterpart in two's complement). Debug builds panic;
/// release builds wrap.
#[inline]
#[must_use]
pub const fn abs(self) -> Self {
Self(self.0.abs())
}
/// Returns the sign of `self` encoded as a scaled `Self`:
/// `-ONE`, `ZERO`, or `+ONE`.
#[inline]
#[must_use]
pub fn signum(self) -> Self {
if self.0.is_positive() {
Self::ONE
} else if self.0.is_negative() {
Self(-Self::multiplier())
} else {
Self::ZERO
}
}
/// Returns `true` if `self` is strictly greater than zero.
#[inline]
#[must_use]
pub const fn is_positive(self) -> bool {
self.0.is_positive()
}
/// Returns `true` if `self` is strictly less than zero.
#[inline]
#[must_use]
pub const fn is_negative(self) -> bool {
self.0.is_negative()
}
}
};
// Native (primitive integer) storage.
($Type:ident, $Storage:ty) => {
impl<const SCALE: u32> $Type<SCALE> {
/// Returns the absolute value of `self`.
///
/// Note: `abs(MIN)` overflows (because |MIN| has no positive
/// counterpart in two's complement). Debug builds panic;
/// release builds wrap.
#[inline]
#[must_use]
pub const fn abs(self) -> Self {
Self(self.0.abs())
}
/// Returns the sign of `self` encoded as a scaled `Self`:
/// `-ONE`, `ZERO`, or `+ONE`.
#[inline]
#[must_use]
pub fn signum(self) -> Self {
match self.0.signum() {
1 => Self::ONE,
-1 => Self(-Self::multiplier()),
_ => Self::ZERO,
}
}
/// Returns `true` if `self` is strictly greater than zero.
#[inline]
#[must_use]
pub const fn is_positive(self) -> bool {
self.0 > 0
}
/// Returns `true` if `self` is strictly less than zero.
#[inline]
#[must_use]
pub const fn is_negative(self) -> bool {
self.0 < 0
}
}
};
}
pub(crate) use decl_decimal_sign_methods;