softposit/
pxe1.rs

1use core::cmp::Ordering;
2
3mod convert;
4mod math;
5mod ops;
6
7#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
8#[repr(transparent)]
9pub struct PxE1<const N: u32>(i32);
10
11impl<const N: u32> PxE1<{ N }> {
12    pub const ES: usize = 1;
13    pub const USEED: usize = 4;
14
15    /// Not a Real (NaR).
16    pub const NAR: Self = Self::new(-0x_8000_0000);
17
18    /// Zero.
19    pub const ZERO: Self = Self::new(0);
20
21    /// Identity.
22    pub const ONE: Self = Self::new(0x_4000_0000);
23
24    #[inline]
25    pub const fn new(i: i32) -> Self {
26        Self(i)
27    }
28    #[inline]
29    pub const fn is_zero(self) -> bool {
30        self.eq(Self::ZERO)
31    }
32    #[inline]
33    pub const fn is_nar(self) -> bool {
34        self.eq(Self::NAR)
35    }
36    #[inline]
37    pub const fn from_bits(v: u32) -> Self {
38        Self(v as _)
39    }
40    #[inline]
41    pub const fn to_bits(self) -> u32 {
42        self.0 as _
43    }
44
45    #[inline]
46    pub const fn eq(self, other: Self) -> bool {
47        self.0 == other.0
48    }
49    #[inline]
50    pub const fn cmp(self, other: Self) -> Ordering {
51        let a = self.0;
52        let b = other.0;
53        if a == b {
54            Ordering::Equal
55        } else if a < b {
56            Ordering::Less
57        } else {
58            Ordering::Greater
59        }
60    }
61    #[inline]
62    pub const fn lt(&self, other: Self) -> bool {
63        self.0 < other.0
64    }
65    #[inline]
66    pub const fn le(&self, other: Self) -> bool {
67        self.0 <= other.0
68    }
69    #[inline]
70    pub const fn ge(&self, other: Self) -> bool {
71        self.0 >= other.0
72    }
73    #[inline]
74    pub const fn gt(&self, other: Self) -> bool {
75        self.0 > other.0
76    }
77}
78
79impl<const N: u32> PxE1<{ N }> {
80    pub(crate) const fn mask() -> u32 {
81        ((-0x_8000_0000_i32) >> (N - 1)) as u32
82    }
83    pub const SIGN_MASK: u32 = 0x_8000_0000;
84    pub const REGIME_SIGN_MASK: u32 = 0x_4000_0000;
85
86    #[inline]
87    pub(crate) const fn sign_ui(a: u32) -> bool {
88        (a & Self::SIGN_MASK) != 0
89    }
90
91    #[inline]
92    const fn sign_reg_ui(a: u32) -> bool {
93        (a & Self::REGIME_SIGN_MASK) != 0
94    }
95
96    #[inline]
97    const fn pack_to_ui(regime: u32, exp_a: u32, frac_a: u32) -> u32 {
98        regime + exp_a + frac_a
99    }
100
101    #[inline]
102    pub(crate) const fn separate_bits(bits: u32) -> (i8, i32, u32) {
103        let (k, tmp) = Self::separate_bits_tmp(bits);
104        (
105            k,
106            (tmp >> ((N as usize) - 1 - Self::ES)) as i32,
107            (tmp | 0x4000_0000) & 0x7FFF_FFFF,
108        )
109    }
110
111    #[inline]
112    pub(crate) const fn separate_bits_tmp(bits: u32) -> (i8, u32) {
113        let mut k = 0;
114        let mut tmp = bits << 2;
115        if Self::sign_reg_ui(bits) {
116            while (tmp & 0x8000_0000) != 0 {
117                k += 1;
118                tmp <<= 1;
119            }
120        } else {
121            k = -1;
122            while (tmp & 0x8000_0000) == 0 {
123                k -= 1;
124                tmp <<= 1;
125            }
126            tmp &= 0x7FFF_FFFF;
127        }
128        (k, tmp)
129    }
130
131    #[inline]
132    const fn calculate_regime(k: i8) -> (u32, bool, u32) {
133        let reg;
134        if k < 0 {
135            reg = (-k) as u32;
136            (0x_4000_0000_u32.wrapping_shr(reg), false, reg)
137        } else {
138            reg = (k + 1) as u32;
139            (0x_7fff_ffff - 0x_7fff_ffff_u32.wrapping_shr(reg), true, reg)
140        }
141    }
142}