Skip to main content

fast_posit/posit/
unary.rs

1use super::*;
2
3impl<
4  const N: u32,
5  const ES: u32,
6  Int: crate::Int,
7  const RS: u32,
8> Posit<N, ES, Int, RS> {
9  /// Returns the posit value of the lexicographic successor of `self`'s representation.
10  ///
11  /// Note that, unlike every other function of a posit, `next` and `prior` do not produce a
12  /// [NaR](Posit::NAR) output on a [NaR](Posit::NAR) input.
13  ///
14  /// Standard: "[**next**](https://posithub.org/docs/posit_standard-2.pdf#subsection.5.2)".
15  ///
16  /// # Example
17  ///
18  /// ```
19  /// # use fast_posit::*;
20  /// assert_eq!(p8::round_from(1.).next(), p8::round_from(1.125));
21  /// assert_eq!(p8::round_from(128.).next(), p8::round_from(160.));
22  /// assert_eq!(p8::MAX.next(), p8::NAR);
23  /// assert_eq!(p8::NAR.next(), p8::MIN);
24  /// ```
25  #[inline]
26  pub fn next(self) -> Self {
27    Self::from_bits(self.0.wrapping_add(Int::ONE))
28  }
29
30  /// Returns the posit value of the lexicographic predecessor of `self`'s representation.
31  ///
32  /// Note that, unlike every other function of a posit, `next` and `prior` do not produce a
33  /// [NaR](Posit::NAR) output on a [NaR](Posit::NAR) input.
34  ///
35  /// Standard: "[**prior**](https://posithub.org/docs/posit_standard-2.pdf#subsection.5.2)".
36  ///
37  /// # Example
38  ///
39  /// ```
40  /// # use fast_posit::*;
41  /// assert_eq!(p8::round_from(1.).prior(), p8::round_from(0.9375));
42  /// assert_eq!(p8::round_from(128.).prior(), p8::round_from(112.));
43  /// assert_eq!(p8::MIN.prior(), p8::NAR);
44  /// assert_eq!(p8::NAR.prior(), p8::MAX);
45  /// ```
46  #[inline]
47  pub fn prior(self) -> Self {
48    Self::from_bits(self.0.wrapping_sub(Int::ONE))
49  }
50}
51
52impl<const N: u32, const ES: u32, Int: crate::Int, const RS: u32>
53core::ops::Neg for Posit<N, ES, Int, RS> {
54  type Output = Posit<N, ES, Int, RS>;
55
56  #[inline]
57  fn neg(self) -> Self::Output {
58    Posit::from_bits(self.0.wrapping_neg())
59  }
60}
61
62impl<const N: u32, const ES: u32, Int: crate::Int, const RS: u32>
63core::ops::Neg for &Posit<N, ES, Int, RS> {
64  type Output = Posit<N, ES, Int, RS>;
65
66  #[inline]
67  fn neg(self) -> Self::Output {
68    Posit::from_bits(self.0.wrapping_neg())
69  }
70}
71
72// TODO make explicit on every documentation whether or not it rounds? Or better to just make
73// explicit that `-posit` and `posit.abs()` do not?
74//
75// TODO And make explicit that NaR inputs are propagated to NaR outputs everywhere? Or just that
76// `next` and `prior` do not?
77
78impl<const N: u32, const ES: u32, Int: crate::Int, const RS: u32>
79Posit<N, ES, Int, RS> {
80  /// Return the absolute value of `self`.
81  ///
82  /// Standard: "[**abs**](https://posithub.org/docs/posit_standard-2.pdf#subsection.5.2)".
83  ///
84  /// # Example
85  ///
86  /// ```
87  /// # use fast_posit::*;
88  /// assert_eq!(p16::ONE.abs(), p16::MINUS_ONE.abs())
89  /// ```
90  #[inline]
91  pub fn abs(self) -> Self {
92    Posit::from_bits(self.0.wrapping_abs())
93  }
94
95  /// Return [1](Self::ONE) if `self > 0`, [-1](Self::MINUS_ONE) if `self < 0`, [0](Self::ZERO) if
96  /// `self == 0`, and [NaR](Self::NAR) if `self == NaR`.
97  ///
98  /// Standard: "[**sign**](https://posithub.org/docs/posit_standard-2.pdf#subsection.5.2)".
99  ///
100  /// # Example
101  ///
102  /// ```
103  /// # use fast_posit::*;
104  /// assert_eq!(p16::round_from(2).sign(), p16::round_from(1));
105  /// assert_eq!(p16::round_from(-3).sign(), p16::round_from(-1));
106  /// assert_eq!(p16::round_from(0).sign(), p16::round_from(0));
107  /// assert_eq!(p16::NAR.sign(), p16::NAR);
108  /// ```
109  #[inline]
110  pub fn sign(self) -> Self {
111    // If this is true, `self` is 0 or NaR, so return unchanged.
112    if self.is_special() {
113      self
114    }
115    // Otherwise:
116    //
117    //   +1 is bit pattern 0b0100… 
118    //   -1 is bit pattern 0b1100…
119    //
120    // So we just need to set bits 0 to N-3 to `0`, and bit N-2 to `1`.
121    else {
122      let bits = self.to_bits() >> (Self::BITS - 2);
123      let bits = bits | Int::ONE;
124      let bits = bits << (Self::BITS - 2);
125      // SAFETY: The junk bits, if any, of `self.to_bits()` are unchanged, so `bits` is still valid
126      // input to `from_bits_unchecked`.
127      unsafe { Posit::from_bits_unchecked(bits) }
128    }
129  }
130}
131
132#[cfg(test)]
133mod tests {
134  use super::*;
135  use malachite::rational::Rational;
136
137  mod neg {
138    use super::*;
139
140    #[test]
141    fn p8() {
142      assert_eq!(-crate::p8::ZERO, crate::p8::ZERO);
143      assert_eq!(-crate::p8::NAR, crate::p8::NAR);
144      for p in crate::p8::cases_exhaustive() {
145        assert_eq!(Rational::try_from(-p).unwrap(), -Rational::try_from(p).unwrap())
146      }
147    }
148
149    #[test]
150    fn posit_10_1() {
151      assert_eq!(-Posit::<10, 0, i16>::ZERO, Posit::<10, 0, i16>::ZERO);
152      assert_eq!(-Posit::<10, 0, i16>::NAR, Posit::<10, 0, i16>::NAR);
153      for p in Posit::<10, 0, i16>::cases_exhaustive() {
154        assert_eq!(Rational::try_from(-p).unwrap(), -Rational::try_from(p).unwrap())
155      }
156    }
157
158    #[test]
159    fn bposit_16_5_6() {
160      assert_eq!(-Posit::<16, 5, i16, 6>::ZERO, Posit::<16, 5, i16, 6>::ZERO);
161      assert_eq!(-Posit::<16, 5, i16, 6>::NAR, Posit::<16, 5, i16, 6>::NAR);
162      for p in Posit::<16, 5, i16, 6>::cases_exhaustive() {
163        assert_eq!(Rational::try_from(-p).unwrap(), -Rational::try_from(p).unwrap())
164      }
165    }
166  }
167
168  mod abs {
169    use super::*;
170
171    #[test]
172    fn p8() {
173      use malachite::base::num::arithmetic::traits::Abs;
174      assert_eq!(crate::p8::ZERO.abs(), crate::p8::ZERO);
175      assert_eq!(crate::p8::NAR.abs(), crate::p8::NAR);
176      for p in crate::p8::cases_exhaustive() {
177        assert_eq!(Rational::try_from(p.abs()).unwrap(), Rational::try_from(p).unwrap().abs())
178      }
179    }
180
181    #[test]
182    fn posit_10_1() {
183      use malachite::base::num::arithmetic::traits::Abs;
184      assert_eq!(Posit::<10, 0, i16>::ZERO.abs(), Posit::<10, 0, i16>::ZERO);
185      assert_eq!(Posit::<10, 0, i16>::NAR.abs(), Posit::<10, 0, i16>::NAR);
186      for p in Posit::<10, 0, i16>::cases_exhaustive() {
187        assert_eq!(Rational::try_from(p.abs()).unwrap(), Rational::try_from(p).unwrap().abs())
188      }
189    }
190
191    #[test]
192    fn bposit_16_5_6() {
193      use malachite::base::num::arithmetic::traits::Abs;
194      assert_eq!(Posit::<16, 5, i16, 6>::ZERO.abs(), Posit::<16, 5, i16, 6>::ZERO);
195      assert_eq!(Posit::<16, 5, i16, 6>::NAR.abs(), Posit::<16, 5, i16, 6>::NAR);
196      for p in Posit::<16, 5, i16, 6>::cases_exhaustive() {
197        assert_eq!(Rational::try_from(p.abs()).unwrap(), Rational::try_from(p).unwrap().abs())
198      }
199    }
200  }
201
202  mod sign {
203    use super::*;
204
205    #[test]
206    fn p8() {
207      assert_eq!(crate::p8::ZERO.sign(), crate::p8::ZERO);
208      assert_eq!(crate::p8::NAR.sign(), crate::p8::NAR);
209      for p in crate::p8::cases_exhaustive() {
210        assert_eq!(
211          p.sign(),
212          if p > Posit::ZERO {Posit::ONE} else {Posit::MINUS_ONE},
213        )
214      }
215    }
216
217    #[test]
218    fn posit_10_1() {
219      assert_eq!(Posit::<10, 0, i16>::ZERO.sign(), Posit::<10, 0, i16>::ZERO);
220      assert_eq!(Posit::<10, 0, i16>::NAR.sign(), Posit::<10, 0, i16>::NAR);
221      for p in Posit::<10, 0, i16>::cases_exhaustive() {
222        assert_eq!(
223          p.sign(),
224          if p > Posit::ZERO {Posit::ONE} else {Posit::MINUS_ONE},
225        )
226      }
227    }
228
229    #[test]
230    fn bposit_16_5_6() {
231      assert_eq!(Posit::<16, 5, i16, 6>::ZERO.sign(), Posit::<16, 5, i16, 6>::ZERO);
232      assert_eq!(Posit::<16, 5, i16, 6>::NAR.sign(), Posit::<16, 5, i16, 6>::NAR);
233      for p in Posit::<16, 5, i16, 6>::cases_exhaustive() {
234        assert_eq!(
235          p.sign(),
236          if p > Posit::ZERO {Posit::ONE} else {Posit::MINUS_ONE},
237        )
238      }
239    }
240  }
241}