Skip to content

Commit b29d99b

Browse files
SparrowLiicuviper
authored andcommitted
Fixes methods
1 parent 2d761d4 commit b29d99b

File tree

2 files changed

+175
-79
lines changed

2 files changed

+175
-79
lines changed

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ pub use int::PrimInt;
4040
pub use ops::checked::{
4141
CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr, CheckedSub,
4242
};
43-
pub use ops::euclid::{CheckedDivRemEuclid, DivRemEuclid};
43+
pub use ops::euclid::{CheckedDivEuclid, CheckedRemEuclid, DivEuclid, RemEuclid};
4444
pub use ops::inv::Inv;
4545
pub use ops::mul_add::{MulAdd, MulAddAssign};
4646
pub use ops::saturating::{Saturating, SaturatingAdd, SaturatingMul, SaturatingSub};

src/ops/euclid.rs

Lines changed: 174 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,139 +1,235 @@
11
use core::ops::{Div, Rem};
2-
pub trait DivRemEuclid: Sized + Div<Self, Output = Self> + Rem<Self, Output = Self> {
2+
pub trait DivEuclid: Sized + Div<Self, Output = Self> {
33
/// Calculates Euclidean division, the matching method for `rem_euclid`.
44
///
55
/// This computes the integer `n` such that
6-
/// `self = n * rhs + self.rem_euclid(rhs)`.
7-
/// In other words, the result is `self / rhs` rounded to the integer `n`
8-
/// such that `self >= n * rhs`.
6+
/// `self = n * v + self.rem_euclid(v)`.
7+
/// In other words, the result is `self / v` rounded to the integer `n`
8+
/// such that `self >= n * v`.
99
///
1010
/// # Examples
1111
///
1212
/// ```
13-
/// use num_traits::DivRemEuclid;
13+
/// use num_traits::DivEuclid;
1414
///
1515
/// let a: i32 = 7;
1616
/// let b: i32 = 4;
17-
/// assert_eq!(DivRemEuclid::div_euclid(&a,&b), 1); // 7 > 4 * 1
18-
/// assert_eq!(DivRemEuclid::div_euclid(&-a,&b), -2); // -7 >= 4 * -2
19-
/// assert_eq!(DivRemEuclid::div_euclid(&a,&-b), -1); // 7 >= -4 * -1
20-
/// assert_eq!(DivRemEuclid::div_euclid(&-a,&-b), 2); // -7 >= -4 * 2
17+
/// assert_eq!(DivEuclid::div_euclid(a,b), 1); // 7 > 4 * 1
18+
/// assert_eq!(DivEuclid::div_euclid(-a,b), -2); // -7 >= 4 * -2
19+
/// assert_eq!(DivEuclid::div_euclid(a,-b), -1); // 7 >= -4 * -1
20+
/// assert_eq!(DivEuclid::div_euclid(-a,-b), 2); // -7 >= -4 * 2
2121
/// ```
22-
fn div_euclid(&self, v: &Self) -> Self;
23-
24-
/// Calculates the least nonnegative remainder of `self (mod rhs)`.
22+
fn div_euclid(self, v: Self) -> Self;
23+
}
24+
pub trait RemEuclid: Sized + Rem<Self, Output = Self> {
25+
/// Calculates the least nonnegative remainder of `self (mod v)`.
2526
///
26-
/// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
27+
/// In particular, the return value `r` satisfies `0.0 <= r < v.abs()` in
2728
/// most cases. However, due to a floating point round-off error it can
28-
/// result in `r == rhs.abs()`, violating the mathematical definition, if
29-
/// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
29+
/// result in `r == v.abs()`, violating the mathematical definition, if
30+
/// `self` is much smaller than `v.abs()` in magnitude and `self < 0.0`.
3031
/// This result is not an element of the function's codomain, but it is the
3132
/// closest floating point number in the real numbers and thus fulfills the
32-
/// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
33+
/// property `self == self.div_euclid(v) * v + self.rem_euclid(v)`
3334
/// approximatively.
3435
///
3536
/// # Examples
3637
///
3738
/// ```
38-
/// use num_traits::DivRemEuclid;
39+
/// use num_traits::RemEuclid;
3940
///
4041
/// let a: i32 = 7;
4142
/// let b: i32 = 4;
42-
/// assert_eq!(DivRemEuclid::rem_euclid(&a,&b), 3);
43-
/// assert_eq!(DivRemEuclid::rem_euclid(&-a,&b), 1);
44-
/// assert_eq!(DivRemEuclid::rem_euclid(&a,&-b), 3);
45-
/// assert_eq!(DivRemEuclid::rem_euclid(&-a,&-b), 1);
43+
/// assert_eq!(RemEuclid::rem_euclid(a,b), 3);
44+
/// assert_eq!(RemEuclid::rem_euclid(-a,b), 1);
45+
/// assert_eq!(RemEuclid::rem_euclid(a,-b), 3);
46+
/// assert_eq!(RemEuclid::rem_euclid(-a,-b), 1);
4647
/// ```
47-
fn rem_euclid(&self, v: &Self) -> Self;
48+
fn rem_euclid(self, v: Self) -> Self;
4849
}
49-
macro_rules! div_rem_euclid_impl {
50-
($trait_name:ident,$method:ident,$method_2:ident for $($t:ty)*) => {$(
50+
macro_rules! div_euclid_int_impl {
51+
($trait_name:ident for $($t:ty)*) => {$(
5152
impl $trait_name for $t {
5253
#[inline]
53-
fn $method(&self, v: &$t) -> Self {
54-
<$t>::$method(*self, *v)
54+
fn div_euclid(self, v: $t) -> Self {
55+
let q = self / v;
56+
if self % v < 0 {
57+
return if v > 0 { q - 1 } else { q + 1 }
58+
}
59+
q
5560
}
56-
61+
}
62+
)*}
63+
}
64+
macro_rules! div_euclid_uint_impl {
65+
($trait_name:ident for $($t:ty)*) => {$(
66+
impl $trait_name for $t {
5767
#[inline]
58-
fn $method_2(&self, v: &$t) -> Self {
59-
<$t>::$method_2(*self, *v)
68+
fn div_euclid(self, v: $t) -> Self {
69+
self / v
6070
}
61-
6271
}
6372
)*}
6473
}
65-
div_rem_euclid_impl!(DivRemEuclid,div_euclid,rem_euclid for isize usize i8 u8 i16 u16 i32 u32 i64 u64);
74+
macro_rules! rem_euclid_int_impl {
75+
($trait_name:ident for $($t:ty)*) => {$(
76+
impl $trait_name for $t {
77+
#[inline]
78+
fn rem_euclid(self, v: $t) -> Self {
79+
let r = self % v;
80+
if r < 0 {
81+
if v < 0 {
82+
r - v
83+
} else {
84+
r + v
85+
}
86+
} else {
87+
r
88+
}
89+
}
90+
}
91+
)*}
92+
}
93+
macro_rules! rem_euclid_uint_impl {
94+
($trait_name:ident for $($t:ty)*) => {$(
95+
impl $trait_name for $t {
96+
#[inline]
97+
fn rem_euclid(self, v: $t) -> Self {
98+
self % v
99+
}
100+
}
101+
)*}
102+
}
103+
div_euclid_int_impl!(DivEuclid for i8 i16 i32 i64);
104+
div_euclid_uint_impl!(DivEuclid for isize usize u8 u16 u32 u64);
105+
rem_euclid_int_impl!(RemEuclid for i8 i16 i32 i64);
106+
rem_euclid_uint_impl!(RemEuclid for isize usize u8 u16 u32 u64);
66107
#[cfg(has_i128)]
67-
div_rem_euclid_impl!(DivRemEuclid,div_euclid,rem_euclid for i128 u128);
108+
div_euclid_int_impl!(DivEuclid for i128);
109+
div_euclid_uint_impl!(DivEuclid for u128);
110+
rem_euclid_int_impl!(RemEuclid for i128);
111+
rem_euclid_uint_impl!(RemEuclid for u128);
68112

69113
#[cfg(any(feature = "std", feature = "libm"))]
70-
impl DivRemEuclid for f32 {
71-
fn div_euclid(&self, rhs: &f32) -> f32 {
72-
let q = <f32 as ::Float>::trunc(self / rhs);
73-
if self % rhs < 0.0 {
74-
return if *rhs > 0.0 { q - 1.0 } else { q + 1.0 };
114+
impl DivEuclid for f32 {
115+
fn div_euclid(self, v: f32) -> f32 {
116+
let q = <f32 as ::Float>::trunc(self / v);
117+
if self % v < 0.0 {
118+
return if v > 0.0 { q - 1.0 } else { q + 1.0 };
75119
}
76120
q
77121
}
122+
}
78123

79-
fn rem_euclid(&self, rhs: &f32) -> f32 {
80-
let r = self % rhs;
124+
#[cfg(any(feature = "std", feature = "libm"))]
125+
impl RemEuclid for f32 {
126+
fn rem_euclid(self, v: f32) -> f32 {
127+
let r = self % v;
81128
if r < 0.0 {
82-
r + <f32 as ::Float>::abs(*rhs)
129+
r + <f32 as ::Float>::abs(v)
83130
} else {
84131
r
85132
}
86133
}
87134
}
88135

89136
#[cfg(any(feature = "std", feature = "libm"))]
90-
impl DivRemEuclid for f64 {
91-
fn div_euclid(&self, rhs: &f64) -> f64 {
92-
let q = <f64 as ::Float>::trunc(self / rhs);
93-
if self % rhs < 0.0 {
94-
return if *rhs > 0.0 { q - 1.0 } else { q + 1.0 };
137+
impl DivEuclid for f64 {
138+
fn div_euclid(self, v: f64) -> f64 {
139+
let q = <f64 as ::Float>::trunc(self / v);
140+
if self % v < 0.0 {
141+
return if v > 0.0 { q - 1.0 } else { q + 1.0 };
95142
}
96143
q
97144
}
98-
99-
fn rem_euclid(&self, rhs: &f64) -> f64 {
100-
let r = self % rhs;
145+
}
146+
#[cfg(any(feature = "std", feature = "libm"))]
147+
impl RemEuclid for f64 {
148+
fn rem_euclid(self, v: f64) -> f64 {
149+
let r = self % v;
101150
if r < 0.0 {
102-
r + <f64 as ::Float>::abs(*rhs)
151+
r + <f64 as ::Float>::abs(v)
103152
} else {
104153
r
105154
}
106155
}
107156
}
108157

109-
pub trait CheckedDivRemEuclid: Sized + Div<Self, Output = Self> + Rem<Self, Output = Self> {
158+
pub trait CheckedDivEuclid: DivEuclid {
110159
/// Performs euclid division that returns `None` instead of panicking on division by zero
111160
/// and instead of wrapping around on underflow and overflow.
112-
fn checked_div_euclid(&self, v: &Self) -> Option<Self>;
113-
161+
fn checked_div_euclid(self, v: Self) -> Option<Self>;
162+
}
163+
pub trait CheckedRemEuclid: RemEuclid {
114164
/// Finds the euclid remainder of dividing two numbers, checking for underflow, overflow and
115165
/// division by zero. If any of that happens, `None` is returned.
116-
fn checked_rem_euclid(&self, v: &Self) -> Option<Self>;
166+
fn checked_rem_euclid(self, v: Self) -> Option<Self>;
117167
}
118-
119-
macro_rules! checked_div_rem_euclid_impl {
120-
($trait_name:ident,$method:ident,$method_2:ident for $($t:ty)*) => {$(
168+
macro_rules! checked_div_euclid_int_impl {
169+
($trait_name:ident for $($t:ty)*) => {$(
121170
impl $trait_name for $t {
122171
#[inline]
123-
fn $method(&self, v: &$t) -> Option<$t> {
124-
<$t>::$method(*self, *v)
172+
fn checked_div_euclid(self, v: $t) -> Option<$t> {
173+
if v == 0 || (self == Self::MIN && v == -1) {
174+
None
175+
} else {
176+
Some(DivEuclid::div_euclid(self,v))
177+
}
125178
}
126-
179+
}
180+
)*}
181+
}
182+
macro_rules! checked_div_euclid_uint_impl {
183+
($trait_name:ident for $($t:ty)*) => {$(
184+
impl $trait_name for $t {
185+
#[inline]
186+
fn checked_div_euclid(self, v: $t) -> Option<$t> {
187+
if v == 0{
188+
None
189+
} else {
190+
Some(DivEuclid::div_euclid(self,v))
191+
}
192+
}
193+
}
194+
)*}
195+
}
196+
macro_rules! checked_rem_euclid_int_impl {
197+
($trait_name:ident for $($t:ty)*) => {$(
198+
impl $trait_name for $t {
199+
#[inline]
200+
fn checked_rem_euclid(self, v: $t) -> Option<$t> {
201+
if v == 0 || (self == Self::MIN && v == -1) {
202+
None
203+
} else {
204+
Some(RemEuclid::rem_euclid(self,v))
205+
}
206+
}
207+
}
208+
)*}
209+
}
210+
macro_rules! checked_rem_euclid_uint_impl {
211+
($trait_name:ident for $($t:ty)*) => {$(
212+
impl $trait_name for $t {
127213
#[inline]
128-
fn $method_2(&self, v: &$t) -> Option<$t> {
129-
<$t>::$method_2(*self, *v)
214+
fn checked_rem_euclid(self, v: $t) -> Option<$t> {
215+
if v == 0{
216+
None
217+
} else {
218+
Some(RemEuclid::rem_euclid(self,v))
219+
}
130220
}
131221
}
132222
)*}
133223
}
134-
checked_div_rem_euclid_impl!(CheckedDivRemEuclid,checked_div_euclid,checked_rem_euclid for isize usize i8 u8 i16 u16 i32 u32 i64 u64);
224+
checked_div_euclid_int_impl!(CheckedDivEuclid for i8 i16 i32 i64);
225+
checked_div_euclid_uint_impl!(CheckedDivEuclid for isize usize u8 u16 u32 u64);
226+
checked_rem_euclid_int_impl!(CheckedRemEuclid for i8 i16 i32 i64);
227+
checked_rem_euclid_uint_impl!(CheckedRemEuclid for isize usize u8 u16 u32 u64);
135228
#[cfg(has_i128)]
136-
checked_div_rem_euclid_impl!(CheckedDivRemEuclid,checked_div_euclid,checked_rem_euclid for i128 u128);
229+
checked_div_euclid_int_impl!(CheckedDivEuclid for i128);
230+
checked_div_euclid_uint_impl!(CheckedDivEuclid for u128);
231+
checked_rem_euclid_int_impl!(CheckedRemEuclid for i128);
232+
checked_rem_euclid_uint_impl!(CheckedRemEuclid for u128);
137233

138234
#[cfg(test)]
139235
mod tests {
@@ -147,8 +243,8 @@ mod tests {
147243
{
148244
let x: $t = 10;
149245
let y: $t = 3;
150-
assert_eq!(DivRemEuclid::div_euclid(&x,&y),3);
151-
assert_eq!(DivRemEuclid::rem_euclid(&x,&y),1);
246+
assert_eq!(DivEuclid::div_euclid(x,y),3);
247+
assert_eq!(RemEuclid::rem_euclid(x,y),1);
152248
}
153249
)+
154250
};
@@ -165,13 +261,13 @@ mod tests {
165261
{
166262
let x: $t = 10;
167263
let y: $t = -3;
168-
assert_eq!(DivRemEuclid::div_euclid(&x,&y),-3);
169-
assert_eq!(DivRemEuclid::div_euclid(&-x,&y),4);
170-
assert_eq!(DivRemEuclid::rem_euclid(&x,&y),1);
171-
assert_eq!(DivRemEuclid::rem_euclid(&-x,&y),2);
264+
assert_eq!(DivEuclid::div_euclid(x,y),-3);
265+
assert_eq!(DivEuclid::div_euclid(-x,y),4);
266+
assert_eq!(RemEuclid::rem_euclid(x,y),1);
267+
assert_eq!(RemEuclid::rem_euclid(-x,y),2);
172268
let x: $t = $t::MIN+1;
173269
let y: $t = -1;
174-
assert_eq!(DivRemEuclid::div_euclid(&x,&y),$t::MAX);
270+
assert_eq!(DivEuclid::div_euclid(x,y),$t::MAX);
175271
}
176272
)+
177273
};
@@ -189,13 +285,13 @@ mod tests {
189285
{
190286
let x: $t = 12.1;
191287
let y: $t = 3.2;
192-
assert!(DivRemEuclid::div_euclid(&x,&y)*y+DivRemEuclid::rem_euclid(&x,&y)-x
288+
assert!(DivEuclid::div_euclid(x,y)*y+RemEuclid::rem_euclid(x,y)-x
193289
<=46.4 * $t::EPSILON);
194-
assert!(DivRemEuclid::div_euclid(&x,&-y)*-y+DivRemEuclid::rem_euclid(&x,&-y)-x
290+
assert!(DivEuclid::div_euclid(x,-y)*-y+RemEuclid::rem_euclid(x,-y)-x
195291
<= 46.4 * $t::EPSILON);
196-
assert!(DivRemEuclid::div_euclid(&-x,&y)*y+DivRemEuclid::rem_euclid(&-x,&y)-(-x)
292+
assert!(DivEuclid::div_euclid(-x,y)*y+RemEuclid::rem_euclid(-x,y)-(-x)
197293
<= 46.4 * $t::EPSILON);
198-
assert!(DivRemEuclid::div_euclid(&-x,&-y)*-y+DivRemEuclid::rem_euclid(&-x,&-y)-(-x)
294+
assert!(DivEuclid::div_euclid(-x,-y)*-y+RemEuclid::rem_euclid(-x,-y)-(-x)
199295
<= 46.4 * $t::EPSILON);
200296
}
201297
)+
@@ -211,10 +307,10 @@ mod tests {
211307
($($t:ident)+) => {
212308
$(
213309
{
214-
assert_eq!(CheckedDivRemEuclid::checked_div_euclid(&$t::MIN,&-1),None);
215-
assert_eq!(CheckedDivRemEuclid::checked_rem_euclid(&$t::MIN,&-1),None);
216-
assert_eq!(CheckedDivRemEuclid::checked_div_euclid(&1,&0),None);
217-
assert_eq!(CheckedDivRemEuclid::checked_rem_euclid(&1,&0),None);
310+
assert_eq!(CheckedDivEuclid::checked_div_euclid($t::MIN,-1),None);
311+
assert_eq!(CheckedRemEuclid::checked_rem_euclid($t::MIN,-1),None);
312+
assert_eq!(CheckedDivEuclid::checked_div_euclid(1,0),None);
313+
assert_eq!(CheckedRemEuclid::checked_rem_euclid(1,0),None);
218314
}
219315
)+
220316
};

0 commit comments

Comments
 (0)