Skip to main content

fastnum/decimal/
context.rs

1mod rounding_mode;
2mod signal_traps;
3
4pub use rounding_mode::RoundingMode;
5pub use signal_traps::SignalsTraps;
6
7use core::fmt::{Debug, Display, Formatter};
8
9use crate::utils::assert_eq_size;
10
11/// # Decimal Context
12///
13/// The context represents the user-selectable parameters and rules which govern
14/// the results of arithmetic operations (for example, the rounding mode when
15/// rounding occurs).
16#[derive(Copy, Clone, Hash, Eq, PartialEq)]
17#[repr(C)]
18pub struct Context {
19    rounding_mode: RoundingMode,
20    signal_traps: SignalsTraps,
21}
22
23impl Context {
24    const DEFAULT: Self = Self {
25        rounding_mode: RoundingMode::default(),
26        signal_traps: SignalsTraps::default(),
27    };
28
29    /// Returns the [Default Decimal Context](#crate::default-decimal-context).
30    #[inline(always)]
31    #[must_use]
32    pub const fn default() -> Self {
33        Self::DEFAULT
34    }
35
36    /// Apply the given [RoundingMode] to the `Context`.
37    #[must_use]
38    #[inline(always)]
39    pub const fn with_rounding_mode(mut self, rm: RoundingMode) -> Self {
40        self.rounding_mode = rm;
41        self
42    }
43
44    /// Apply no traps to given `Context`.
45    #[inline(always)]
46    #[must_use]
47    pub const fn without_traps(mut self) -> Self {
48        self.signal_traps = SignalsTraps::empty();
49        self
50    }
51
52    /// Method applies specified [SignalsTraps] to the given context.
53    /// # Examples
54    ///
55    /// ```
56    /// use fastnum::{*, decimal::*};
57    ///
58    /// let ctx = Context::default().without_traps();
59    ///
60    /// // No panic! We can divide by zero!
61    /// let res = dec256!(1.0).with_ctx(ctx) / dec256!(0).with_ctx(ctx);
62    ///
63    /// assert!(res.is_infinite());
64    /// assert!(res.is_op_div_by_zero());
65    /// assert!(res.is_op_invalid());
66    /// ```
67    #[must_use]
68    #[inline(always)]
69    pub const fn with_signal_traps(mut self, traps: SignalsTraps) -> Self {
70        self.signal_traps = traps;
71        self
72    }
73
74    /// Get [RoundingMode] of given `Context`.
75    #[must_use]
76    #[inline(always)]
77    pub const fn rounding_mode(&self) -> RoundingMode {
78        self.rounding_mode
79    }
80
81    /// Get [SignalsTraps] of given `Context`.
82    #[must_use]
83    #[inline(always)]
84    pub const fn signal_traps(&self) -> SignalsTraps {
85        self.signal_traps
86    }
87
88    #[inline(always)]
89    pub(crate) const fn new(rounding_mode: RoundingMode, signal_traps: SignalsTraps) -> Self {
90        Self {
91            rounding_mode,
92            signal_traps,
93        }
94    }
95
96    #[inline(always)]
97    pub(crate) const fn merge(mut self, other: Self) -> Self {
98        self.signal_traps = self.signal_traps.merge(other.signal_traps);
99
100        if !other.rounding_mode.is_default() {
101            self.rounding_mode = other.rounding_mode;
102        }
103
104        self
105    }
106}
107
108impl Display for Context {
109    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
110        write!(f, "R={}, S={}", self.rounding_mode, self.signal_traps)
111    }
112}
113
114impl Debug for Context {
115    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
116        write!(f, "{self}")
117    }
118}
119
120assert_eq_size!(Context, u16);