1use core::num::{NonZeroI64, NonZeroU64};
6use core::ops;
7
8use NumOpResult as R;
9
10use super::{Amount, SignedAmount};
11use crate::internal_macros::{
12 impl_add_assign_for_results, impl_div_assign, impl_mul_assign, impl_rem_assign,
13 impl_sub_assign_for_results,
14};
15use crate::result::{MathErrorKind, MathOp, NumOpResult, OptionExt};
16
17impl From<Amount> for NumOpResult<Amount> {
18 #[inline]
19 fn from(a: Amount) -> Self { Self::Valid(a) }
20}
21impl From<&Amount> for NumOpResult<Amount> {
22 #[inline]
23 fn from(a: &Amount) -> Self { Self::Valid(*a) }
24}
25
26impl From<SignedAmount> for NumOpResult<SignedAmount> {
27 #[inline]
28 fn from(a: SignedAmount) -> Self { Self::Valid(a) }
29}
30impl From<&SignedAmount> for NumOpResult<SignedAmount> {
31 #[inline]
32 fn from(a: &SignedAmount) -> Self { Self::Valid(*a) }
33}
34
35crate::internal_macros::impl_op_for_references! {
36 impl ops::Add<Amount> for Amount {
37 type Output = NumOpResult<Amount>;
38
39 fn add(self, rhs: Amount) -> Self::Output { self.checked_add(rhs).valid_or_error(MathErrorKind::Overflow { op: MathOp::Add, is_negative: false }) }
40 }
41 impl ops::Add<NumOpResult<Amount>> for Amount {
42 type Output = NumOpResult<Amount>;
43
44 fn add(self, rhs: NumOpResult<Amount>) -> Self::Output { rhs.and_then(|a| a + self) }
45 }
46
47 impl ops::Sub<Amount> for Amount {
48 type Output = NumOpResult<Amount>;
49
50 fn sub(self, rhs: Amount) -> Self::Output { self.checked_sub(rhs).valid_or_error(MathErrorKind::Overflow { op: MathOp::Sub, is_negative: true }) }
51 }
52 impl ops::Sub<NumOpResult<Amount>> for Amount {
53 type Output = NumOpResult<Amount>;
54
55 fn sub(self, rhs: NumOpResult<Amount>) -> Self::Output {
56 match rhs {
57 R::Valid(amount) => self - amount,
58 R::Error(_) => rhs,
59 }
60 }
61 }
62
63 impl ops::Mul<u64> for Amount {
64 type Output = NumOpResult<Amount>;
65
66 fn mul(self, rhs: u64) -> Self::Output { self.checked_mul(rhs).valid_or_error(MathErrorKind::Overflow { op: MathOp::Mul, is_negative: false }) }
67 }
68 impl ops::Mul<u64> for NumOpResult<Amount> {
69 type Output = NumOpResult<Amount>;
70
71 fn mul(self, rhs: u64) -> Self::Output { self.and_then(|lhs| lhs * rhs) }
72 }
73 impl ops::Mul<Amount> for u64 {
74 type Output = NumOpResult<Amount>;
75
76 fn mul(self, rhs: Amount) -> Self::Output { rhs.checked_mul(self).valid_or_error(MathErrorKind::Overflow { op: MathOp::Mul, is_negative: false }) }
77 }
78 impl ops::Mul<NumOpResult<Amount>> for u64 {
79 type Output = NumOpResult<Amount>;
80
81 fn mul(self, rhs: NumOpResult<Amount>) -> Self::Output { rhs.and_then(|rhs| self * rhs) }
82 }
83
84 impl ops::Div<u64> for Amount {
85 type Output = NumOpResult<Amount>;
86
87 fn div(self, rhs: u64) -> Self::Output { self.checked_div(rhs).valid_or_error(MathErrorKind::DivByZero) }
88 }
89 impl ops::Div<u64> for NumOpResult<Amount> {
90 type Output = NumOpResult<Amount>;
91
92 fn div(self, rhs: u64) -> Self::Output { self.and_then(|lhs| lhs / rhs) }
93 }
94 impl ops::Div<Amount> for Amount {
95 type Output = NumOpResult<u64>;
96
97 fn div(self, rhs: Amount) -> Self::Output {
98 self.to_sat().checked_div(rhs.to_sat()).valid_or_error(MathErrorKind::DivByZero)
99 }
100 }
101 impl ops::Div<NonZeroU64> for Amount {
102 type Output = Amount;
103
104 fn div(self, rhs: NonZeroU64) -> Self::Output { Self::from_sat(self.to_sat() / rhs).expect("construction after division cannot fail") }
105 }
106 impl ops::Div<NonZeroU64> for NumOpResult<Amount> {
107 type Output = NumOpResult<Amount>;
108
109 fn div(self, rhs: NonZeroU64) -> Self::Output { self.map(|lhs| lhs / rhs) }
110 }
111 impl ops::Rem<u64> for Amount {
112 type Output = NumOpResult<Amount>;
113
114 fn rem(self, modulus: u64) -> Self::Output { self.checked_rem(modulus).valid_or_error(MathErrorKind::RemByZero) }
115 }
116 impl ops::Rem<NonZeroU64> for Amount {
117 type Output = Amount;
118
119 fn rem(self, modulus: NonZeroU64) -> Self::Output { Self::from_sat(self.to_sat() % modulus).expect("construction from remainder cannot fail") }
120 }
121 impl ops::Rem<u64> for NumOpResult<Amount> {
122 type Output = NumOpResult<Amount>;
123
124 fn rem(self, modulus: u64) -> Self::Output { self.and_then(|lhs| lhs % modulus) }
125 }
126 impl ops::Rem<NonZeroU64> for NumOpResult<Amount> {
127 type Output = NumOpResult<Amount>;
128
129 fn rem(self, modulus: NonZeroU64) -> Self::Output { self.map(|lhs| lhs % modulus) }
130 }
131
132 impl ops::Add<SignedAmount> for SignedAmount {
133 type Output = NumOpResult<SignedAmount>;
134
135 fn add(self, rhs: SignedAmount) -> Self::Output {
136 let kind = MathErrorKind::Overflow { op: MathOp::Add, is_negative: rhs.is_negative() };
137 self.checked_add(rhs).valid_or_error(kind)
138 }
139 }
140 impl ops::Add<NumOpResult<SignedAmount>> for SignedAmount {
141 type Output = NumOpResult<SignedAmount>;
142
143 fn add(self, rhs: NumOpResult<SignedAmount>) -> Self::Output { rhs.and_then(|a| a + self) }
144 }
145
146 impl ops::Sub<SignedAmount> for SignedAmount {
147 type Output = NumOpResult<SignedAmount>;
148
149 fn sub(self, rhs: SignedAmount) -> Self::Output {
150 let kind = MathErrorKind::Overflow { op: MathOp::Sub, is_negative: !rhs.is_negative() };
151 self.checked_sub(rhs).valid_or_error(kind)
152 }
153 }
154 impl ops::Sub<NumOpResult<SignedAmount>> for SignedAmount {
155 type Output = NumOpResult<SignedAmount>;
156
157 fn sub(self, rhs: NumOpResult<SignedAmount>) -> Self::Output {
158 match rhs {
159 R::Valid(amount) => self - amount,
160 R::Error(_) => rhs,
161 }
162 }
163 }
164
165 impl ops::Mul<i64> for SignedAmount {
166 type Output = NumOpResult<SignedAmount>;
167
168 fn mul(self, rhs: i64) -> Self::Output {
169 let is_negative = self.is_negative() != rhs.is_negative();
170 self.checked_mul(rhs).valid_or_error(MathErrorKind::Overflow { op: MathOp::Mul, is_negative })
171 }
172 }
173 impl ops::Mul<i64> for NumOpResult<SignedAmount> {
174 type Output = NumOpResult<SignedAmount>;
175
176 fn mul(self, rhs: i64) -> Self::Output { self.and_then(|lhs| lhs * rhs) }
177 }
178 impl ops::Mul<SignedAmount> for i64 {
179 type Output = NumOpResult<SignedAmount>;
180
181 fn mul(self, rhs: SignedAmount) -> Self::Output {
182 let is_negative = self.is_negative() != rhs.is_negative();
183 rhs.checked_mul(self).valid_or_error(MathErrorKind::Overflow { op: MathOp::Mul, is_negative })
184 }
185 }
186 impl ops::Mul<NumOpResult<SignedAmount>> for i64 {
187 type Output = NumOpResult<SignedAmount>;
188
189 fn mul(self, rhs: NumOpResult<SignedAmount>) -> Self::Output { rhs.and_then(|rhs| self * rhs) }
190 }
191
192 impl ops::Div<i64> for SignedAmount {
193 type Output = NumOpResult<SignedAmount>;
194
195 fn div(self, rhs: i64) -> Self::Output { self.checked_div(rhs).valid_or_error(MathErrorKind::DivByZero) }
196 }
197 impl ops::Div<i64> for NumOpResult<SignedAmount> {
198 type Output = NumOpResult<SignedAmount>;
199
200 fn div(self, rhs: i64) -> Self::Output { self.and_then(|lhs| lhs / rhs) }
201 }
202 impl ops::Div<SignedAmount> for SignedAmount {
203 type Output = NumOpResult<i64>;
204
205 fn div(self, rhs: SignedAmount) -> Self::Output {
206 self.to_sat().checked_div(rhs.to_sat()).valid_or_error(MathErrorKind::DivByZero)
207 }
208 }
209 impl ops::Div<NonZeroI64> for SignedAmount {
210 type Output = SignedAmount;
211
212 fn div(self, rhs: NonZeroI64) -> Self::Output { Self::from_sat(self.to_sat() / rhs.get()).expect("construction after division cannot fail") }
213 }
214 impl ops::Div<NonZeroI64> for NumOpResult<SignedAmount> {
215 type Output = NumOpResult<SignedAmount>;
216
217 fn div(self, rhs: NonZeroI64) -> Self::Output { self.map(|lhs| lhs / rhs) }
218 }
219 impl ops::Rem<i64> for SignedAmount {
220 type Output = NumOpResult<SignedAmount>;
221
222 fn rem(self, modulus: i64) -> Self::Output { self.checked_rem(modulus).valid_or_error(MathErrorKind::RemByZero) }
223 }
224 impl ops::Rem<NonZeroI64> for SignedAmount {
225 type Output = SignedAmount;
226
227 fn rem(self, modulus: NonZeroI64) -> Self::Output { SignedAmount::from_sat(self.to_sat() % modulus.get()).expect("construction from remainder cannot fail") }
228 }
229 impl ops::Rem<i64> for NumOpResult<SignedAmount> {
230 type Output = NumOpResult<SignedAmount>;
231
232 fn rem(self, modulus: i64) -> Self::Output { self.and_then(|lhs| lhs % modulus) }
233 }
234 impl ops::Rem<NonZeroI64> for NumOpResult<SignedAmount> {
235 type Output = NumOpResult<SignedAmount>;
236
237 fn rem(self, modulus: NonZeroI64) -> Self::Output { self.map(|lhs| lhs % modulus) }
238 }
239}
240
241impl_mul_assign!(NumOpResult<Amount>, u64);
242impl_mul_assign!(NumOpResult<SignedAmount>, i64);
243impl_div_assign!(NumOpResult<Amount>, u64);
244impl_div_assign!(NumOpResult<SignedAmount>, i64);
245impl_div_assign!(Amount, NonZeroU64);
246impl_div_assign!(SignedAmount, NonZeroI64);
247impl_div_assign!(NumOpResult<Amount>, NonZeroU64);
248impl_div_assign!(NumOpResult<SignedAmount>, NonZeroI64);
249impl_rem_assign!(NumOpResult<Amount>, u64);
250impl_rem_assign!(NumOpResult<SignedAmount>, i64);
251impl_rem_assign!(Amount, NonZeroU64);
252impl_rem_assign!(SignedAmount, NonZeroI64);
253impl_rem_assign!(NumOpResult<Amount>, NonZeroU64);
254impl_rem_assign!(NumOpResult<SignedAmount>, NonZeroI64);
255
256impl_add_assign_for_results!(Amount);
257impl_add_assign_for_results!(SignedAmount);
258impl_sub_assign_for_results!(Amount);
259impl_sub_assign_for_results!(SignedAmount);
260
261impl ops::Neg for Amount {
262 type Output = SignedAmount;
263
264 #[inline]
265 fn neg(self) -> Self::Output { self.to_signed().neg() }
266}
267
268impl ops::Neg for SignedAmount {
269 type Output = Self;
270
271 #[inline]
272 fn neg(self) -> Self::Output {
273 Self::from_sat(self.to_sat().neg()).expect("all +ve and -ve values are valid")
274 }
275}
276
277impl ops::Neg for NumOpResult<Amount> {
278 type Output = NumOpResult<SignedAmount>;
279
280 #[inline]
281 fn neg(self) -> Self::Output { self.map(ops::Neg::neg) }
282}
283
284impl ops::Neg for NumOpResult<SignedAmount> {
285 type Output = Self;
286
287 #[inline]
288 fn neg(self) -> Self::Output { self.map(ops::Neg::neg) }
289}
290
291impl core::iter::Sum<Amount> for NumOpResult<Amount> {
293 fn sum<I>(mut iter: I) -> Self
294 where
295 I: Iterator<Item = Amount>,
296 {
297 let result = iter.try_fold(Amount::ZERO, |acc, amount| (acc + amount).into_result());
298 Self::from_result(result)
299 }
300}
301
302impl<'a> core::iter::Sum<&'a Amount> for NumOpResult<Amount> {
304 fn sum<I>(mut iter: I) -> Self
305 where
306 I: Iterator<Item = &'a Amount>,
307 {
308 let result = iter.try_fold(Amount::ZERO, |acc, amount| (acc + amount).into_result());
309 Self::from_result(result)
310 }
311}
312
313impl core::iter::Sum<Self> for NumOpResult<Amount> {
315 fn sum<I>(mut iter: I) -> Self
316 where
317 I: Iterator<Item = Self>,
318 {
319 let result =
320 iter.try_fold(Amount::ZERO, |acc, amount| (acc + amount.into_result()?).into_result());
321 Self::from_result(result)
322 }
323}
324impl<'a> core::iter::Sum<&'a Self> for NumOpResult<Amount> {
326 fn sum<I>(mut iter: I) -> Self
327 where
328 I: Iterator<Item = &'a Self>,
329 {
330 let result =
331 iter.try_fold(Amount::ZERO, |acc, amount| (acc + amount.into_result()?).into_result());
332 Self::from_result(result)
333 }
334}
335
336impl core::iter::Sum<SignedAmount> for NumOpResult<SignedAmount> {
338 fn sum<I>(mut iter: I) -> Self
339 where
340 I: Iterator<Item = SignedAmount>,
341 {
342 let result = iter.try_fold(SignedAmount::ZERO, |acc, amount| (acc + amount).into_result());
343 Self::from_result(result)
344 }
345}
346
347impl<'a> core::iter::Sum<&'a SignedAmount> for NumOpResult<SignedAmount> {
349 fn sum<I>(mut iter: I) -> Self
350 where
351 I: Iterator<Item = &'a SignedAmount>,
352 {
353 let result = iter.try_fold(SignedAmount::ZERO, |acc, amount| (acc + amount).into_result());
354 Self::from_result(result)
355 }
356}
357
358impl core::iter::Sum<Self> for NumOpResult<SignedAmount> {
360 fn sum<I>(mut iter: I) -> Self
361 where
362 I: Iterator<Item = Self>,
363 {
364 let result = iter.try_fold(SignedAmount::ZERO, |acc, amount| {
365 (acc + amount.into_result()?).into_result()
366 });
367 Self::from_result(result)
368 }
369}
370
371impl<'a> core::iter::Sum<&'a Self> for NumOpResult<SignedAmount> {
373 fn sum<I>(mut iter: I) -> Self
374 where
375 I: Iterator<Item = &'a Self>,
376 {
377 let result = iter.try_fold(SignedAmount::ZERO, |acc, amount| {
378 (acc + amount.into_result()?).into_result()
379 });
380 Self::from_result(result)
381 }
382}
383#[cfg(test)]
384mod tests {
385 use super::*;
386 use crate::result::NumOpError;
387
388 #[test]
389 fn sum_amounts() {
390 let amounts =
391 [Amount::from_sat_u32(100), Amount::from_sat_u32(200), Amount::from_sat_u32(300)];
392
393 let sum: NumOpResult<Amount> = amounts.into_iter().sum();
394 assert_eq!(sum, NumOpResult::Valid(Amount::from_sat_u32(600)));
395 }
396
397 #[test]
398 fn sum_amounts_with_references() {
399 let amounts =
400 [Amount::from_sat_u32(100), Amount::from_sat_u32(200), Amount::from_sat_u32(300)];
401
402 let sum: NumOpResult<Amount> = amounts.iter().sum();
403 assert_eq!(sum, NumOpResult::Valid(Amount::from_sat_u32(600)));
404 }
405
406 #[test]
407 fn sum_preserves_division_by_zero_error() {
408 let err = [Amount::ONE_SAT / 0_u64];
409 let sum: NumOpResult<Amount> = err.into_iter().sum();
410 assert!(sum.unwrap_err().operation().is_division());
411 let sum: NumOpResult<Amount> = err.iter().sum();
412 assert!(sum.unwrap_err().operation().is_division());
413
414 let err = [SignedAmount::ONE_SAT / 0_i64];
415 let sum: NumOpResult<SignedAmount> = err.into_iter().sum();
416 assert!(sum.unwrap_err().operation().is_division());
417 let sum: NumOpResult<SignedAmount> = err.iter().sum();
418 assert!(sum.unwrap_err().operation().is_division());
419 }
420
421 #[test]
422 fn sum_amount_results() {
423 let amounts = [
424 NumOpResult::Valid(Amount::from_sat_u32(100)),
425 NumOpResult::Valid(Amount::from_sat_u32(200)),
426 NumOpResult::Valid(Amount::from_sat_u32(300)),
427 ];
428
429 let sum: NumOpResult<Amount> = amounts.into_iter().sum();
430 assert_eq!(sum, NumOpResult::Valid(Amount::from_sat_u32(600)));
431 }
432
433 #[test]
434 fn sum_amount_results_with_references() {
435 let amounts = [
436 NumOpResult::Valid(Amount::from_sat_u32(100)),
437 NumOpResult::Valid(Amount::from_sat_u32(200)),
438 NumOpResult::Valid(Amount::from_sat_u32(300)),
439 ];
440
441 let sum: NumOpResult<Amount> = amounts.iter().sum();
442 assert_eq!(sum, NumOpResult::Valid(Amount::from_sat_u32(600)));
443 }
444
445 #[test]
446 fn sum_amount_with_error_propagation() {
447 let amounts = [
448 NumOpResult::Valid(Amount::from_sat_u32(100)),
449 NumOpResult::Error(NumOpError::while_doing(MathErrorKind::Overflow {
450 op: MathOp::Add,
451 is_negative: false,
452 })),
453 NumOpResult::Valid(Amount::from_sat_u32(200)),
454 ];
455
456 let sum: NumOpResult<Amount> = amounts.into_iter().sum();
457 assert!(matches!(sum, NumOpResult::Error(_)));
458 }
459
460 #[test]
461 fn sum_signed_amounts() {
462 let amounts = [
463 SignedAmount::from_sat_i32(100),
464 SignedAmount::from_sat_i32(-50),
465 SignedAmount::from_sat_i32(200),
466 ];
467
468 let sum: NumOpResult<SignedAmount> = amounts.into_iter().sum();
469 assert_eq!(sum, NumOpResult::Valid(SignedAmount::from_sat_i32(250)));
470 }
471
472 #[test]
473 fn sum_signed_amounts_with_references() {
474 let amounts = [
475 SignedAmount::from_sat_i32(100),
476 SignedAmount::from_sat_i32(-50),
477 SignedAmount::from_sat_i32(200),
478 ];
479
480 let sum: NumOpResult<SignedAmount> = amounts.iter().sum();
481 assert_eq!(sum, NumOpResult::Valid(SignedAmount::from_sat_i32(250)));
482 }
483
484 #[test]
485 fn sum_signed_amount_results() {
486 let amounts = [
487 NumOpResult::Valid(SignedAmount::from_sat_i32(100)),
488 NumOpResult::Valid(SignedAmount::from_sat_i32(-50)),
489 NumOpResult::Valid(SignedAmount::from_sat_i32(200)),
490 ];
491
492 let sum: NumOpResult<SignedAmount> = amounts.into_iter().sum();
493 assert_eq!(sum, NumOpResult::Valid(SignedAmount::from_sat_i32(250)));
494 }
495
496 #[test]
497 fn sum_signed_amount_results_with_references() {
498 let amounts = [
499 NumOpResult::Valid(SignedAmount::from_sat_i32(100)),
500 NumOpResult::Valid(SignedAmount::from_sat_i32(-50)),
501 NumOpResult::Valid(SignedAmount::from_sat_i32(200)),
502 ];
503
504 let sum: NumOpResult<SignedAmount> = amounts.iter().sum();
505 assert_eq!(sum, NumOpResult::Valid(SignedAmount::from_sat_i32(250)));
506 }
507
508 #[test]
509 fn sum_signed_amount_with_error_propagation() {
510 let amounts = [
511 NumOpResult::Valid(SignedAmount::from_sat_i32(100)),
512 NumOpResult::Error(NumOpError::while_doing(MathErrorKind::Overflow {
513 op: MathOp::Add,
514 is_negative: false,
515 })),
516 NumOpResult::Valid(SignedAmount::from_sat_i32(200)),
517 ];
518
519 let sum: NumOpResult<SignedAmount> = amounts.into_iter().sum();
520 assert!(matches!(sum, NumOpResult::Error(_)));
521 }
522
523 #[test]
524 fn op_assign_amount() {
525 let sat = Amount::from_sat_u32(50);
526
527 let mut res = sat + sat;
528 res += Amount::from_sat_u32(50);
529 assert_eq!(res, NumOpResult::Valid(Amount::from_sat_u32(150)));
530
531 let add_err = NumOpResult::Error(NumOpError::while_doing(MathErrorKind::Overflow {
532 op: MathOp::Add,
533 is_negative: false,
534 }));
535 res += add_err; assert_eq!(res, add_err);
537
538 let mut res = sat + sat;
539 res -= Amount::from_sat_u32(20);
540 assert_eq!(res, NumOpResult::Valid(Amount::from_sat_u32(80)));
541
542 let sub_err = NumOpResult::Error(NumOpError::while_doing(MathErrorKind::Overflow {
543 op: MathOp::Sub,
544 is_negative: true,
545 }));
546 res -= sub_err; assert_eq!(res, sub_err);
548 }
549
550 #[test]
551 fn op_assign_signed_amount() {
552 let ssat = SignedAmount::from_sat_i32(50);
553
554 let mut res = ssat + ssat;
555 res += SignedAmount::from_sat_i32(-30);
556 assert_eq!(res, NumOpResult::Valid(SignedAmount::from_sat_i32(70)));
557
558 let add_err = NumOpResult::Error(NumOpError::while_doing(MathErrorKind::Overflow {
559 op: MathOp::Add,
560 is_negative: false,
561 }));
562 res += add_err; assert_eq!(res, add_err);
564
565 let mut res = ssat + ssat;
566 res -= SignedAmount::from_sat_i32(25);
567 assert_eq!(res, NumOpResult::Valid(SignedAmount::from_sat_i32(75)));
568
569 let sub_err = NumOpResult::Error(NumOpError::while_doing(MathErrorKind::Overflow {
570 op: MathOp::Sub,
571 is_negative: true,
572 }));
573 res -= sub_err; assert_eq!(res, sub_err);
575 }
576
577 #[test]
578 fn rem_assign_amount() {
579 let sat = Amount::from_sat_u32(50);
580 let mut res = sat + sat;
581 res %= 30_u64;
582 assert_eq!(res, NumOpResult::Valid(Amount::from_sat_u32(10)));
583
584 res %= &4_u64;
585 assert_eq!(res, NumOpResult::Valid(Amount::from_sat_u32(2)));
586
587 res %= 0_u64;
588 assert_eq!(res, NumOpResult::Error(NumOpError::while_doing(MathErrorKind::RemByZero)));
589
590 res %= 5_u64;
591 assert_eq!(res, NumOpResult::Error(NumOpError::while_doing(MathErrorKind::RemByZero)));
592 }
593
594 #[test]
595 fn rem_assign_nz_amount() {
596 fn nz(x: u64) -> NonZeroU64 { NonZeroU64::new(x).unwrap() }
597
598 let mut res = Amount::from_sat_u32(100);
599 res %= nz(30_u64);
600 assert_eq!(res, Amount::from_sat_u32(10));
601
602 res %= &nz(4_u64);
603 assert_eq!(res, Amount::from_sat_u32(2));
604
605 res %= nz(5_u64);
606 assert_eq!(res, Amount::from_sat_u32(2));
607 }
608
609 #[test]
610 fn rem_assign_signed_amount() {
611 let ssat = SignedAmount::from_sat_i32(-50);
612
613 let mut res = ssat + ssat;
614 res %= 30_i64;
615 assert_eq!(res, NumOpResult::Valid(SignedAmount::from_sat_i32(-10)));
616
617 res %= &4_i64;
618 assert_eq!(res, NumOpResult::Valid(SignedAmount::from_sat_i32(-2)));
619
620 res %= 0_i64;
621 assert_eq!(res, NumOpResult::Error(NumOpError::while_doing(MathErrorKind::RemByZero)));
622
623 res %= 5_i64;
624 assert_eq!(res, NumOpResult::Error(NumOpError::while_doing(MathErrorKind::RemByZero)));
625 }
626
627 #[test]
628 fn rem_assign_nz_signed_amount() {
629 fn nz(x: i64) -> NonZeroI64 { NonZeroI64::new(x).unwrap() }
630
631 let mut res = SignedAmount::from_sat_i32(-100);
632 res %= nz(30_i64);
633 assert_eq!(res, SignedAmount::from_sat_i32(-10));
634
635 res %= &nz(4_i64);
636 assert_eq!(res, SignedAmount::from_sat_i32(-2));
637
638 res %= nz(5_i64);
639 assert_eq!(res, SignedAmount::from_sat_i32(-2));
640 }
641
642 #[test]
643 fn div_assign_amount_nonzero() {
644 let mut amount = Amount::from_sat_u32(100);
645 amount /= NonZeroU64::new(12).unwrap();
646 assert_eq!(amount, Amount::from_sat_u32(8));
647
648 amount /= NonZeroU64::new(10).unwrap();
650 assert_eq!(amount, Amount::ZERO);
651
652 let mut res = amount + Amount::from_sat_u32(100);
653 res /= NonZeroU64::new(4).unwrap();
654 assert_eq!(res, NumOpResult::Valid(Amount::from_sat_u32(25)));
655
656 let mut res: NumOpResult<Amount> =
658 NumOpResult::Error(NumOpError::while_doing(MathErrorKind::Overflow {
659 op: MathOp::Add,
660 is_negative: false,
661 }));
662 res /= NonZeroU64::new(2).unwrap();
663 assert_eq!(
664 res,
665 NumOpResult::Error(NumOpError::while_doing(MathErrorKind::Overflow {
666 op: MathOp::Add,
667 is_negative: false
668 }))
669 );
670 }
671
672 #[test]
673 fn div_assign_signed_amount_nonzero() {
674 let mut ssat = SignedAmount::from_sat_i32(-100);
675 ssat /= NonZeroI64::new(4).unwrap();
676 assert_eq!(ssat, SignedAmount::from_sat_i32(-25));
677
678 ssat /= &NonZeroI64::new(-5).unwrap();
679 assert_eq!(ssat, SignedAmount::from_sat_i32(5));
680
681 ssat /= NonZeroI64::new(-10).unwrap();
683 assert_eq!(ssat, SignedAmount::ZERO);
684
685 let mut res = ssat - SignedAmount::from_sat_i32(100);
686 res /= NonZeroI64::new(4).unwrap();
687 assert_eq!(res, NumOpResult::Valid(SignedAmount::from_sat_i32(-25)));
688
689 let mut res: NumOpResult<SignedAmount> =
690 NumOpResult::Error(NumOpError::while_doing(MathErrorKind::Overflow {
691 op: MathOp::Sub,
692 is_negative: true,
693 }));
694 res /= NonZeroI64::new(2).unwrap();
695 assert_eq!(
696 res,
697 NumOpResult::Error(NumOpError::while_doing(MathErrorKind::Overflow {
698 op: MathOp::Sub,
699 is_negative: true
700 }))
701 );
702 }
703
704 #[test]
705 fn op_assign_amount_error() {
706 let mut res: NumOpResult<Amount> =
707 NumOpResult::Error(NumOpError::while_doing(MathErrorKind::Overflow {
708 op: MathOp::Mul,
709 is_negative: false,
710 }));
711 let orig_res = res;
712
713 res += Amount::from_sat_u32(10);
715 assert_eq!(res, orig_res);
716
717 res += NumOpResult::Error(NumOpError::while_doing(MathErrorKind::Overflow {
718 op: MathOp::Sub,
719 is_negative: true,
720 }));
721 assert_eq!(res, orig_res);
722
723 res -= Amount::from_sat_u32(10);
724 assert_eq!(res, orig_res);
725
726 res -= NumOpResult::Error(NumOpError::while_doing(MathErrorKind::Overflow {
727 op: MathOp::Add,
728 is_negative: false,
729 }));
730 assert_eq!(res, orig_res);
731 }
732}