/rust/registry/src/index.crates.io-1949cf8c6b5b557f/fastnum-0.7.4/src/decimal/signals.rs
Line | Count | Source |
1 | | use core::fmt::{Debug, Display, Formatter}; |
2 | | |
3 | | use crate::utils::assert_eq_size; |
4 | | |
5 | | /// # Signals |
6 | | /// |
7 | | /// The exceptional conditions are grouped into signals, which can be controlled |
8 | | /// individually. |
9 | | /// For each of the signals, the corresponding flag is set to `1` |
10 | | /// when the signal occurs. |
11 | | #[derive(Copy, Clone, Hash, PartialEq, Eq)] |
12 | | #[repr(transparent)] |
13 | | pub struct Signals(u8); |
14 | | |
15 | | impl Signals { |
16 | | pub(crate) const OP_CLAMPED_MASK: u8 = 0b0000_0001; |
17 | | pub(crate) const OP_DIV_BY_ZERO_MASK: u8 = 0b0000_0010; |
18 | | pub(crate) const OP_INVALID_MASK: u8 = 0b0000_0100; |
19 | | pub(crate) const OP_INEXACT_MASK: u8 = 0b0000_1000; |
20 | | pub(crate) const OP_OVERFLOW_MASK: u8 = 0b0001_0000; |
21 | | pub(crate) const OP_ROUNDED_MASK: u8 = 0b0010_0000; |
22 | | pub(crate) const OP_SUBNORMAL_MASK: u8 = 0b0100_0000; |
23 | | pub(crate) const OP_UNDERFLOW_MASK: u8 = 0b1000_0000; |
24 | | |
25 | | /// By default, no operation signals are raised. |
26 | | pub const EMPTY: Self = Self(0); |
27 | | |
28 | | /// Raised when the exponent of a result has been altered or constrained to |
29 | | /// fit the target type. |
30 | | pub const OP_CLAMPED: Self = Self(Self::OP_CLAMPED_MASK); |
31 | | |
32 | | /// Raised when a non-zero dividend is divided by zero. |
33 | | pub const OP_DIV_BY_ZERO: Self = Self(Self::OP_DIV_BY_ZERO_MASK); |
34 | | |
35 | | /// Raised when a result would be undefined or impossible. |
36 | | pub const OP_INVALID: Self = Self(Self::OP_INVALID_MASK); |
37 | | |
38 | | /// Raised when a result is not exact (one or more non-zero coefficient |
39 | | /// digits were discarded during rounding). |
40 | | pub const OP_INEXACT: Self = Self(Self::OP_INEXACT_MASK); |
41 | | |
42 | | /// Raised when the exponent of a result is too large to be represented. |
43 | | pub const OP_OVERFLOW: Self = Self(Self::OP_OVERFLOW_MASK); |
44 | | |
45 | | /// Raised when a result has been rounded (that is, some zero or non-zero |
46 | | /// coefficient digits were discarded). |
47 | | pub const OP_ROUNDED: Self = Self(Self::OP_ROUNDED_MASK); |
48 | | |
49 | | /// Raised when a result is subnormal (its adjusted exponent is less than |
50 | | /// E<sub>min</sub>), before any rounding. |
51 | | pub const OP_SUBNORMAL: Self = Self(Self::OP_SUBNORMAL_MASK); |
52 | | |
53 | | /// Raised when a result is both subnormal and inexact. |
54 | | pub const OP_UNDERFLOW: Self = Self(Self::OP_UNDERFLOW_MASK); |
55 | | |
56 | | pub(crate) const DEFAULT_TRAPS: Self = |
57 | | Self(Self::OP_DIV_BY_ZERO.0 | Self::OP_INVALID.0 | Self::OP_OVERFLOW.0); |
58 | | |
59 | | /// Return an empty set of signaling flags. |
60 | | #[must_use] |
61 | | #[inline(always)] |
62 | 0 | pub const fn empty() -> Self { |
63 | 0 | Self::EMPTY |
64 | 0 | } |
65 | | |
66 | | #[inline(always)] |
67 | 0 | pub(crate) const fn new(mask: u8) -> Self { |
68 | 0 | Self(mask) |
69 | 0 | } |
70 | | |
71 | | #[inline(always)] |
72 | 0 | pub(crate) const fn mask(&self) -> u8 { |
73 | 0 | self.0 |
74 | 0 | } |
75 | | |
76 | | #[inline(always)] |
77 | 0 | pub(crate) const fn raise(&mut self, signals: Signals) { |
78 | 0 | *self = self.combine(signals); |
79 | 0 | } |
80 | | |
81 | | /// Combines the given signal with another one. |
82 | | #[must_use] |
83 | | #[inline(always)] |
84 | 0 | pub const fn combine(mut self, other: Self) -> Self { |
85 | 0 | self.0 |= other.0; |
86 | 0 | self |
87 | 0 | } |
88 | | |
89 | | /// Intersect the given signal with another one. |
90 | | #[must_use] |
91 | | #[inline(always)] |
92 | 0 | pub const fn intersect(mut self, other: Self) -> Self { |
93 | 0 | self.0 &= other.0; |
94 | 0 | self |
95 | 0 | } |
96 | | |
97 | | #[must_use] |
98 | | #[inline(always)] |
99 | 0 | pub(crate) const fn set(mut self, other: Self) -> Self { |
100 | 0 | self.0 |= other.0; |
101 | 0 | self |
102 | 0 | } |
103 | | |
104 | | #[allow(dead_code)] |
105 | | #[must_use] |
106 | | #[inline(always)] |
107 | 0 | pub(crate) const fn unset(mut self, other: Self) -> Self { |
108 | 0 | self.0 &= !other.0; |
109 | 0 | self |
110 | 0 | } |
111 | | |
112 | | #[allow(dead_code)] |
113 | | #[must_use] |
114 | | #[inline(always)] |
115 | 0 | pub(crate) const fn toggle(mut self, other: Self) -> Self { |
116 | 0 | self.0 ^= other.0; |
117 | 0 | self |
118 | 0 | } |
119 | | |
120 | | /// Is empty |
121 | | #[must_use] |
122 | | #[inline(always)] |
123 | 0 | pub const fn is_empty(&self) -> bool { |
124 | 0 | self.0 == Self::EMPTY.0 |
125 | 0 | } |
126 | | |
127 | | #[must_use] |
128 | | #[inline(always)] |
129 | 0 | pub(crate) const fn is_raised(&self, other: Self) -> bool { |
130 | 0 | self.0 & other.0 != 0 |
131 | 0 | } |
132 | | } |
133 | | |
134 | | macro_rules! display { |
135 | | ($self: ident, $f: ident, $($v: ident => $l: literal),*) => { |
136 | | #[allow(unused_assignments)] |
137 | | { |
138 | | let mut delimiter = false; |
139 | | $( |
140 | | if $self.is_raised(Self::$v) { |
141 | | match delimiter { |
142 | | true => { |
143 | | write!($f, ", ")?; |
144 | | } |
145 | | false => { |
146 | | delimiter = true; |
147 | | } |
148 | | } |
149 | | write!($f, $l)?; |
150 | | } |
151 | | )* |
152 | | } |
153 | | }; |
154 | | } |
155 | | |
156 | | impl Display for Signals { |
157 | 0 | fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { |
158 | 0 | if self.is_empty() { |
159 | 0 | return Ok(()); |
160 | 0 | } |
161 | | |
162 | 0 | display!(self, f, |
163 | | OP_CLAMPED => "!CP", |
164 | | OP_DIV_BY_ZERO => "!DBZ", |
165 | | OP_INEXACT => "!INEXACT", |
166 | | OP_INVALID => "!INV", |
167 | | OP_OVERFLOW => "!OFW", |
168 | | OP_ROUNDED => "!ROUND", |
169 | | OP_SUBNORMAL => "!SN", |
170 | | OP_UNDERFLOW => "!UFW" |
171 | | ); |
172 | | |
173 | 0 | Ok(()) |
174 | 0 | } |
175 | | } |
176 | | |
177 | | impl Debug for Signals { |
178 | 0 | fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { |
179 | 0 | write!(f, "{self}") |
180 | 0 | } |
181 | | } |
182 | | |
183 | | assert_eq_size!(Signals, u8); |