1c0nst::c0nst! {
7pub c0nst trait Euclid: Sized {
8 type Output;
11
12 fn div_euclid(self, v: Self) -> Self::Output;
32
33 fn rem_euclid(self, v: Self) -> Self::Output;
57
58 fn div_rem_euclid(self, v: Self) -> (Self::Output, Self::Output);
76}
77}
78
79macro_rules! euclid_forward_impl {
80 ($($t:ty)*) => {$(
81 c0nst::c0nst! {
82 c0nst impl Euclid for $t {
83 type Output = $t;
84 #[inline]
85 fn div_euclid(self, v: $t) -> Self {
86 <$t>::div_euclid(self, v)
87 }
88
89 #[inline]
90 fn rem_euclid(self, v: $t) -> Self {
91 <$t>::rem_euclid(self, v)
92 }
93
94 #[inline]
95 fn div_rem_euclid(self, v: $t) -> ($t, $t) {
96 (<$t>::div_euclid(self, v), <$t>::rem_euclid(self, v))
97 }
98 }
99 }
100 )*}
101}
102
103euclid_forward_impl!(isize i8 i16 i32 i64 i128);
104euclid_forward_impl!(usize u8 u16 u32 u64 u128);
105
106#[cfg(feature = "std")]
109macro_rules! euclid_forward_impl_float {
110 ($($t:ty)*) => {$(
111 impl Euclid for $t {
112 type Output = $t;
113 #[inline]
114 fn div_euclid(self, v: $t) -> Self {
115 <$t>::div_euclid(self, v)
116 }
117
118 #[inline]
119 fn rem_euclid(self, v: $t) -> Self {
120 <$t>::rem_euclid(self, v)
121 }
122
123 #[inline]
124 fn div_rem_euclid(self, v: $t) -> ($t, $t) {
125 (<$t>::div_euclid(self, v), <$t>::rem_euclid(self, v))
126 }
127 }
128 )*}
129}
130
131#[cfg(feature = "std")]
132euclid_forward_impl_float!(f32 f64);
133
134#[cfg(not(feature = "std"))]
135impl Euclid for f32 {
136 type Output = f32;
137 #[inline]
138 fn div_euclid(self, v: f32) -> f32 {
139 let q = <f32 as crate::float::FloatCore>::trunc(self / v);
140 if self % v < 0.0 {
141 return if v > 0.0 { q - 1.0 } else { q + 1.0 };
142 }
143 q
144 }
145
146 #[inline]
147 fn rem_euclid(self, v: f32) -> f32 {
148 let r = self % v;
149 if r < 0.0 {
150 r + <f32 as crate::float::FloatCore>::abs(v)
151 } else {
152 r
153 }
154 }
155
156 #[inline]
157 fn div_rem_euclid(self, v: f32) -> (f32, f32) {
158 (Euclid::div_euclid(self, v), Euclid::rem_euclid(self, v))
159 }
160}
161
162#[cfg(not(feature = "std"))]
163impl Euclid for f64 {
164 type Output = f64;
165 #[inline]
166 fn div_euclid(self, v: f64) -> f64 {
167 let q = <f64 as crate::float::FloatCore>::trunc(self / v);
168 if self % v < 0.0 {
169 return if v > 0.0 { q - 1.0 } else { q + 1.0 };
170 }
171 q
172 }
173
174 #[inline]
175 fn rem_euclid(self, v: f64) -> f64 {
176 let r = self % v;
177 if r < 0.0 {
178 r + <f64 as crate::float::FloatCore>::abs(v)
179 } else {
180 r
181 }
182 }
183
184 #[inline]
185 fn div_rem_euclid(self, v: f64) -> (f64, f64) {
186 (Euclid::div_euclid(self, v), Euclid::rem_euclid(self, v))
187 }
188}
189
190c0nst::c0nst! {
191pub c0nst trait CheckedEuclid: [c0nst] Euclid {
192 fn checked_div_euclid(self, v: Self) -> Option<<Self as Euclid>::Output>;
195
196 fn checked_rem_euclid(self, v: Self) -> Option<<Self as Euclid>::Output>;
199
200 fn checked_div_rem_euclid(self, v: Self) -> Option<(<Self as Euclid>::Output, <Self as Euclid>::Output)>;
216}
217}
218
219macro_rules! checked_euclid_forward_impl {
220 ($($t:ty)*) => {$(
221 c0nst::c0nst! {
222 c0nst impl CheckedEuclid for $t {
223 #[inline]
224 fn checked_div_euclid(self, v: $t) -> Option<Self> {
225 <$t>::checked_div_euclid(self, v)
226 }
227
228 #[inline]
229 fn checked_rem_euclid(self, v: $t) -> Option<Self> {
230 <$t>::checked_rem_euclid(self, v)
231 }
232
233 #[inline]
236 fn checked_div_rem_euclid(self, v: $t) -> Option<(Self, Self)> {
237 let d = match <$t>::checked_div_euclid(self, v) {
238 Some(x) => x,
239 None => return None,
240 };
241 let r = match <$t>::checked_rem_euclid(self, v) {
242 Some(x) => x,
243 None => return None,
244 };
245 Some((d, r))
246 }
247 }
248 }
249 )*}
250}
251
252checked_euclid_forward_impl!(isize i8 i16 i32 i64 i128);
253checked_euclid_forward_impl!(usize u8 u16 u32 u64 u128);
254
255c0nst::c0nst! {
256pub c0nst trait WrappingEuclid: [c0nst] Euclid {
258 fn wrapping_div_euclid(self, v: Self) -> <Self as Euclid>::Output;
266
267 fn wrapping_rem_euclid(self, v: Self) -> <Self as Euclid>::Output;
275}
276}
277
278macro_rules! wrapping_euclid_forward_impl {
279 ($($t:ty)*) => {$(
280 c0nst::c0nst! {
281 c0nst impl WrappingEuclid for $t {
282 #[inline]
283 fn wrapping_div_euclid(self, v: $t) -> Self {
284 <$t>::wrapping_div_euclid(self, v)
285 }
286
287 #[inline]
288 fn wrapping_rem_euclid(self, v: $t) -> Self {
289 <$t>::wrapping_rem_euclid(self, v)
290 }
291 }
292 }
293 )*}
294}
295
296wrapping_euclid_forward_impl!(isize i8 i16 i32 i64 i128);
297wrapping_euclid_forward_impl!(usize u8 u16 u32 u64 u128);
298
299c0nst::c0nst! {
300pub c0nst trait OverflowingEuclid: [c0nst] Euclid {
302 fn overflowing_div_euclid(self, v: Self) -> (<Self as Euclid>::Output, bool);
310
311 fn overflowing_rem_euclid(self, v: Self) -> (<Self as Euclid>::Output, bool);
320}
321}
322
323macro_rules! overflowing_euclid_forward_impl {
324 ($($t:ty)*) => {$(
325 c0nst::c0nst! {
326 c0nst impl OverflowingEuclid for $t {
327 #[inline]
328 fn overflowing_div_euclid(self, v: $t) -> (Self, bool) {
329 <$t>::overflowing_div_euclid(self, v)
330 }
331
332 #[inline]
333 fn overflowing_rem_euclid(self, v: $t) -> (Self, bool) {
334 <$t>::overflowing_rem_euclid(self, v)
335 }
336 }
337 }
338 )*}
339}
340
341overflowing_euclid_forward_impl!(isize i8 i16 i32 i64 i128);
342overflowing_euclid_forward_impl!(usize u8 u16 u32 u64 u128);
343
344#[cfg(test)]
345mod tests {
346 use super::*;
347
348 #[test]
349 fn euclid_unsigned() {
350 macro_rules! test_euclid {
351 ($($t:ident)+) => {
352 $(
353 {
354 let x: $t = 10;
355 let y: $t = 3;
356 let div = Euclid::div_euclid(x, y);
357 let rem = Euclid::rem_euclid(x, y);
358 assert_eq!(div, 3);
359 assert_eq!(rem, 1);
360 assert_eq!((div, rem), Euclid::div_rem_euclid(x, y));
361 }
362 )+
363 };
364 }
365
366 test_euclid!(usize u8 u16 u32 u64);
367 }
368
369 #[test]
370 fn euclid_signed() {
371 macro_rules! test_euclid {
372 ($($t:ident)+) => {
373 $(
374 {
375 let x: $t = 10;
376 let y: $t = -3;
377 assert_eq!(Euclid::div_euclid(x, y), -3);
378 assert_eq!(Euclid::div_euclid(-x, y), 4);
379 assert_eq!(Euclid::rem_euclid(x, y), 1);
380 assert_eq!(Euclid::rem_euclid(-x, y), 2);
381 assert_eq!((Euclid::div_euclid(x, y), Euclid::rem_euclid(x, y)), Euclid::div_rem_euclid(x, y));
382 let x: $t = $t::MIN + 1;
383 let y: $t = -1;
384 assert_eq!(Euclid::div_euclid(x, y), $t::MAX);
385 }
386 )+
387 };
388 }
389
390 test_euclid!(isize i8 i16 i32 i64 i128);
391 }
392
393 #[test]
394 #[cfg(feature = "std")]
395 fn euclid_float() {
396 macro_rules! test_euclid {
397 ($($t:ident)+) => {
398 $(
399 {
400 let x: $t = 12.1;
401 let y: $t = 3.2;
402 assert!((Euclid::div_euclid(x, y) * y + Euclid::rem_euclid(x, y) - x).abs()
405 <= 46.4 * <$t>::EPSILON);
406 assert!((Euclid::div_euclid(x, -y) * -y + Euclid::rem_euclid(x, -y) - x).abs()
407 <= 46.4 * <$t>::EPSILON);
408 assert!((Euclid::div_euclid(-x, y) * y + Euclid::rem_euclid(-x, y) + x).abs()
409 <= 46.4 * <$t>::EPSILON);
410 assert!((Euclid::div_euclid(-x, -y) * -y + Euclid::rem_euclid(-x, -y) + x).abs()
411 <= 46.4 * <$t>::EPSILON);
412 assert_eq!((Euclid::div_euclid(x, y), Euclid::rem_euclid(x, y)), Euclid::div_rem_euclid(x, y));
413 }
414 )+
415 };
416 }
417
418 test_euclid!(f32 f64);
419 }
420
421 #[test]
422 fn euclid_wrapping_overflowing() {
423 assert_eq!(WrappingEuclid::wrapping_div_euclid(i8::MIN, -1), i8::MIN);
424 assert_eq!(WrappingEuclid::wrapping_rem_euclid(i8::MIN, -1), 0);
425 assert_eq!(WrappingEuclid::wrapping_div_euclid(-7i32, 4), -2);
426 assert_eq!(WrappingEuclid::wrapping_rem_euclid(-7i32, 4), 1);
427 assert_eq!(
428 OverflowingEuclid::overflowing_div_euclid(i8::MIN, -1),
429 (i8::MIN, true)
430 );
431 assert_eq!(
432 OverflowingEuclid::overflowing_rem_euclid(i8::MIN, -1),
433 (0, true)
434 );
435 assert_eq!(
436 OverflowingEuclid::overflowing_div_euclid(7u8, 4),
437 (1, false)
438 );
439 }
440
441 #[test]
442 fn euclid_checked() {
443 macro_rules! test_euclid_checked {
444 ($($t:ident)+) => {
445 $(
446 {
447 assert_eq!(CheckedEuclid::checked_div_euclid($t::MIN, -1), None);
448 assert_eq!(CheckedEuclid::checked_rem_euclid($t::MIN, -1), None);
449 assert_eq!(CheckedEuclid::checked_div_euclid(1, 0), None);
450 assert_eq!(CheckedEuclid::checked_rem_euclid(1, 0), None);
451 }
452 )+
453 };
454 }
455
456 test_euclid_checked!(isize i8 i16 i32 i64 i128);
457 }
458}