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}