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 pub const NAR: Self = Self::new(-0x_8000_0000);
17
18 pub const ZERO: Self = Self::new(0);
20
21 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}