softposit/p16e1/math/
floor.rs

1use crate::u16_with_sign;
2
3impl super::P16E1 {
4    pub const fn floor(self) -> Self {
5        let mut mask = 0x2000_u16;
6        let mut scale = 0_u16;
7
8        let mut ui_a = self.to_bits();
9        let sign = ui_a > 0x8000;
10
11        // sign is True if p_a > NaR.
12        if sign {
13            ui_a = ui_a.wrapping_neg() // A is now |A|.
14        };
15
16        let u_a = if ui_a < 0x4000 {
17            // 0 <= |pA| < 1 floor to zero.(if not negative and whole number)
18            if sign && (ui_a != 0x0) {
19                0x4000
20            } else {
21                0x0
22            }
23        } else if ui_a < 0x5000 {
24            // 1 <= x < 2 floor to 1 (if not negative and whole number)
25            if sign && (ui_a != 0x4000) {
26                0x5000
27            } else {
28                0x4000
29            }
30        } else if ui_a < 0x5800 {
31            // 2 <= x < 3 floor to 2 (if not negative and whole number)
32            if sign & (ui_a != 0x5000) {
33                0x5800
34            } else {
35                0x5000
36            }
37        } else if ui_a >= 0x7C00 {
38            // If |A| is 256 or greater, leave it unchanged.
39            return self; // This also takes care of the NaR case, 0x8000.
40        } else {
41            // 34% of the cases, we have to decode the posit.
42            while (mask & ui_a) != 0 {
43                // Increment scale by 2 for each regime sign bit.
44                scale += 2; // Regime sign bit is always 1 in this range.
45                mask >>= 1; // Move the mask right, to the next bit.
46            }
47            mask >>= 1; // Skip over termination bit.
48            if (mask & ui_a) != 0 {
49                scale += 1; // If exponent is 1, increment the scale.
50            }
51            mask >>= scale; // Point to the last bit of the integer part.
52
53            mask >>= 1;
54            let mut tmp = ui_a & mask;
55            let bit_n_plus_one = tmp; // "True" if nonzero.
56            ui_a ^= tmp; // Erase the bit, if it was set.
57            tmp = ui_a & (mask - 1); // tmp has any remaining bits = bitsMore
58            ui_a ^= tmp; // Erase those bits, if any were set.
59
60            if sign && ((bit_n_plus_one | tmp) != 0) {
61                ui_a += mask << 1;
62            }
63            ui_a
64        };
65        Self::from_bits(u16_with_sign(u_a, sign))
66    }
67}