1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
use crate::u16_with_sign;

impl super::P16E1 {
    pub const fn ceil(self) -> Self {
        let mut mask = 0x2000_u16;
        let mut scale = 0_u16;

        let mut ui_a = self.to_bits();
        let sign = ui_a > 0x8000;

        // sign is True if p_a > NaR.
        if sign {
            ui_a = ui_a.wrapping_neg() // A is now |A|.
        };

        let u_a = if ui_a == 0 {
            return self;
        } else if ui_a <= 0x4000 {
            // 0 <= |pA| < 1 ceiling to zero.(if not negative and whole number)
            if sign && (ui_a != 0x4000) {
                0x0
            } else {
                0x4000
            }
        } else if ui_a <= 0x5000 {
            // 1 <= x < 2 ceiling to 1 (if not negative and whole number)
            if sign && (ui_a != 0x5000) {
                0x4000
            } else {
                0x5000
            }
        } else if ui_a <= 0x5800 {
            // 2 <= x < 3 ceiling to 2 (if not negative and whole number)
            if sign & (ui_a != 0x5800) {
                0x5000
            } else {
                0x5800
            }
        } else if ui_a >= 0x7C00 {
            // If |A| is 256 or greater, leave it unchanged.
            return self; // This also takes care of the NaR case, 0x8000.
        } else {
            // 34% of the cases, we have to decode the posit.
            while (mask & ui_a) != 0 {
                // Increment scale by 2 for each regime sign bit.
                scale += 2; // Regime sign bit is always 1 in this range.
                mask >>= 1; // Move the mask right, to the next bit.
            }
            mask >>= 1; // Skip over termination bit.
            if (mask & ui_a) != 0 {
                scale += 1; // If exponent is 1, increment the scale.
            }
            mask >>= scale; // Point to the last bit of the integer part.

            mask >>= 1;
            let mut tmp = ui_a & mask;
            let bit_n_plus_one = tmp; // "True" if nonzero.
            ui_a ^= tmp; // Erase the bit, if it was set.
            tmp = ui_a & (mask - 1); // tmp has any remaining bits = bitsMore
            ui_a ^= tmp; // Erase those bits, if any were set.

            if !sign && (bit_n_plus_one | tmp) != 0 {
                ui_a += mask << 1;
            }
            ui_a
        };
        Self::from_bits(u16_with_sign(u_a, sign))
    }
}