Implement Div by amount for amount types

It is semantically valid to divide an amount by another amount. The
result of the operation is an integer.

Note that we cannot implement `Div` by `NumOpResult` because there is no
way to show the div by invalid case.

Implement `Div` by amount for both amount types.
This commit is contained in:
Tobin C. Harding 2025-03-03 08:00:14 +11:00
parent b57bfb9bc5
commit 0a9f14f7b0
No known key found for this signature in database
GPG Key ID: 40BF9E4C269D6607
2 changed files with 42 additions and 0 deletions

View File

@ -182,6 +182,11 @@ crate::internal_macros::impl_op_for_references! {
fn div(self, rhs: u64) -> Self::Output { self.and_then(|lhs| lhs / rhs) }
}
impl ops::Div<Amount> for Amount {
type Output = u64;
fn div(self, rhs: Amount) -> Self::Output { self.to_sat() / rhs.to_sat() }
}
impl ops::Rem<u64> for Amount {
type Output = NumOpResult<Amount>;
@ -252,6 +257,11 @@ crate::internal_macros::impl_op_for_references! {
fn div(self, rhs: i64) -> Self::Output { self.and_then(|lhs| lhs / rhs) }
}
impl ops::Div<SignedAmount> for SignedAmount {
type Output = i64;
fn div(self, rhs: SignedAmount) -> Self::Output { self.to_sat() / rhs.to_sat() }
}
impl ops::Rem<i64> for SignedAmount {
type Output = NumOpResult<SignedAmount>;

View File

@ -1282,6 +1282,38 @@ fn op_int_combos() {
assert_eq!(sres(1901) % 7, sres(4));
}
#[test]
fn unsigned_amount_div_by_amount() {
let sat = Amount::from_sat;
assert_eq!(sat(0) / sat(7), 0);
assert_eq!(sat(1897) / sat(7), 271);
}
#[test]
#[should_panic(expected = "attempt to divide by zero")]
fn unsigned_amount_div_by_amount_zero() {
let _ = Amount::from_sat(1897) / Amount::ZERO;
}
#[test]
fn signed_amount_div_by_amount() {
let ssat = SignedAmount::from_sat;
assert_eq!(ssat(0) / ssat(7), 0);
assert_eq!(ssat(1897) / ssat(7), 271);
assert_eq!(ssat(1897) / ssat(-7), -271);
assert_eq!(ssat(-1897) / ssat(7), -271);
assert_eq!(ssat(-1897) / ssat(-7), 271);
}
#[test]
#[should_panic(expected = "attempt to divide by zero")]
fn signed_amount_div_by_amount_zero() {
let _ = SignedAmount::from_sat(1897) / SignedAmount::ZERO;
}
#[test]
fn check_const() {
assert_eq!(SignedAmount::ONE_BTC.to_sat(), 100_000_000);