1
1
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 > {
3
3
/// Calculates Euclidean division, the matching method for `rem_euclid`.
4
4
///
5
5
/// 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 `.
9
9
///
10
10
/// # Examples
11
11
///
12
12
/// ```
13
- /// use num_traits::DivRemEuclid ;
13
+ /// use num_traits::DivEuclid ;
14
14
///
15
15
/// let a: i32 = 7;
16
16
/// 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
21
21
/// ```
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)`.
25
26
///
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
27
28
/// 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`.
30
31
/// This result is not an element of the function's codomain, but it is the
31
32
/// 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 )`
33
34
/// approximatively.
34
35
///
35
36
/// # Examples
36
37
///
37
38
/// ```
38
- /// use num_traits::DivRemEuclid ;
39
+ /// use num_traits::RemEuclid ;
39
40
///
40
41
/// let a: i32 = 7;
41
42
/// 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);
46
47
/// ```
47
- fn rem_euclid ( & self , v : & Self ) -> Self ;
48
+ fn rem_euclid ( self , v : Self ) -> Self ;
48
49
}
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) * ) => { $(
51
52
impl $trait_name for $t {
52
53
#[ 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
55
60
}
56
-
61
+ }
62
+ ) * }
63
+ }
64
+ macro_rules! div_euclid_uint_impl {
65
+ ( $trait_name: ident for $( $t: ty) * ) => { $(
66
+ impl $trait_name for $t {
57
67
#[ 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
60
70
}
61
-
62
71
}
63
72
) * }
64
73
}
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 ) ;
66
107
#[ 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 ) ;
68
112
69
113
#[ 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 } ;
75
119
}
76
120
q
77
121
}
122
+ }
78
123
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;
81
128
if r < 0.0 {
82
- r + <f32 as :: Float >:: abs ( * rhs )
129
+ r + <f32 as :: Float >:: abs ( v )
83
130
} else {
84
131
r
85
132
}
86
133
}
87
134
}
88
135
89
136
#[ 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 } ;
95
142
}
96
143
q
97
144
}
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;
101
150
if r < 0.0 {
102
- r + <f64 as :: Float >:: abs ( * rhs )
151
+ r + <f64 as :: Float >:: abs ( v )
103
152
} else {
104
153
r
105
154
}
106
155
}
107
156
}
108
157
109
- pub trait CheckedDivRemEuclid : Sized + Div < Self , Output = Self > + Rem < Self , Output = Self > {
158
+ pub trait CheckedDivEuclid : DivEuclid {
110
159
/// Performs euclid division that returns `None` instead of panicking on division by zero
111
160
/// 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 {
114
164
/// Finds the euclid remainder of dividing two numbers, checking for underflow, overflow and
115
165
/// 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 > ;
117
167
}
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) * ) => { $(
121
170
impl $trait_name for $t {
122
171
#[ 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
+ }
125
178
}
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 {
127
213
#[ 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
+ }
130
220
}
131
221
}
132
222
) * }
133
223
}
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 ) ;
135
228
#[ 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 ) ;
137
233
138
234
#[ cfg( test) ]
139
235
mod tests {
@@ -147,8 +243,8 @@ mod tests {
147
243
{
148
244
let x: $t = 10 ;
149
245
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 ) ;
152
248
}
153
249
) +
154
250
} ;
@@ -165,13 +261,13 @@ mod tests {
165
261
{
166
262
let x: $t = 10 ;
167
263
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 ) ;
172
268
let x: $t = $t:: MIN +1 ;
173
269
let y: $t = -1 ;
174
- assert_eq!( DivRemEuclid :: div_euclid( & x , & y) , $t:: MAX ) ;
270
+ assert_eq!( DivEuclid :: div_euclid( x , y) , $t:: MAX ) ;
175
271
}
176
272
) +
177
273
} ;
@@ -189,13 +285,13 @@ mod tests {
189
285
{
190
286
let x: $t = 12.1 ;
191
287
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
193
289
<=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
195
291
<= 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)
197
293
<= 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)
199
295
<= 46.4 * $t:: EPSILON ) ;
200
296
}
201
297
) +
@@ -211,10 +307,10 @@ mod tests {
211
307
( $( $t: ident) +) => {
212
308
$(
213
309
{
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 ) ;
218
314
}
219
315
) +
220
316
} ;
0 commit comments