fast_posit/posit/
unary.rs

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