@@ -191,6 +191,24 @@ impl Div<T,T> for T {
191191#[cfg(stage2,notest)]
192192#[cfg(stage3,notest)]
193193impl Quot<T,T> for T {
194+ /**
195+ * Returns the integer quotient, truncated towards 0. As this behaviour reflects
196+ * the underlying machine implementation it is more efficient than `Natural::div`.
197+ *
198+ * # Examples
199+ *
200+ * ~~~
201+ * assert!( 8 / 3 == 2);
202+ * assert!( 8 / -3 == -2);
203+ * assert!(-8 / 3 == -2);
204+ * assert!(-8 / -3 == 2);
205+
206+ * assert!( 1 / 2 == 0);
207+ * assert!( 1 / -2 == 0);
208+ * assert!(-1 / 2 == 0);
209+ * assert!(-1 / -2 == 0);
210+ * ~~~
211+ */
194212 #[inline(always)]
195213 fn quot(&self, other: &T) -> T { *self / *other }
196214}
@@ -205,6 +223,27 @@ impl Modulo<T,T> for T {
205223#[cfg(stage2,notest)]
206224#[cfg(stage3,notest)]
207225impl Rem<T,T> for T {
226+ /**
227+ * Returns the integer remainder after division, satisfying:
228+ *
229+ * ~~~
230+ * assert!((n / d) * d + (n % d) == n)
231+ * ~~~
232+ *
233+ * # Examples
234+ *
235+ * ~~~
236+ * assert!( 8 % 3 == 2);
237+ * assert!( 8 % -3 == 2);
238+ * assert!(-8 % 3 == -2);
239+ * assert!(-8 % -3 == -2);
240+
241+ * assert!( 1 % 2 == 1);
242+ * assert!( 1 % -2 == 1);
243+ * assert!(-1 % 2 == -1);
244+ * assert!(-1 % -2 == -1);
245+ * ~~~
246+ */
208247 #[inline(always)]
209248 fn rem(&self, other: &T) -> T { *self % *other }
210249}
@@ -247,6 +286,123 @@ impl Signed for T {
247286 fn is_negative(&self) -> bool { *self < 0 }
248287}
249288
289+ impl Natural for T {
290+ /**
291+ * Floored integer division
292+ *
293+ * # Examples
294+ *
295+ * ~~~
296+ * assert!(( 8).div( 3) == 2);
297+ * assert!(( 8).div(-3) == -3);
298+ * assert!((-8).div( 3) == -3);
299+ * assert!((-8).div(-3) == 2);
300+ *
301+ * assert!(( 1).div( 2) == 0);
302+ * assert!(( 1).div(-2) == -1);
303+ * assert!((-1).div( 2) == -1);
304+ * assert!((-1).div(-2) == 0);
305+ * ~~~
306+ */
307+ #[inline(always)]
308+ fn div(&self, other: T) -> T {
309+ // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
310+ // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
311+ match self.quot_rem(other) {
312+ (q, r) if (r > 0 && other < 0)
313+ || (r < 0 && other > 0) => q - 1,
314+ (q, _) => q,
315+ }
316+ }
317+
318+ /**
319+ * Integer modulo, satisfying:
320+ *
321+ * ~~~
322+ * assert!(n.div(d) * d + n.modulo(d) == n)
323+ * ~~~
324+ *
325+ * # Examples
326+ *
327+ * ~~~
328+ * assert!(( 8).modulo( 3) == 2);
329+ * assert!(( 8).modulo(-3) == -1);
330+ * assert!((-8).modulo( 3) == 1);
331+ * assert!((-8).modulo(-3) == -2);
332+ *
333+ * assert!(( 1).modulo( 2) == 1);
334+ * assert!(( 1).modulo(-2) == -1);
335+ * assert!((-1).modulo( 2) == 1);
336+ * assert!((-1).modulo(-2) == -1);
337+ * ~~~
338+ */
339+ #[inline(always)]
340+ fn modulo(&self, other: T) -> T {
341+ // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
342+ // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
343+ match *self % other {
344+ r if (r > 0 && other < 0)
345+ || (r < 0 && other > 0) => r + other,
346+ r => r,
347+ }
348+ }
349+
350+ /// Calculates `div` and `modulo` simultaneously
351+ #[inline(always)]
352+ fn div_mod(&self, other: T) -> (T,T) {
353+ // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
354+ // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
355+ match self.quot_rem(other) {
356+ (q, r) if (r > 0 && other < 0)
357+ || (r < 0 && other > 0) => (q - 1, r + other),
358+ (q, r) => (q, r),
359+ }
360+ }
361+
362+ /// Calculates `quot` (`\` ) and `rem` (`%`) simultaneously
363+ #[inline(always)]
364+ fn quot_rem(&self, other: T) -> (T,T) {
365+ (*self / other, *self % other)
366+ }
367+
368+ /**
369+ * Calculates the Greatest Common Divisor (GCD) of the number and `other`
370+ *
371+ * The result is always positive
372+ */
373+ #[inline(always)]
374+ fn gcd(&self, other: T) -> T {
375+ // Use Euclid's algorithm
376+ let mut m = *self, n = other;
377+ while m != 0 {
378+ let temp = m;
379+ m = n % temp;
380+ n = temp;
381+ }
382+ n.abs()
383+ }
384+
385+ /**
386+ * Calculates the Lowest Common Multiple (LCM) of the number and `other`
387+ */
388+ #[inline(always)]
389+ fn lcm(&self, other: T) -> T {
390+ ((*self * other) / self.gcd(other)).abs() // should not have to recaluculate abs
391+ }
392+
393+ /// Returns `true` if the number can be divided by `other` without leaving a remainder
394+ #[inline(always)]
395+ fn divisible_by(&self, other: T) -> bool { *self % other == 0 }
396+
397+ /// Returns `true` if the number is divisible by `2`
398+ #[inline(always)]
399+ fn is_even(&self) -> bool { self.divisible_by(2) }
400+
401+ /// Returns `true` if the number is not divisible by `2`
402+ #[inline(always)]
403+ fn is_odd(&self) -> bool { !self.is_even() }
404+ }
405+
250406#[cfg(notest)]
251407impl BitOr<T,T> for T {
252408 #[inline(always)]
@@ -388,6 +544,95 @@ mod tests {
388544 assert!((-1 as T).is_negative());
389545 }
390546
547+ /**
548+ * Checks that the division rule holds for:
549+ *
550+ * - `n`: numerator (dividend)
551+ * - `d`: denominator (divisor)
552+ * - `qr`: quotient and remainder
553+ */
554+ #[cfg(test)]
555+ fn test_division_rule(nd: (T,T), qr: (T,T)) {
556+ let (n,d) = nd,
557+ (q,r) = qr;
558+
559+ assert_eq!(d * q + r, n);
560+ }
561+
562+ #[test]
563+ fn test_quot_rem() {
564+ fn test_nd_qr(nd: (T,T), qr: (T,T)) {
565+ let (n,d) = nd;
566+ let separate_quot_rem = (n / d, n % d);
567+ let combined_quot_rem = n.quot_rem(d);
568+
569+ assert_eq!(separate_quot_rem, qr);
570+ assert_eq!(combined_quot_rem, qr);
571+
572+ test_division_rule(nd, separate_quot_rem);
573+ test_division_rule(nd, combined_quot_rem);
574+ }
575+
576+ test_nd_qr(( 8, 3), ( 2, 2));
577+ test_nd_qr(( 8, -3), (-2, 2));
578+ test_nd_qr((-8, 3), (-2, -2));
579+ test_nd_qr((-8, -3), ( 2, -2));
580+
581+ test_nd_qr(( 1, 2), ( 0, 1));
582+ test_nd_qr(( 1, -2), ( 0, 1));
583+ test_nd_qr((-1, 2), ( 0, -1));
584+ test_nd_qr((-1, -2), ( 0, -1));
585+ }
586+
587+ #[test]
588+ fn test_div_mod() {
589+ fn test_nd_dm(nd: (T,T), dm: (T,T)) {
590+ let (n,d) = nd;
591+ let separate_div_mod = (n.div(d), n.modulo(d));
592+ let combined_div_mod = n.div_mod(d);
593+
594+ assert_eq!(separate_div_mod, dm);
595+ assert_eq!(combined_div_mod, dm);
596+
597+ test_division_rule(nd, separate_div_mod);
598+ test_division_rule(nd, combined_div_mod);
599+ }
600+
601+ test_nd_dm(( 8, 3), ( 2, 2));
602+ test_nd_dm(( 8, -3), (-3, -1));
603+ test_nd_dm((-8, 3), (-3, 1));
604+ test_nd_dm((-8, -3), ( 2, -2));
605+
606+ test_nd_dm(( 1, 2), ( 0, 1));
607+ test_nd_dm(( 1, -2), (-1, -1));
608+ test_nd_dm((-1, 2), (-1, 1));
609+ test_nd_dm((-1, -2), ( 0, -1));
610+ }
611+
612+ #[test]
613+ fn test_gcd() {
614+ assert_eq!((10 as T).gcd(2), 2 as T);
615+ assert_eq!((10 as T).gcd(3), 1 as T);
616+ assert_eq!((0 as T).gcd(3), 3 as T);
617+ assert_eq!((3 as T).gcd(3), 3 as T);
618+ assert_eq!((56 as T).gcd(42), 14 as T);
619+ assert_eq!((3 as T).gcd(-3), 3 as T);
620+ assert_eq!((-6 as T).gcd(3), 3 as T);
621+ assert_eq!((-4 as T).gcd(-2), 2 as T);
622+ }
623+
624+ #[test]
625+ fn test_lcm() {
626+ assert_eq!((1 as T).lcm(0), 0 as T);
627+ assert_eq!((0 as T).lcm(1), 0 as T);
628+ assert_eq!((1 as T).lcm(1), 1 as T);
629+ assert_eq!((-1 as T).lcm(1), 1 as T);
630+ assert_eq!((1 as T).lcm(-1), 1 as T);
631+ assert_eq!((-1 as T).lcm(-1), 1 as T);
632+ assert_eq!((8 as T).lcm(9), 72 as T);
633+ assert_eq!((11 as T).lcm(5), 55 as T);
634+ }
635+
391636 #[test]
392637 fn test_bitwise_ops() {
393638 assert_eq!(0b1110 as T, (0b1100 as T).bitor(&(0b1010 as T)));
0 commit comments