Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion arbi/src/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,17 +93,22 @@ impl Arbi {
if self.is_negative() {
if y_is_neg {
// x < 0, y < 0 ==> x = -|x|, y = -|y| ==> x - y = |y| - |x|
// y - x = -|y| - (-|x|) = |x| - |y|
self.dsub_abs_inplace(y, !from_other);
} else {
// x < 0, y >= 0 ==> x = -|x|, y = |y| ==> x - y = -(|x| + |y|)
// y - x = |y| + |x|
self.dadd_abs_inplace(y);
self.neg = true;
self.neg = !from_other;
}
} else if y_is_neg {
// x >= 0, y < 0 ==> x = |x|, y = -|y| ==> x - y = |x| + |y|
// y - x = -|y| - |x| = -(|y| + |x|)
self.dadd_abs_inplace(y);
self.neg = from_other;
} else {
// x >= 0, y >= 0 ==> x = |x|, y = |y| ==> x - y = |x| - |y|
// y - x = |y| - |x|
self.dsub_abs_inplace(y, from_other);
}
}
Expand Down
31 changes: 31 additions & 0 deletions arbi/src/builtin_int_methods/is_multiple_of.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
Copyright 2025 Owain Davies
SPDX-License-Identifier: Apache-2.0 OR MIT
*/

use crate::Arbi;

impl Arbi {
/// Returns `true` if `self` is an integer multiple of `rhs`, and `false`
/// otherwise.
///
/// If both `self` and `rhs` are zero, returns `true`. If `self` is nonzero
/// and `rhs` is zero, returns `false`. Otherwise, this function is
/// equivalent to `self % rhs == 0`.
///
/// # Examples
/// ```
/// use arbi::Arbi;
/// assert!(Arbi::from(8).is_multiple_of(&Arbi::from(4)));
/// assert!(!Arbi::from(7).is_multiple_of(&Arbi::from(4)));
/// assert!(Arbi::from(0).is_multiple_of(&Arbi::from(0)));
/// assert!(!Arbi::from(7).is_multiple_of(&Arbi::from(0)));
/// ```
pub fn is_multiple_of(&self, rhs: &Self) -> bool {
if rhs.is_zero() {
self.is_zero()
} else {
(self % rhs).is_zero()
}
}
}
2 changes: 2 additions & 0 deletions arbi/src/builtin_int_methods/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ mod from_bytes;
mod ilog;
mod ilog10;
mod ilog2;
mod is_multiple_of;
mod is_positive_is_negative;
mod is_power_of_two;
mod isqrt;
mod next_multiple_of;
mod reverse_bits;
mod signum;
mod swap_bytes;
Expand Down
80 changes: 80 additions & 0 deletions arbi/src/builtin_int_methods/next_multiple_of.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
Copyright 2025 Owain Davies
SPDX-License-Identifier: Apache-2.0 OR MIT
*/

use crate::{Arbi, Assign};

impl Arbi {
/// If `rhs` is positive, return the smallest value greater than or equal to
/// `self` that is a multiple of `rhs`. If `rhs` is negative, return the
/// largest value less than or equal to `self` that is a multiple of `rhs`.
///
/// # Panic
/// Panics if `rhs` is zero.
///
/// # Examples
/// ```
/// use arbi::Arbi;
/// assert_eq!(Arbi::from(12).next_multiple_of(&Arbi::from(6)), 12);
/// assert_eq!(Arbi::from(19).next_multiple_of(&Arbi::from(7)), 21);
/// assert_eq!(Arbi::from(25).next_multiple_of(&Arbi::from(-5)), 25);
/// assert_eq!(Arbi::from(25).next_multiple_of(&Arbi::from(-7)), 21);
/// assert_eq!(Arbi::from(-21).next_multiple_of(&Arbi::from(7)), -21);
/// assert_eq!(Arbi::from(-25).next_multiple_of(&Arbi::from(7)), -21);
/// assert_eq!(Arbi::from(-21).next_multiple_of(&Arbi::from(-7)), -21);
/// assert_eq!(Arbi::from(-25).next_multiple_of(&Arbi::from(-7)), -28);
/// ```
///
/// Panics if `rhs` is zero:
/// ```should_panic
/// use arbi::Arbi;
/// Arbi::from(123).next_multiple_of(&Arbi::zero());
/// ```
pub fn next_multiple_of(&self, rhs: &Self) -> Self {
let (_, mut r) = self.divrem_floor_ref(rhs);
if r.is_zero() {
r.assign(self);
r
} else {
(rhs - r) + self
}
}

/// If `rhs` is positive, return the largest value less than or equal to
/// `self` that is a multiple of `rhs`. If `rhs` is negative, return the
/// smallest value greater than or equal to `self` that is a multiple of
/// `rhs`.
///
/// # Panic
/// Panics if `rhs` is zero.
///
/// # Examples
/// ```
/// use arbi::Arbi;
/// assert_eq!(Arbi::from(12).prev_multiple_of(&Arbi::from(6)), 12);
/// assert_eq!(Arbi::from(19).prev_multiple_of(&Arbi::from(7)), 14);
/// assert_eq!(Arbi::from(25).prev_multiple_of(&Arbi::from(-5)), 25);
/// assert_eq!(Arbi::from(25).prev_multiple_of(&Arbi::from(-7)), 28);
/// assert_eq!(Arbi::from(-21).prev_multiple_of(&Arbi::from(7)), -21);
/// assert_eq!(Arbi::from(-25).prev_multiple_of(&Arbi::from(7)), -28);
/// assert_eq!(Arbi::from(-21).prev_multiple_of(&Arbi::from(-7)), -21);
/// assert_eq!(Arbi::from(-25).prev_multiple_of(&Arbi::from(-7)), -21);
/// ```
///
/// Panics if `rhs` is zero:
/// ```should_panic
/// use arbi::Arbi;
/// Arbi::from(123).prev_multiple_of(&Arbi::zero());
/// ```
pub fn prev_multiple_of(&self, rhs: &Self) -> Self {
let (_, mut r) = self.divrem_floor_ref(rhs);
if r.is_zero() {
// Potentially avoid memory allocation
r.assign(self);
r
} else {
self - r
}
}
}
Loading