1#![allow(clippy::unused_unit)]
2
3use super::*;
4
5impl<
6 const N: u32,
7 const ES: u32,
8 Int: crate::Int,
9 const SIZE: usize,
10> core::ops::AddAssign<Posit<N, ES, Int>> for Quire<N, ES, SIZE> {
11 fn add_assign(&mut self, rhs: Posit<N, ES, Int>) {
22 if rhs == Posit::ZERO {
23 ()
24 } else if crate::utl::unlikely(rhs == Posit::NAR) || crate::utl::unlikely(self.is_nar()) {
25 self.set_nar()
26 } else {
27 let decoded = unsafe { rhs.decode_regular() };
29 unsafe { self.add_posit_kernel(decoded) }
31 }
32 }
33}
34
35impl<
36 const N: u32,
37 const ES: u32,
38 Int: crate::Int,
39 const SIZE: usize,
40> core::ops::AddAssign<&Posit<N, ES, Int>> for Quire<N, ES, SIZE> {
41 #[inline]
52 fn add_assign(&mut self, rhs: &Posit<N, ES, Int>) {
53 *self += *rhs
54 }
55}
56
57impl<
58 const N: u32,
59 const ES: u32,
60 Int: crate::Int,
61 const SIZE: usize,
62> core::ops::SubAssign<Posit<N, ES, Int>> for Quire<N, ES, SIZE> {
63 #[inline]
74 fn sub_assign(&mut self, rhs: Posit<N, ES, Int>) {
75 *self += -rhs
76 }
77}
78
79impl<
80 const N: u32,
81 const ES: u32,
82 Int: crate::Int,
83 const SIZE: usize,
84> core::ops::SubAssign<&Posit<N, ES, Int>> for Quire<N, ES, SIZE> {
85 #[inline]
96 fn sub_assign(&mut self, rhs: &Posit<N, ES, Int>) {
97 *self += -*rhs
98 }
99}
100
101impl<
102 const N: u32,
103 const ES: u32,
104 const SIZE: usize,
105> Quire<N, ES, SIZE> {
106 pub fn add_prod<Int: crate::Int>(&mut self, a: Posit<N, ES, Int>, b: Posit<N, ES, Int>) {
110 if crate::utl::unlikely(a == Posit::NAR) || crate::utl::unlikely(b == Posit::NAR) {
111 self.set_nar()
112 } else if a == Posit::ZERO || b == Posit::ZERO || crate::utl::unlikely(self.is_nar()) {
113 ()
114 } else {
115 let a = unsafe { a.decode_regular() };
117 let b = unsafe { b.decode_regular() };
118 unsafe { self.add_posit_prod_kernel(a, b) }
120 }
121 }
122
123 #[inline]
127 pub fn sub_prod<Int: crate::Int>(&mut self, a: Posit<N, ES, Int>, b: Posit<N, ES, Int>) {
128 self.add_prod(-a, b)
129 }
130}
131
132impl<
133 const N: u32,
134 const ES: u32,
135 const SIZE: usize,
136> core::ops::AddAssign<&Quire<N, ES, SIZE>> for Quire<N, ES, SIZE> {
137 fn add_assign(&mut self, rhs: &Quire<N, ES, SIZE>) {
139 if crate::utl::unlikely(self.is_nar()) {
140 ()
141 } else if crate::utl::unlikely(rhs.is_nar()) {
142 self.set_nar()
143 } else {
144 unsafe { self.accumulate_slice(rhs.as_u64_array(), 0) }
148 }
149 }
150}
151
152impl<
164 const N: u32,
165 const ES: u32,
166 const SIZE: usize,
167> core::ops::Neg for Quire<N, ES, SIZE> {
168 type Output = Self;
169
170 fn neg(mut self) -> Self::Output {
171 let mut carry = true;
173 for i in self.as_u64_array_mut() {
174 *i = (!*i).wrapping_add(u64::from(carry));
175 carry &= *i == 0;
176 }
177 self
178 }
179}
180
181impl<
182 const N: u32,
183 const ES: u32,
184 const SIZE: usize,
185> Quire<N, ES, SIZE> {
186 pub fn abs(self) -> Self {
190 let is_negative = (self.as_u64_array()[Self::LEN_U64 - 1] as i64) < 0;
191 if is_negative {-self} else {self}
192 }
193}
194
195#[cfg(test)]
196mod tests {
197 use super::*;
198 use malachite::rational::Rational;
199 use proptest::prelude::*;
200
201 mod posit_posit {
203 use super::*;
206
207 macro_rules! test_exhaustive {
208 ($name:ident, $posit:ty, $quire:ty) => {
209 #[test]
210 fn $name() {
211 for a in <$posit>::cases_exhaustive_all() {
212 for b in <$posit>::cases_exhaustive_all() {
213 let posit = a + b;
214 let mut quire = <$quire>::from(a);
215 quire += b;
216 assert!(super::rational::try_is_correct_rounded(Rational::try_from(quire), posit))
217 }
218 }
219 }
220 };
221 }
222
223 macro_rules! test_proptest {
224 ($name:ident, $posit:ty, $quire:ty) => {
225 proptest!{
226 #![proptest_config(ProptestConfig::with_cases(crate::PROPTEST_CASES))]
227 #[test]
228 fn $name(
229 a in <$posit>::cases_proptest_all(),
230 b in <$posit>::cases_proptest_all(),
231 ) {
232 let posit = a + b;
233 let mut quire = <$quire>::from(a);
234 quire += b;
235 assert!(super::rational::try_is_correct_rounded(Rational::try_from(quire), posit))
236 }
237 }
238 };
239 }
240
241 test_exhaustive!{posit_10_0_exhaustive, Posit<10, 0, i16>, Quire<10, 0, 128>}
242 test_exhaustive!{posit_10_1_exhaustive, Posit<10, 1, i16>, Quire<10, 1, 128>}
243 test_exhaustive!{posit_10_2_exhaustive, Posit<10, 2, i16>, Quire<10, 2, 128>}
244 test_exhaustive!{posit_10_3_exhaustive, Posit<10, 3, i16>, Quire<10, 3, 128>}
245 test_exhaustive!{posit_8_0_exhaustive, Posit<8, 0, i8>, Quire<8, 0, 128>}
246
247 test_exhaustive!{p8_exhaustive, crate::p8, crate::q8}
248 test_proptest!{p16_proptest, crate::p16, crate::q16}
249 test_proptest!{p32_proptest, crate::p32, crate::q32}
250 test_proptest!{p64_proptest, crate::p64, crate::q64}
251
252 test_exhaustive!{posit_3_0_exhaustive, Posit<3, 0, i8>, Quire<3, 0, 128>}
253 test_exhaustive!{posit_4_0_exhaustive, Posit<4, 0, i8>, Quire<4, 0, 128>}
254 test_exhaustive!{posit_4_1_exhaustive, Posit<4, 1, i8>, Quire<4, 1, 128>}
255 }
256
257 mod quire_posit {
259 use super::*;
260
261 #[test]
263 fn q8_overflow_positive() {
264 use crate::{p8, q8};
265 let mut quire = q8::MAX;
266 assert!(!quire.is_nar());
267 quire -= p8::ONE;
268 assert!(!quire.is_nar());
269 quire += p8::ONE;
270 assert!(!quire.is_nar());
271 quire += p8::ONE;
272 assert!(quire.is_nar());
273 }
274
275 #[test]
277 fn q8_overflow_negative() {
278 use crate::{p8, q8};
279 let mut quire = q8::MIN;
280 assert!(!quire.is_nar());
281 quire += p8::ONE;
282 assert!(!quire.is_nar());
283 quire -= p8::ONE;
284 assert!(!quire.is_nar());
285 quire -= p8::ONE;
286 assert!(quire.is_nar());
287 }
288
289 macro_rules! test_proptest {
290 ($name:ident, $posit:ty, $quire:ty) => {
291 proptest!{
292 #![proptest_config(ProptestConfig::with_cases(crate::PROPTEST_CASES))]
293 #[test]
294 fn $name(
295 q in <$quire>::cases_proptest_all(),
296 p in <$posit>::cases_proptest_all(),
297 ) {
298 let mut sum = q.clone();
299 sum += p;
300 match (Rational::try_from(q), Rational::try_from(p)) {
301 (Ok(q), Ok(p)) => assert!(super::rational::quire_is_correct_rounded(q + p, sum)),
302 _ => assert!(sum.is_nar()),
303 }
304 }
305 }
306 };
307 }
308
309 test_proptest!{posit_10_0_proptest, Posit<10, 0, i16>, Quire<10, 0, 128>}
310 test_proptest!{posit_10_1_proptest, Posit<10, 1, i16>, Quire<10, 1, 128>}
311 test_proptest!{posit_10_2_proptest, Posit<10, 2, i16>, Quire<10, 2, 128>}
312 test_proptest!{posit_10_3_proptest, Posit<10, 3, i16>, Quire<10, 3, 128>}
313 test_proptest!{posit_8_0_proptest, Posit<8, 0, i8>, Quire<8, 0, 128>}
314
315 test_proptest!{p8_proptest, crate::p8, crate::q8}
316 test_proptest!{p16_proptest, crate::p16, crate::q16}
317 test_proptest!{p32_proptest, crate::p32, crate::q32}
318 test_proptest!{p64_proptest, crate::p64, crate::q64}
319
320 test_proptest!{posit_3_0_proptest, Posit<3, 0, i8>, Quire<3, 0, 128>}
321 test_proptest!{posit_4_0_proptest, Posit<4, 0, i8>, Quire<4, 0, 128>}
322 test_proptest!{posit_4_1_proptest, Posit<4, 1, i8>, Quire<4, 1, 128>}
323 }
324
325 mod quire_quire {
327 use super::*;
328
329 #[test]
330 fn q32_overflow_positive() {
331 use crate::RoundFrom;
332 let mut quire = crate::q32::MAX;
333 assert!(!quire.is_nar());
334 quire += &crate::q32::from(crate::p32::round_from(1e-9));
335 assert!(quire.is_nar())
336 }
337
338 #[test]
339 fn q32_overflow_negative() {
340 use crate::RoundFrom;
341 let mut quire = crate::q32::MIN;
342 assert!(!quire.is_nar());
343 quire += &crate::q32::from(crate::p32::round_from(-1e-9));
344 assert!(quire.is_nar())
345 }
346
347 macro_rules! test_proptest {
348 ($name:ident, $quire:ty) => {
349 proptest!{
350 #![proptest_config(ProptestConfig::with_cases(crate::PROPTEST_CASES))]
351 #[test]
352 fn $name(
353 a in <$quire>::cases_proptest_all(),
354 b in <$quire>::cases_proptest_all(),
355 ) {
356 let mut sum = a.clone();
357 sum += &b;
358 match (Rational::try_from(a), Rational::try_from(b)) {
359 (Ok(a), Ok(b)) => assert!(super::rational::quire_is_correct_rounded(a + b, sum)),
360 _ => assert!(sum.is_nar()),
361 }
362 }
363 }
364 };
365 }
366
367 test_proptest!{posit_10_0_proptest, Quire<10, 0, 128>}
368 test_proptest!{posit_10_1_proptest, Quire<10, 1, 128>}
369 test_proptest!{posit_10_2_proptest, Quire<10, 2, 128>}
370 test_proptest!{posit_10_3_proptest, Quire<10, 3, 128>}
371 test_proptest!{posit_8_0_proptest, Quire<8, 0, 128>}
372
373 test_proptest!{p8_proptest, crate::q8}
374 test_proptest!{p16_proptest, crate::q16}
375 test_proptest!{p32_proptest, crate::q32}
376 test_proptest!{p64_proptest, crate::q64}
377
378 test_proptest!{posit_3_0_proptest, Quire<3, 0, 128>}
379 test_proptest!{posit_4_0_proptest, Quire<4, 0, 128>}
380 test_proptest!{posit_4_1_proptest, Quire<4, 1, 128>}
381 }
382
383 mod quire_posit_posit {
385 use super::*;
386
387 macro_rules! test_proptest {
388 ($name:ident, $posit:ty, $quire:ty) => {
389 proptest!{
390 #![proptest_config(ProptestConfig::with_cases(crate::PROPTEST_CASES))]
391 #[test]
392 fn $name(
393 q in <$quire>::cases_proptest_all(),
394 a in <$posit>::cases_proptest_all(),
395 b in <$posit>::cases_proptest_all(),
396 ) {
397 let mut result = q.clone();
398 result.add_prod(a, b);
399 match (Rational::try_from(q), Rational::try_from(a), Rational::try_from(b)) {
400 (Ok(q), Ok(a), Ok(b)) => assert!(super::rational::quire_is_correct_rounded(q + a * b, result)),
401 _ => assert!(result.is_nar()),
402 }
403 }
404 }
405 };
406 }
407
408 test_proptest!{posit_10_0_proptest, Posit<10, 0, i16>, Quire<10, 0, 128>}
409 test_proptest!{posit_10_1_proptest, Posit<10, 1, i16>, Quire<10, 1, 128>}
410 test_proptest!{posit_10_2_proptest, Posit<10, 2, i16>, Quire<10, 2, 128>}
411 test_proptest!{posit_10_3_proptest, Posit<10, 3, i16>, Quire<10, 3, 128>}
412 test_proptest!{posit_8_0_proptest, Posit<8, 0, i8>, Quire<8, 0, 128>}
413
414 test_proptest!{p8_proptest, crate::p8, crate::q8}
415 test_proptest!{p16_proptest, crate::p16, crate::q16}
416 test_proptest!{p32_proptest, crate::p32, crate::q32}
417 test_proptest!{posit_3_0_proptest, Posit<3, 0, i8>, Quire<3, 0, 128>}
420 test_proptest!{posit_4_0_proptest, Posit<4, 0, i8>, Quire<4, 0, 128>}
421 test_proptest!{posit_4_1_proptest, Posit<4, 1, i8>, Quire<4, 1, 128>}
422 }
423
424 mod quire_dot_product {
426 use super::*;
427
428 macro_rules! test_proptest {
429 ($name:ident, $posit:ty, $quire:ty) => {
430 proptest!{
431 #![proptest_config(ProptestConfig::with_cases(crate::PROPTEST_CASES / 50_000))]
432 #[test]
433 fn $name(
434 pairs in proptest::collection::vec(
435 (<$posit>::cases_proptest(), <$posit>::cases_proptest()),
436 50_000,
437 ),
438 ) {
439 let mut quire = <$quire>::ZERO;
440 let mut exact = Rational::from(0);
441 for (a, b) in pairs {
442 quire.add_prod(a, b);
443 exact += Rational::try_from(a).unwrap() * Rational::try_from(b).unwrap();
444 assert_eq!(Rational::try_from(quire.clone()), Ok(exact.clone()))
445 }
446 }
447 }
448 };
449 }
450
451 test_proptest!{posit_10_0_proptest, Posit<10, 0, i16>, Quire<10, 0, 128>}
452 test_proptest!{posit_10_1_proptest, Posit<10, 1, i16>, Quire<10, 1, 128>}
453 test_proptest!{posit_10_2_proptest, Posit<10, 2, i16>, Quire<10, 2, 128>}
454 test_proptest!{posit_10_3_proptest, Posit<10, 3, i16>, Quire<10, 3, 128>}
455 test_proptest!{posit_8_0_proptest, Posit<8, 0, i8>, Quire<8, 0, 128>}
456
457 test_proptest!{p8_proptest, crate::p8, crate::q8}
458 test_proptest!{p16_proptest, crate::p16, crate::q16}
459 test_proptest!{p32_proptest, crate::p32, crate::q32}
460 test_proptest!{posit_3_0_proptest, Posit<3, 0, i8>, Quire<3, 0, 128>}
463 test_proptest!{posit_4_0_proptest, Posit<4, 0, i8>, Quire<4, 0, 128>}
464 test_proptest!{posit_4_1_proptest, Posit<4, 1, i8>, Quire<4, 1, 128>}
465 }
466
467 mod quire_neg {
469 use super::*;
470
471 macro_rules! test_proptest {
472 ($name:ident, $posit:ty, $quire:ty) => {
473 proptest!{
474 #![proptest_config(ProptestConfig::with_cases(crate::PROPTEST_CASES))]
475 #[test]
476 fn $name(quire in <$quire>::cases_proptest_all()) {
477 use malachite::base::num::arithmetic::traits::Abs;
478 assert_eq!(
479 Rational::try_from(-quire.clone()),
480 Rational::try_from(quire.clone()).map(|x| -x),
481 );
482 assert_eq!(
483 Rational::try_from(quire.clone().abs()),
484 Rational::try_from(quire.clone()).map(|x| x.abs()),
485 );
486 }
487 }
488 };
489 }
490
491 test_proptest!{posit_10_0_proptest, Posit<10, 0, i16>, Quire<10, 0, 128>}
492 test_proptest!{posit_10_1_proptest, Posit<10, 1, i16>, Quire<10, 1, 128>}
493 test_proptest!{posit_10_2_proptest, Posit<10, 2, i16>, Quire<10, 2, 128>}
494 test_proptest!{posit_10_3_proptest, Posit<10, 3, i16>, Quire<10, 3, 128>}
495 test_proptest!{posit_8_0_proptest, Posit<8, 0, i8>, Quire<8, 0, 128>}
496
497 test_proptest!{p8_proptest, crate::p8, crate::q8}
498 test_proptest!{p16_proptest, crate::p16, crate::q16}
499 test_proptest!{p32_proptest, crate::p32, crate::q32}
500 test_proptest!{p64_proptest, crate::p64, crate::q64}
501
502 test_proptest!{posit_3_0_proptest, Posit<3, 0, i8>, Quire<3, 0, 128>}
503 test_proptest!{posit_4_0_proptest, Posit<4, 0, i8>, Quire<4, 0, 128>}
504 test_proptest!{posit_4_1_proptest, Posit<4, 1, i8>, Quire<4, 1, 128>}
505 }
506}