Coverage Report

Created: 2026-03-31 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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);