From 08aa3ee0d397d412186e1e03559ec9d5e3004cda Mon Sep 17 00:00:00 2001 From: M Farkas-Dyck Date: Wed, 12 Dec 2018 10:56:57 -0800 Subject: [PATCH 01/10] Define ceiled division, rounding to nearest multiple --- src/lib.rs | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 41e0139..e87c03d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -73,6 +73,24 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// ~~~ fn mod_floor(&self, other: &Self) -> Self; + /// Ceiled integer division. + /// + /// # Examples + /// + /// ~~~ + /// # use num_integer::Integer; + /// assert_eq!(( 8).div_ceil( &3), 3); + /// assert_eq!(( 8).div_ceil(&-3), -2); + /// assert_eq!((-8).div_ceil( &3), -2); + /// assert_eq!((-8).div_ceil(&-3), 3); + /// + /// assert_eq!(( 1).div_ceil( &2), 1); + /// assert_eq!(( 1).div_ceil(&-2), 0); + /// assert_eq!((-1).div_ceil( &2), 0); + /// assert_eq!((-1).div_ceil(&-2), 1); + /// ~~~ + fn div_ceil(&self, other: &Self) -> Self; + /// Greatest Common Divisor (GCD). /// /// # Examples @@ -171,6 +189,32 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { fn div_mod_floor(&self, other: &Self) -> (Self, Self) { (self.div_floor(other), self.mod_floor(other)) } + + /// Rounds up to nearest multiple of argument. + /// + /// # Examples + /// + /// ~~~ + /// # use num_integer::Integer; + /// assert_eq!(16.round_up_to(&8), 16); + /// assert_eq!(23.round_up_to(&8), 24); + /// ~~~ + fn round_up_to(&self, other: &Self) -> Self where Self: traits::NumRef { + self.div_ceil(other).mul(other) + } + + /// Rounds down to nearest multiple of argument. + /// + /// # Examples + /// + /// ~~~ + /// # use num_integer::Integer; + /// assert_eq!(16.round_down_to(&8), 16); + /// assert_eq!(23.round_down_to(&8), 16); + /// ~~~ + fn round_down_to(&self, other: &Self) -> Self where Self: traits::NumRef { + self.div_floor(other).mul(other) + } } /// Simultaneous integer division and modulus @@ -193,6 +237,11 @@ pub fn mod_floor(x: T, y: T) -> T { pub fn div_mod_floor(x: T, y: T) -> (T, T) { x.div_mod_floor(&y) } +/// Ceiled integer division +#[inline] +pub fn div_ceil(x: T, y: T) -> T { + x.div_ceil(&y) +} /// Calculates the Greatest Common Divisor (GCD) of the number and `other`. The /// result is always positive. @@ -245,6 +294,15 @@ macro_rules! impl_integer_for_isize { } } + #[inline] + fn div_ceil(&self, other: &Self) -> Self { + match self.div_rem(other) { + (d, r) if (r > 0 && *other > 0) + || (r < 0 && *other < 0) => d + 1, + (d, _) => d, + } + } + /// Calculates the Greatest Common Divisor (GCD) of the number and /// `other`. The result is always positive. #[inline] @@ -527,6 +585,11 @@ macro_rules! impl_integer_for_usize { *self % *other } + #[inline] + fn div_ceil(&self, other: &Self) -> Self { + *self / *other + (0 != *self % *other) as Self + } + /// Calculates the Greatest Common Divisor (GCD) of the number and `other` #[inline] fn gcd(&self, other: &Self) -> Self { From 79f06f30a1daef8132800276c52a5944f84eae75 Mon Sep 17 00:00:00 2001 From: M Farkas-Dyck Date: Wed, 12 Dec 2018 11:01:35 -0800 Subject: [PATCH 02/10] inline --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index e87c03d..c21e211 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -199,6 +199,7 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// assert_eq!(16.round_up_to(&8), 16); /// assert_eq!(23.round_up_to(&8), 24); /// ~~~ + #[inline] fn round_up_to(&self, other: &Self) -> Self where Self: traits::NumRef { self.div_ceil(other).mul(other) } @@ -212,6 +213,7 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// assert_eq!(16.round_down_to(&8), 16); /// assert_eq!(23.round_down_to(&8), 16); /// ~~~ + #[inline] fn round_down_to(&self, other: &Self) -> Self where Self: traits::NumRef { self.div_floor(other).mul(other) } From bf04b1dc2fbff094d48cd340bfad0d9686f13da3 Mon Sep 17 00:00:00 2001 From: M Farkas-Dyck Date: Mon, 17 Dec 2018 15:18:38 -0800 Subject: [PATCH 03/10] define default `div_ceil` --- src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index c21e211..e2f972c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -89,7 +89,10 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// assert_eq!((-1).div_ceil( &2), 0); /// assert_eq!((-1).div_ceil(&-2), 1); /// ~~~ - fn div_ceil(&self, other: &Self) -> Self; + fn div_ceil(&self, other: &Self) -> Self { + let (q, r) = self.div_mod_floor(other); + if r.is_zero() { q } else { q+Self::one() } + } /// Greatest Common Divisor (GCD). /// From 4bb8818c9157c944091c5bbd8427bd6ee3498076 Mon Sep 17 00:00:00 2001 From: M Farkas-Dyck Date: Mon, 17 Dec 2018 15:30:41 -0800 Subject: [PATCH 04/10] rename `round_{up,down}_to` --- src/lib.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e2f972c..c577a95 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -199,11 +199,11 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// /// ~~~ /// # use num_integer::Integer; - /// assert_eq!(16.round_up_to(&8), 16); - /// assert_eq!(23.round_up_to(&8), 24); + /// assert_eq!(16.next_multiple_of(&8), 16); + /// assert_eq!(23.next_multiple_of(&8), 24); /// ~~~ #[inline] - fn round_up_to(&self, other: &Self) -> Self where Self: traits::NumRef { + fn next_multiple_of(&self, other: &Self) -> Self where Self: traits::NumRef { self.div_ceil(other).mul(other) } @@ -213,11 +213,11 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// /// ~~~ /// # use num_integer::Integer; - /// assert_eq!(16.round_down_to(&8), 16); - /// assert_eq!(23.round_down_to(&8), 16); + /// assert_eq!(16.next_multiple_back_of(&8), 16); + /// assert_eq!(23.next_multiple_back_of(&8), 16); /// ~~~ #[inline] - fn round_down_to(&self, other: &Self) -> Self where Self: traits::NumRef { + fn next_multiple_back_of(&self, other: &Self) -> Self where Self: traits::NumRef { self.div_floor(other).mul(other) } } From 41adfe54a917204f778ca2f2b95bba1317301d60 Mon Sep 17 00:00:00 2001 From: M Farkas-Dyck Date: Mon, 17 Dec 2018 15:45:10 -0800 Subject: [PATCH 05/10] make `next_multiple_of` need `Self: Clone` rather than `Self: NumRef` --- src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c577a95..6880b1d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -203,8 +203,8 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// assert_eq!(23.next_multiple_of(&8), 24); /// ~~~ #[inline] - fn next_multiple_of(&self, other: &Self) -> Self where Self: traits::NumRef { - self.div_ceil(other).mul(other) + fn next_multiple_of(&self, other: &Self) -> Self where Self: Clone { + self.div_ceil(other).mul(other.clone()) } /// Rounds down to nearest multiple of argument. @@ -217,8 +217,8 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// assert_eq!(23.next_multiple_back_of(&8), 16); /// ~~~ #[inline] - fn next_multiple_back_of(&self, other: &Self) -> Self where Self: traits::NumRef { - self.div_floor(other).mul(other) + fn next_multiple_back_of(&self, other: &Self) -> Self where Self: Clone { + self.div_floor(other).mul(other.clone()) } } From 4a6d1599cd27852a3dbad863c4554f33ca808b10 Mon Sep 17 00:00:00 2001 From: M Farkas-Dyck Date: Mon, 17 Dec 2018 15:50:21 -0800 Subject: [PATCH 06/10] redefine `next_multiple_of` to do no multiplication beyond what may be done in `mod_floor` --- src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 6880b1d..a4558cd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -204,7 +204,8 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// ~~~ #[inline] fn next_multiple_of(&self, other: &Self) -> Self where Self: Clone { - self.div_ceil(other).mul(other.clone()) + let m = self.mod_floor(other); + self.clone() + if m.is_zero() { Self::zero() } else { other.clone() - m } } /// Rounds down to nearest multiple of argument. @@ -218,7 +219,7 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// ~~~ #[inline] fn next_multiple_back_of(&self, other: &Self) -> Self where Self: Clone { - self.div_floor(other).mul(other.clone()) + self.clone() - self.mod_floor(other) } } From 426f1d0d240f08f9d4c9582511a82bf3d7a6e2ea Mon Sep 17 00:00:00 2001 From: M Farkas-Dyck Date: Mon, 17 Dec 2018 15:56:50 -0800 Subject: [PATCH 07/10] test negative arguments of `next_multiple_of` --- src/lib.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a4558cd..e90c338 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -199,8 +199,10 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// /// ~~~ /// # use num_integer::Integer; - /// assert_eq!(16.next_multiple_of(&8), 16); - /// assert_eq!(23.next_multiple_of(&8), 24); + /// assert_eq!(16.next_multiple_of(& 8), 16); + /// assert_eq!(23.next_multiple_of(& 8), 24); + /// assert_eq!(16.next_multiple_of(&-8), 16); + /// assert_eq!(23.next_multiple_of(&-8), 16); /// ~~~ #[inline] fn next_multiple_of(&self, other: &Self) -> Self where Self: Clone { @@ -214,8 +216,10 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// /// ~~~ /// # use num_integer::Integer; - /// assert_eq!(16.next_multiple_back_of(&8), 16); - /// assert_eq!(23.next_multiple_back_of(&8), 16); + /// assert_eq!(16.next_multiple_back_of(& 8), 16); + /// assert_eq!(23.next_multiple_back_of(& 8), 16); + /// assert_eq!(16.next_multiple_back_of(&-8), 16); + /// assert_eq!(23.next_multiple_back_of(&-8), 24); /// ~~~ #[inline] fn next_multiple_back_of(&self, other: &Self) -> Self where Self: Clone { From 93176f52d30e54ea1c2d40261e1262fa24a293d0 Mon Sep 17 00:00:00 2001 From: M Farkas-Dyck Date: Fri, 22 Feb 2019 16:28:05 -0800 Subject: [PATCH 08/10] rename `next_multiple_back_of` as `prev_multiple_of` and test more --- src/lib.rs | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e90c338..ee6eef5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -199,10 +199,14 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// /// ~~~ /// # use num_integer::Integer; - /// assert_eq!(16.next_multiple_of(& 8), 16); - /// assert_eq!(23.next_multiple_of(& 8), 24); - /// assert_eq!(16.next_multiple_of(&-8), 16); - /// assert_eq!(23.next_multiple_of(&-8), 16); + /// assert_eq!(( 16).next_multiple_of(& 8), 16); + /// assert_eq!(( 23).next_multiple_of(& 8), 24); + /// assert_eq!(( 16).next_multiple_of(&-8), 16); + /// assert_eq!(( 23).next_multiple_of(&-8), 16); + /// assert_eq!((-16).next_multiple_of(& 8), -16); + /// assert_eq!((-23).next_multiple_of(& 8), -16); + /// assert_eq!((-16).next_multiple_of(&-8), -16); + /// assert_eq!((-23).next_multiple_of(&-8), -24); /// ~~~ #[inline] fn next_multiple_of(&self, other: &Self) -> Self where Self: Clone { @@ -216,13 +220,17 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// /// ~~~ /// # use num_integer::Integer; - /// assert_eq!(16.next_multiple_back_of(& 8), 16); - /// assert_eq!(23.next_multiple_back_of(& 8), 16); - /// assert_eq!(16.next_multiple_back_of(&-8), 16); - /// assert_eq!(23.next_multiple_back_of(&-8), 24); + /// assert_eq!(( 16).prev_multiple_of(& 8), 16); + /// assert_eq!(( 23).prev_multiple_of(& 8), 16); + /// assert_eq!(( 16).prev_multiple_of(&-8), 16); + /// assert_eq!(( 23).prev_multiple_of(&-8), 24); + /// assert_eq!((-16).prev_multiple_of(& 8), -16); + /// assert_eq!((-23).prev_multiple_of(& 8), -24); + /// assert_eq!((-16).prev_multiple_of(&-8), -16); + /// assert_eq!((-23).prev_multiple_of(&-8), -16); /// ~~~ #[inline] - fn next_multiple_back_of(&self, other: &Self) -> Self where Self: Clone { + fn prev_multiple_of(&self, other: &Self) -> Self where Self: Clone { self.clone() - self.mod_floor(other) } } From 7f88fde7271c1108778d7c507812026d4c37521c Mon Sep 17 00:00:00 2001 From: M Farkas-Dyck Date: Fri, 22 Feb 2019 16:31:59 -0800 Subject: [PATCH 09/10] note relation of `next_multiple_of` and `prev_multiple_of` --- src/lib.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index ee6eef5..ba96ce5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -195,6 +195,10 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// Rounds up to nearest multiple of argument. /// + /// # Notes + /// + /// For signed types, `a.next_multiple_of(b) = a.prev_multiple_of(b.neg())`. + /// /// # Examples /// /// ~~~ @@ -216,6 +220,10 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// Rounds down to nearest multiple of argument. /// + /// # Notes + /// + /// For signed types, `a.prev_multiple_of(b) = a.next_multiple_of(b.neg())`. + /// /// # Examples /// /// ~~~ From 31ff090abcdcece299f8143d72b9f06600f185bb Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 27 Mar 2019 16:14:56 -0700 Subject: [PATCH 10/10] cargo fmt --- src/lib.rs | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ba96ce5..f4d3ad3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -91,7 +91,11 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// ~~~ fn div_ceil(&self, other: &Self) -> Self { let (q, r) = self.div_mod_floor(other); - if r.is_zero() { q } else { q+Self::one() } + if r.is_zero() { + q + } else { + q + Self::one() + } } /// Greatest Common Divisor (GCD). @@ -213,9 +217,17 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// assert_eq!((-23).next_multiple_of(&-8), -24); /// ~~~ #[inline] - fn next_multiple_of(&self, other: &Self) -> Self where Self: Clone { + fn next_multiple_of(&self, other: &Self) -> Self + where + Self: Clone, + { let m = self.mod_floor(other); - self.clone() + if m.is_zero() { Self::zero() } else { other.clone() - m } + self.clone() + + if m.is_zero() { + Self::zero() + } else { + other.clone() - m + } } /// Rounds down to nearest multiple of argument. @@ -238,7 +250,10 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// assert_eq!((-23).prev_multiple_of(&-8), -16); /// ~~~ #[inline] - fn prev_multiple_of(&self, other: &Self) -> Self where Self: Clone { + fn prev_multiple_of(&self, other: &Self) -> Self + where + Self: Clone, + { self.clone() - self.mod_floor(other) } } @@ -322,10 +337,11 @@ macro_rules! impl_integer_for_isize { #[inline] fn div_ceil(&self, other: &Self) -> Self { - match self.div_rem(other) { - (d, r) if (r > 0 && *other > 0) - || (r < 0 && *other < 0) => d + 1, - (d, _) => d, + let (d, r) = self.div_rem(other); + if (r > 0 && *other > 0) || (r < 0 && *other < 0) { + d + 1 + } else { + d } }