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