fast_posit/posit/quire/
ops.rs

1use super::*;
2
3impl<
4  const N: u32,
5  const ES: u32,
6  const SIZE: usize,
7> Quire<N, ES, SIZE> {
8  pub(crate) fn add<Int: crate::Int>(&mut self, posit: Posit<N, ES, Int>) {
9    if posit == Posit::ZERO {
10      ()
11    } else if posit == Posit::NAR || self.is_nar() {
12      *self = Quire::NAR
13    } else {
14      // SAFETY: `posit` is not 0 or NaR
15      let decoded = unsafe { posit.decode_regular() };
16      // SAFETY: `decoded` comes from `Posit::decode_regular`, therefore its `exp` is in bounds
17      unsafe { self.accumulate_decoded(decoded) }
18    }
19  }
20
21  pub(crate) fn sub<Int: crate::Int>(&mut self, posit: Posit<N, ES, Int>) {
22    self.add(-posit)
23  }
24}
25
26impl<
27  const N: u32,
28  const ES: u32,
29  Int: crate::Int,
30  const SIZE: usize,
31> core::ops::AddAssign<Posit<N, ES, Int>> for Quire<N, ES, SIZE> {
32  /// Standard: "[**qAddP**](https://posithub.org/docs/posit_standard-2.pdf#subsection.5.11)".
33  ///
34  /// # Example
35  ///
36  /// ```
37  /// # use fast_posit::*;
38  /// let mut quire = q16::from(p16::ONE);
39  /// quire += p16::round_from(0.42);
40  /// assert_eq!(p16::round_from(1.42), (&quire).round_into())
41  /// ```
42  fn add_assign(&mut self, rhs: Posit<N, ES, Int>) {
43    self.add(rhs)
44  }
45}
46
47impl<
48  const N: u32,
49  const ES: u32,
50  Int: crate::Int,
51  const SIZE: usize,
52> core::ops::AddAssign<&Posit<N, ES, Int>> for Quire<N, ES, SIZE> {
53  /// Standard: "[**qAddP**](https://posithub.org/docs/posit_standard-2.pdf#subsection.5.11)".
54  ///
55  /// # Example
56  ///
57  /// ```
58  /// # use fast_posit::*;
59  /// let mut quire = q16::from(p16::ONE);
60  /// quire += p16::round_from(0.42);
61  /// assert_eq!(p16::round_from(1.42), (&quire).round_into())
62  /// ```
63  fn add_assign(&mut self, rhs: &Posit<N, ES, Int>) {
64    self.add(*rhs)
65  }
66}
67
68impl<
69  const N: u32,
70  const ES: u32,
71  Int: crate::Int,
72  const SIZE: usize,
73> core::ops::SubAssign<Posit<N, ES, Int>> for Quire<N, ES, SIZE> {
74  /// Standard: "[**qSubP**](https://posithub.org/docs/posit_standard-2.pdf#subsection.5.11)".
75  ///
76  /// # Example
77  ///
78  /// ```
79  /// # use fast_posit::*;
80  /// let mut quire = q16::from(p16::ONE);
81  /// quire -= p16::round_from(0.42);
82  /// assert_eq!(p16::round_from(0.58), (&quire).round_into())
83  /// ```
84  fn sub_assign(&mut self, rhs: Posit<N, ES, Int>) {
85    self.sub(rhs)
86  }
87}
88
89impl<
90  const N: u32,
91  const ES: u32,
92  Int: crate::Int,
93  const SIZE: usize,
94> core::ops::SubAssign<&Posit<N, ES, Int>> for Quire<N, ES, SIZE> {
95  /// Standard: "[**qSubP**](https://posithub.org/docs/posit_standard-2.pdf#subsection.5.11)".
96  ///
97  /// # Example
98  ///
99  /// ```
100  /// # use fast_posit::*;
101  /// let mut quire = q16::from(p16::ONE);
102  /// quire -= p16::round_from(0.42);
103  /// assert_eq!(p16::round_from(0.58), (&quire).round_into())
104  /// ```
105  fn sub_assign(&mut self, rhs: &Posit<N, ES, Int>) {
106    self.sub(*rhs)
107  }
108}
109
110#[cfg(test)]
111mod tests {
112  use super::*;
113  use malachite::rational::Rational;
114  use proptest::prelude::*;
115
116  /// `Quire::from(posit) += posit`
117  mod posit_posit {
118    // TODO these tests are basic: they test for two posits a and b whether summing them on the quire
119    // yields the correct result. But more tests are needed: summing vectors of n posits, not just 2.
120    use super::*;
121
122    macro_rules! test_exhaustive {
123      ($name:ident, $posit:ty, $quire:ty) => {
124        #[test]
125        fn $name() {
126          for a in <$posit>::cases_exhaustive_all() {
127            for b in <$posit>::cases_exhaustive_all() {
128              let posit = a + b;
129              let mut quire = <$quire>::from(a);
130              quire += b;
131              assert!(super::rational::try_is_correct_rounded(Rational::try_from(quire), posit))
132            }
133          }
134        }
135      };
136    }
137
138    macro_rules! test_proptest {
139      ($name:ident, $posit:ty, $quire:ty) => {
140        proptest!{
141          #![proptest_config(ProptestConfig::with_cases(crate::PROPTEST_CASES))]
142          #[test]
143          fn $name(
144            a in <$posit>::cases_proptest_all(),
145            b in <$posit>::cases_proptest_all(),
146          ) {
147            let posit = a + b;
148            let mut quire = <$quire>::from(a);
149            quire += b;
150            assert!(super::rational::try_is_correct_rounded(Rational::try_from(quire), posit))
151          }
152        }
153      };
154    }
155
156    test_exhaustive!{posit_10_0_exhaustive, Posit<10, 0, i16>, Quire<10, 0, 128>}
157    test_exhaustive!{posit_10_1_exhaustive, Posit<10, 1, i16>, Quire<10, 1, 128>}
158    test_exhaustive!{posit_10_2_exhaustive, Posit<10, 2, i16>, Quire<10, 2, 128>}
159    test_exhaustive!{posit_10_3_exhaustive, Posit<10, 3, i16>, Quire<10, 3, 128>}
160    test_exhaustive!{posit_8_0_exhaustive, Posit<8, 0, i8>, Quire<8, 0, 128>}
161
162    test_exhaustive!{p8_exhaustive, crate::p8, crate::q8}
163    test_proptest!{p16_proptest, crate::p16, crate::q16}
164    test_proptest!{p32_proptest, crate::p32, crate::q32}
165    test_proptest!{p64_proptest, crate::p64, crate::q64}
166
167    test_exhaustive!{posit_3_0_exhaustive, Posit<3, 0, i8>, Quire<3, 0, 128>}
168    test_exhaustive!{posit_4_0_exhaustive, Posit<4, 0, i8>, Quire<4, 0, 128>}
169    test_exhaustive!{posit_4_1_exhaustive, Posit<4, 1, i8>, Quire<4, 1, 128>}
170  }
171
172  /// `quire += posit`
173  mod quire_posit {
174    use super::*;
175
176    macro_rules! test_proptest {
177      ($name:ident, $posit:ty, $quire:ty) => {
178        proptest!{
179          #![proptest_config(ProptestConfig::with_cases(crate::PROPTEST_CASES))]
180          #[test]
181          fn $name(
182            q in <$quire>::cases_proptest_all(),
183            p in <$posit>::cases_proptest_all(),
184          ) {
185            let mut quire = q.clone();
186            quire += p;
187            match (Rational::try_from(q), Rational::try_from(p)) {
188              (Ok(q), Ok(p)) => assert_eq!(Rational::try_from(quire), Ok(q + p)),
189              _ => assert!(quire.is_nar()),
190            }
191          }
192        }
193      };
194    }
195
196    test_proptest!{posit_10_0_proptest, Posit<10, 0, i16>, Quire<10, 0, 128>}
197    test_proptest!{posit_10_1_proptest, Posit<10, 1, i16>, Quire<10, 1, 128>}
198    test_proptest!{posit_10_2_proptest, Posit<10, 2, i16>, Quire<10, 2, 128>}
199    test_proptest!{posit_10_3_proptest, Posit<10, 3, i16>, Quire<10, 3, 128>}
200    test_proptest!{posit_8_0_proptest, Posit<8, 0, i8>, Quire<8, 0, 128>}
201
202    test_proptest!{p8_proptest, crate::p8, crate::q8}
203    test_proptest!{p16_proptest, crate::p16, crate::q16}
204    test_proptest!{p32_proptest, crate::p32, crate::q32}
205    test_proptest!{p64_proptest, crate::p64, crate::q64}
206
207    test_proptest!{posit_3_0_proptest, Posit<3, 0, i8>, Quire<3, 0, 128>}
208    test_proptest!{posit_4_0_proptest, Posit<4, 0, i8>, Quire<4, 0, 128>}
209    test_proptest!{posit_4_1_proptest, Posit<4, 1, i8>, Quire<4, 1, 128>}
210  }
211}