fastnum/decimal/
signals.rs1use core::fmt::{Debug, Display, Formatter};
2
3use crate::utils::assert_eq_size;
4
5#[derive(Copy, Clone, Hash, PartialEq, Eq)]
12#[repr(transparent)]
13pub struct Signals(u8);
14
15impl 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 pub const EMPTY: Self = Self(0);
27
28 pub const OP_CLAMPED: Self = Self(Self::OP_CLAMPED_MASK);
31
32 pub const OP_DIV_BY_ZERO: Self = Self(Self::OP_DIV_BY_ZERO_MASK);
34
35 pub const OP_INVALID: Self = Self(Self::OP_INVALID_MASK);
37
38 pub const OP_INEXACT: Self = Self(Self::OP_INEXACT_MASK);
41
42 pub const OP_OVERFLOW: Self = Self(Self::OP_OVERFLOW_MASK);
44
45 pub const OP_ROUNDED: Self = Self(Self::OP_ROUNDED_MASK);
48
49 pub const OP_SUBNORMAL: Self = Self(Self::OP_SUBNORMAL_MASK);
52
53 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 #[must_use]
61 #[inline(always)]
62 pub const fn empty() -> Self {
63 Self::EMPTY
64 }
65
66 #[inline(always)]
67 pub(crate) const fn new(mask: u8) -> Self {
68 Self(mask)
69 }
70
71 #[inline(always)]
72 pub(crate) const fn mask(&self) -> u8 {
73 self.0
74 }
75
76 #[inline(always)]
77 pub(crate) const fn raise(&mut self, signals: Signals) {
78 *self = self.combine(signals);
79 }
80
81 #[must_use]
83 #[inline(always)]
84 pub const fn combine(mut self, other: Self) -> Self {
85 self.0 |= other.0;
86 self
87 }
88
89 #[must_use]
91 #[inline(always)]
92 pub const fn intersect(mut self, other: Self) -> Self {
93 self.0 &= other.0;
94 self
95 }
96
97 #[must_use]
98 #[inline(always)]
99 pub(crate) const fn set(mut self, other: Self) -> Self {
100 self.0 |= other.0;
101 self
102 }
103
104 #[allow(dead_code)]
105 #[must_use]
106 #[inline(always)]
107 pub(crate) const fn unset(mut self, other: Self) -> Self {
108 self.0 &= !other.0;
109 self
110 }
111
112 #[allow(dead_code)]
113 #[must_use]
114 #[inline(always)]
115 pub(crate) const fn toggle(mut self, other: Self) -> Self {
116 self.0 ^= other.0;
117 self
118 }
119
120 #[must_use]
122 #[inline(always)]
123 pub const fn is_empty(&self) -> bool {
124 self.0 == Self::EMPTY.0
125 }
126
127 #[must_use]
128 #[inline(always)]
129 pub(crate) const fn is_raised(&self, other: Self) -> bool {
130 self.0 & other.0 != 0
131 }
132}
133
134macro_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
156impl Display for Signals {
157 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
158 if self.is_empty() {
159 return Ok(());
160 }
161
162 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 Ok(())
174 }
175}
176
177impl Debug for Signals {
178 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
179 write!(f, "{self}")
180 }
181}
182
183assert_eq_size!(Signals, u8);