Skip to main content

machina_softfloat/
env.rs

1// SPDX-License-Identifier: MIT
2// Floating-point environment: rounding mode, exception flags, tininess.
3
4use core::ops::{BitOr, BitOrAssign};
5
6// ---------------------------------------------------------------
7// Rounding mode
8// ---------------------------------------------------------------
9
10#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
11#[repr(u8)]
12pub enum RoundMode {
13    #[default]
14    NearEven = 0,
15    ToZero = 1,
16    Down = 2,
17    Up = 3,
18    NearMaxMag = 4,
19    Odd = 5,
20}
21
22// ---------------------------------------------------------------
23// Exception flags (bitflags-style)
24// ---------------------------------------------------------------
25
26#[derive(Clone, Copy, Debug, PartialEq, Eq)]
27pub struct ExcFlags(pub u8);
28
29impl ExcFlags {
30    pub const NONE: Self = Self(0);
31    pub const INVALID: Self = Self(1);
32    pub const DIVBYZERO: Self = Self(2);
33    pub const OVERFLOW: Self = Self(4);
34    pub const UNDERFLOW: Self = Self(8);
35    pub const INEXACT: Self = Self(16);
36
37    #[inline]
38    pub fn is_empty(self) -> bool {
39        self.0 == 0
40    }
41    #[inline]
42    pub fn contains(self, other: Self) -> bool {
43        self.0 & other.0 != 0
44    }
45}
46
47impl BitOr for ExcFlags {
48    type Output = Self;
49    #[inline]
50    fn bitor(self, rhs: Self) -> Self {
51        Self(self.0 | rhs.0)
52    }
53}
54
55impl BitOrAssign for ExcFlags {
56    #[inline]
57    fn bitor_assign(&mut self, rhs: Self) {
58        self.0 |= rhs.0;
59    }
60}
61
62// ---------------------------------------------------------------
63// Tininess detection mode
64// ---------------------------------------------------------------
65
66#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
67pub enum Tininess {
68    BeforeRounding,
69    #[default]
70    AfterRounding,
71}
72
73// ---------------------------------------------------------------
74// Floating-point environment
75// ---------------------------------------------------------------
76
77#[derive(Clone, Copy, Debug)]
78pub struct FloatEnv {
79    round_mode: RoundMode,
80    flags: ExcFlags,
81    tininess: Tininess,
82    default_nan: bool,
83}
84
85impl FloatEnv {
86    pub fn new(rm: RoundMode) -> Self {
87        Self {
88            round_mode: rm,
89            flags: ExcFlags::NONE,
90            tininess: Tininess::AfterRounding,
91            default_nan: false,
92        }
93    }
94
95    #[inline]
96    pub fn round_mode(&self) -> RoundMode {
97        self.round_mode
98    }
99    #[inline]
100    pub fn set_round_mode(&mut self, rm: RoundMode) {
101        self.round_mode = rm;
102    }
103
104    #[inline]
105    pub fn flags(&self) -> ExcFlags {
106        self.flags
107    }
108    #[inline]
109    pub fn set_flags(&mut self, f: ExcFlags) {
110        self.flags = f;
111    }
112    #[inline]
113    pub fn raise(&mut self, f: ExcFlags) {
114        self.flags |= f;
115    }
116    #[inline]
117    pub fn clear_flags(&mut self) {
118        self.flags = ExcFlags::NONE;
119    }
120
121    #[inline]
122    pub fn tininess(&self) -> Tininess {
123        self.tininess
124    }
125    #[inline]
126    pub fn set_tininess(&mut self, t: Tininess) {
127        self.tininess = t;
128    }
129
130    #[inline]
131    pub fn default_nan(&self) -> bool {
132        self.default_nan
133    }
134    #[inline]
135    pub fn set_default_nan(&mut self, v: bool) {
136        self.default_nan = v;
137    }
138}
139
140impl Default for FloatEnv {
141    fn default() -> Self {
142        Self::new(RoundMode::NearEven)
143    }
144}