integer.rs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  1. // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
  2. // file at the top-level directory of this distribution and at
  3. // http://rust-lang.org/COPYRIGHT.
  4. //
  5. // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
  6. // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
  7. // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
  8. // option. This file may not be copied, modified, or distributed
  9. // except according to those terms.
  10. //! Integer trait and functions.
  11. use {Num, Signed};
  12. pub trait Integer
  13. : Sized
  14. + Num
  15. + PartialOrd + Ord + Eq
  16. {
  17. /// Floored integer division.
  18. ///
  19. /// # Examples
  20. ///
  21. /// ~~~
  22. /// # use num::Integer;
  23. /// assert!(( 8).div_floor(& 3) == 2);
  24. /// assert!(( 8).div_floor(&-3) == -3);
  25. /// assert!((-8).div_floor(& 3) == -3);
  26. /// assert!((-8).div_floor(&-3) == 2);
  27. ///
  28. /// assert!(( 1).div_floor(& 2) == 0);
  29. /// assert!(( 1).div_floor(&-2) == -1);
  30. /// assert!((-1).div_floor(& 2) == -1);
  31. /// assert!((-1).div_floor(&-2) == 0);
  32. /// ~~~
  33. fn div_floor(&self, other: &Self) -> Self;
  34. /// Floored integer modulo, satisfying:
  35. ///
  36. /// ~~~
  37. /// # use num::Integer;
  38. /// # let n = 1; let d = 1;
  39. /// assert!(n.div_floor(&d) * d + n.mod_floor(&d) == n)
  40. /// ~~~
  41. ///
  42. /// # Examples
  43. ///
  44. /// ~~~
  45. /// # use num::Integer;
  46. /// assert!(( 8).mod_floor(& 3) == 2);
  47. /// assert!(( 8).mod_floor(&-3) == -1);
  48. /// assert!((-8).mod_floor(& 3) == 1);
  49. /// assert!((-8).mod_floor(&-3) == -2);
  50. ///
  51. /// assert!(( 1).mod_floor(& 2) == 1);
  52. /// assert!(( 1).mod_floor(&-2) == -1);
  53. /// assert!((-1).mod_floor(& 2) == 1);
  54. /// assert!((-1).mod_floor(&-2) == -1);
  55. /// ~~~
  56. fn mod_floor(&self, other: &Self) -> Self;
  57. /// Greatest Common Divisor (GCD).
  58. ///
  59. /// # Examples
  60. ///
  61. /// ~~~
  62. /// # use num::Integer;
  63. /// assert_eq!(6.gcd(&8), 2);
  64. /// assert_eq!(7.gcd(&3), 1);
  65. /// ~~~
  66. fn gcd(&self, other: &Self) -> Self;
  67. /// Lowest Common Multiple (LCM).
  68. ///
  69. /// # Examples
  70. ///
  71. /// ~~~
  72. /// # use num::Integer;
  73. /// assert_eq!(7.lcm(&3), 21);
  74. /// assert_eq!(2.lcm(&4), 4);
  75. /// ~~~
  76. fn lcm(&self, other: &Self) -> Self;
  77. /// Deprecated, use `is_multiple_of` instead.
  78. fn divides(&self, other: &Self) -> bool;
  79. /// Returns `true` if `other` is a multiple of `self`.
  80. ///
  81. /// # Examples
  82. ///
  83. /// ~~~
  84. /// # use num::Integer;
  85. /// assert_eq!(9.is_multiple_of(&3), true);
  86. /// assert_eq!(3.is_multiple_of(&9), false);
  87. /// ~~~
  88. fn is_multiple_of(&self, other: &Self) -> bool;
  89. /// Returns `true` if the number is even.
  90. ///
  91. /// # Examples
  92. ///
  93. /// ~~~
  94. /// # use num::Integer;
  95. /// assert_eq!(3.is_even(), false);
  96. /// assert_eq!(4.is_even(), true);
  97. /// ~~~
  98. fn is_even(&self) -> bool;
  99. /// Returns `true` if the number is odd.
  100. ///
  101. /// # Examples
  102. ///
  103. /// ~~~
  104. /// # use num::Integer;
  105. /// assert_eq!(3.is_odd(), true);
  106. /// assert_eq!(4.is_odd(), false);
  107. /// ~~~
  108. fn is_odd(&self) -> bool;
  109. /// Simultaneous truncated integer division and modulus.
  110. /// Returns `(quotient, remainder)`.
  111. ///
  112. /// # Examples
  113. ///
  114. /// ~~~
  115. /// # use num::Integer;
  116. /// assert_eq!(( 8).div_rem( &3), ( 2, 2));
  117. /// assert_eq!(( 8).div_rem(&-3), (-2, 2));
  118. /// assert_eq!((-8).div_rem( &3), (-2, -2));
  119. /// assert_eq!((-8).div_rem(&-3), ( 2, -2));
  120. ///
  121. /// assert_eq!(( 1).div_rem( &2), ( 0, 1));
  122. /// assert_eq!(( 1).div_rem(&-2), ( 0, 1));
  123. /// assert_eq!((-1).div_rem( &2), ( 0, -1));
  124. /// assert_eq!((-1).div_rem(&-2), ( 0, -1));
  125. /// ~~~
  126. #[inline]
  127. fn div_rem(&self, other: &Self) -> (Self, Self);
  128. /// Simultaneous floored integer division and modulus.
  129. /// Returns `(quotient, remainder)`.
  130. ///
  131. /// # Examples
  132. ///
  133. /// ~~~
  134. /// # use num::Integer;
  135. /// assert_eq!(( 8).div_mod_floor( &3), ( 2, 2));
  136. /// assert_eq!(( 8).div_mod_floor(&-3), (-3, -1));
  137. /// assert_eq!((-8).div_mod_floor( &3), (-3, 1));
  138. /// assert_eq!((-8).div_mod_floor(&-3), ( 2, -2));
  139. ///
  140. /// assert_eq!(( 1).div_mod_floor( &2), ( 0, 1));
  141. /// assert_eq!(( 1).div_mod_floor(&-2), (-1, -1));
  142. /// assert_eq!((-1).div_mod_floor( &2), (-1, 1));
  143. /// assert_eq!((-1).div_mod_floor(&-2), ( 0, -1));
  144. /// ~~~
  145. fn div_mod_floor(&self, other: &Self) -> (Self, Self) {
  146. (self.div_floor(other), self.mod_floor(other))
  147. }
  148. }
  149. /// Simultaneous integer division and modulus
  150. #[inline] pub fn div_rem<T: Integer>(x: T, y: T) -> (T, T) { x.div_rem(&y) }
  151. /// Floored integer division
  152. #[inline] pub fn div_floor<T: Integer>(x: T, y: T) -> T { x.div_floor(&y) }
  153. /// Floored integer modulus
  154. #[inline] pub fn mod_floor<T: Integer>(x: T, y: T) -> T { x.mod_floor(&y) }
  155. /// Simultaneous floored integer division and modulus
  156. #[inline] pub fn div_mod_floor<T: Integer>(x: T, y: T) -> (T, T) { x.div_mod_floor(&y) }
  157. /// Calculates the Greatest Common Divisor (GCD) of the number and `other`. The
  158. /// result is always positive.
  159. #[inline(always)] pub fn gcd<T: Integer>(x: T, y: T) -> T { x.gcd(&y) }
  160. /// Calculates the Lowest Common Multiple (LCM) of the number and `other`.
  161. #[inline(always)] pub fn lcm<T: Integer>(x: T, y: T) -> T { x.lcm(&y) }
  162. macro_rules! impl_integer_for_isize {
  163. ($T:ty, $test_mod:ident) => (
  164. impl Integer for $T {
  165. /// Floored integer division
  166. #[inline]
  167. fn div_floor(&self, other: &$T) -> $T {
  168. // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
  169. // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
  170. match self.div_rem(other) {
  171. (d, r) if (r > 0 && *other < 0)
  172. || (r < 0 && *other > 0) => d - 1,
  173. (d, _) => d,
  174. }
  175. }
  176. /// Floored integer modulo
  177. #[inline]
  178. fn mod_floor(&self, other: &$T) -> $T {
  179. // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
  180. // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
  181. match *self % *other {
  182. r if (r > 0 && *other < 0)
  183. || (r < 0 && *other > 0) => r + *other,
  184. r => r,
  185. }
  186. }
  187. /// Calculates `div_floor` and `mod_floor` simultaneously
  188. #[inline]
  189. fn div_mod_floor(&self, other: &$T) -> ($T,$T) {
  190. // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
  191. // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
  192. match self.div_rem(other) {
  193. (d, r) if (r > 0 && *other < 0)
  194. || (r < 0 && *other > 0) => (d - 1, r + *other),
  195. (d, r) => (d, r),
  196. }
  197. }
  198. /// Calculates the Greatest Common Divisor (GCD) of the number and
  199. /// `other`. The result is always positive.
  200. #[inline]
  201. fn gcd(&self, other: &$T) -> $T {
  202. // Use Stein's algorithm
  203. let mut m = *self;
  204. let mut n = *other;
  205. if m == 0 || n == 0 { return (m | n).abs() }
  206. // find common factors of 2
  207. let shift = (m | n).trailing_zeros();
  208. // The algorithm needs positive numbers, but the minimum value
  209. // can't be represented as a positive one.
  210. // It's also a power of two, so the gcd can be
  211. // calculated by bitshifting in that case
  212. // Assuming two's complement, the number created by the shift
  213. // is positive for all numbers except gcd = abs(min value)
  214. // The call to .abs() causes a panic in debug mode
  215. if m == <$T>::min_value() || n == <$T>::min_value() {
  216. return (1 << shift).abs()
  217. }
  218. // guaranteed to be positive now, rest like unsigned algorithm
  219. m = m.abs();
  220. n = n.abs();
  221. // divide n and m by 2 until odd
  222. // m inside loop
  223. n >>= n.trailing_zeros();
  224. while m != 0 {
  225. m >>= m.trailing_zeros();
  226. if n > m { ::std::mem::swap(&mut n, &mut m) }
  227. m -= n;
  228. }
  229. n << shift
  230. }
  231. /// Calculates the Lowest Common Multiple (LCM) of the number and
  232. /// `other`.
  233. #[inline]
  234. fn lcm(&self, other: &$T) -> $T {
  235. // should not have to recalculate abs
  236. ((*self * *other) / self.gcd(other)).abs()
  237. }
  238. /// Deprecated, use `is_multiple_of` instead.
  239. #[inline]
  240. fn divides(&self, other: &$T) -> bool { return self.is_multiple_of(other); }
  241. /// Returns `true` if the number is a multiple of `other`.
  242. #[inline]
  243. fn is_multiple_of(&self, other: &$T) -> bool { *self % *other == 0 }
  244. /// Returns `true` if the number is divisible by `2`
  245. #[inline]
  246. fn is_even(&self) -> bool { (*self) & 1 == 0 }
  247. /// Returns `true` if the number is not divisible by `2`
  248. #[inline]
  249. fn is_odd(&self) -> bool { !self.is_even() }
  250. /// Simultaneous truncated integer division and modulus.
  251. #[inline]
  252. fn div_rem(&self, other: &$T) -> ($T, $T) {
  253. (*self / *other, *self % *other)
  254. }
  255. }
  256. #[cfg(test)]
  257. mod $test_mod {
  258. use Integer;
  259. /// Checks that the division rule holds for:
  260. ///
  261. /// - `n`: numerator (dividend)
  262. /// - `d`: denominator (divisor)
  263. /// - `qr`: quotient and remainder
  264. #[cfg(test)]
  265. fn test_division_rule((n,d): ($T,$T), (q,r): ($T,$T)) {
  266. assert_eq!(d * q + r, n);
  267. }
  268. #[test]
  269. fn test_div_rem() {
  270. fn test_nd_dr(nd: ($T,$T), qr: ($T,$T)) {
  271. let (n,d) = nd;
  272. let separate_div_rem = (n / d, n % d);
  273. let combined_div_rem = n.div_rem(&d);
  274. assert_eq!(separate_div_rem, qr);
  275. assert_eq!(combined_div_rem, qr);
  276. test_division_rule(nd, separate_div_rem);
  277. test_division_rule(nd, combined_div_rem);
  278. }
  279. test_nd_dr(( 8, 3), ( 2, 2));
  280. test_nd_dr(( 8, -3), (-2, 2));
  281. test_nd_dr((-8, 3), (-2, -2));
  282. test_nd_dr((-8, -3), ( 2, -2));
  283. test_nd_dr(( 1, 2), ( 0, 1));
  284. test_nd_dr(( 1, -2), ( 0, 1));
  285. test_nd_dr((-1, 2), ( 0, -1));
  286. test_nd_dr((-1, -2), ( 0, -1));
  287. }
  288. #[test]
  289. fn test_div_mod_floor() {
  290. fn test_nd_dm(nd: ($T,$T), dm: ($T,$T)) {
  291. let (n,d) = nd;
  292. let separate_div_mod_floor = (n.div_floor(&d), n.mod_floor(&d));
  293. let combined_div_mod_floor = n.div_mod_floor(&d);
  294. assert_eq!(separate_div_mod_floor, dm);
  295. assert_eq!(combined_div_mod_floor, dm);
  296. test_division_rule(nd, separate_div_mod_floor);
  297. test_division_rule(nd, combined_div_mod_floor);
  298. }
  299. test_nd_dm(( 8, 3), ( 2, 2));
  300. test_nd_dm(( 8, -3), (-3, -1));
  301. test_nd_dm((-8, 3), (-3, 1));
  302. test_nd_dm((-8, -3), ( 2, -2));
  303. test_nd_dm(( 1, 2), ( 0, 1));
  304. test_nd_dm(( 1, -2), (-1, -1));
  305. test_nd_dm((-1, 2), (-1, 1));
  306. test_nd_dm((-1, -2), ( 0, -1));
  307. }
  308. #[test]
  309. fn test_gcd() {
  310. assert_eq!((10 as $T).gcd(&2), 2 as $T);
  311. assert_eq!((10 as $T).gcd(&3), 1 as $T);
  312. assert_eq!((0 as $T).gcd(&3), 3 as $T);
  313. assert_eq!((3 as $T).gcd(&3), 3 as $T);
  314. assert_eq!((56 as $T).gcd(&42), 14 as $T);
  315. assert_eq!((3 as $T).gcd(&-3), 3 as $T);
  316. assert_eq!((-6 as $T).gcd(&3), 3 as $T);
  317. assert_eq!((-4 as $T).gcd(&-2), 2 as $T);
  318. }
  319. #[test]
  320. fn test_gcd_cmp_with_euclidean() {
  321. fn euclidean_gcd(mut m: $T, mut n: $T) -> $T {
  322. while m != 0 {
  323. ::std::mem::swap(&mut m, &mut n);
  324. m %= n;
  325. }
  326. n.abs()
  327. }
  328. // gcd(-128, b) = 128 is not representable as positive value
  329. // for i8
  330. for i in -127..127 {
  331. for j in -127..127 {
  332. assert_eq!(euclidean_gcd(i,j), i.gcd(&j));
  333. }
  334. }
  335. // last value
  336. // FIXME: Use inclusive ranges for above loop when implemented
  337. let i = 127;
  338. for j in -127..127 {
  339. assert_eq!(euclidean_gcd(i,j), i.gcd(&j));
  340. }
  341. assert_eq!(127.gcd(&127), 127);
  342. }
  343. #[test]
  344. fn test_gcd_min_val() {
  345. let min = <$T>::min_value();
  346. let max = <$T>::max_value();
  347. let max_pow2 = max / 2 + 1;
  348. assert_eq!(min.gcd(&max), 1 as $T);
  349. assert_eq!(max.gcd(&min), 1 as $T);
  350. assert_eq!(min.gcd(&max_pow2), max_pow2);
  351. assert_eq!(max_pow2.gcd(&min), max_pow2);
  352. assert_eq!(min.gcd(&42), 2 as $T);
  353. assert_eq!((42 as $T).gcd(&min), 2 as $T);
  354. }
  355. #[test]
  356. #[should_panic]
  357. fn test_gcd_min_val_min_val() {
  358. let min = <$T>::min_value();
  359. assert!(min.gcd(&min) >= 0);
  360. }
  361. #[test]
  362. #[should_panic]
  363. fn test_gcd_min_val_0() {
  364. let min = <$T>::min_value();
  365. assert!(min.gcd(&0) >= 0);
  366. }
  367. #[test]
  368. #[should_panic]
  369. fn test_gcd_0_min_val() {
  370. let min = <$T>::min_value();
  371. assert!((0 as $T).gcd(&min) >= 0);
  372. }
  373. #[test]
  374. fn test_lcm() {
  375. assert_eq!((1 as $T).lcm(&0), 0 as $T);
  376. assert_eq!((0 as $T).lcm(&1), 0 as $T);
  377. assert_eq!((1 as $T).lcm(&1), 1 as $T);
  378. assert_eq!((-1 as $T).lcm(&1), 1 as $T);
  379. assert_eq!((1 as $T).lcm(&-1), 1 as $T);
  380. assert_eq!((-1 as $T).lcm(&-1), 1 as $T);
  381. assert_eq!((8 as $T).lcm(&9), 72 as $T);
  382. assert_eq!((11 as $T).lcm(&5), 55 as $T);
  383. }
  384. #[test]
  385. fn test_even() {
  386. assert_eq!((-4 as $T).is_even(), true);
  387. assert_eq!((-3 as $T).is_even(), false);
  388. assert_eq!((-2 as $T).is_even(), true);
  389. assert_eq!((-1 as $T).is_even(), false);
  390. assert_eq!((0 as $T).is_even(), true);
  391. assert_eq!((1 as $T).is_even(), false);
  392. assert_eq!((2 as $T).is_even(), true);
  393. assert_eq!((3 as $T).is_even(), false);
  394. assert_eq!((4 as $T).is_even(), true);
  395. }
  396. #[test]
  397. fn test_odd() {
  398. assert_eq!((-4 as $T).is_odd(), false);
  399. assert_eq!((-3 as $T).is_odd(), true);
  400. assert_eq!((-2 as $T).is_odd(), false);
  401. assert_eq!((-1 as $T).is_odd(), true);
  402. assert_eq!((0 as $T).is_odd(), false);
  403. assert_eq!((1 as $T).is_odd(), true);
  404. assert_eq!((2 as $T).is_odd(), false);
  405. assert_eq!((3 as $T).is_odd(), true);
  406. assert_eq!((4 as $T).is_odd(), false);
  407. }
  408. }
  409. )
  410. }
  411. impl_integer_for_isize!(i8, test_integer_i8);
  412. impl_integer_for_isize!(i16, test_integer_i16);
  413. impl_integer_for_isize!(i32, test_integer_i32);
  414. impl_integer_for_isize!(i64, test_integer_i64);
  415. impl_integer_for_isize!(isize, test_integer_isize);
  416. macro_rules! impl_integer_for_usize {
  417. ($T:ty, $test_mod:ident) => (
  418. impl Integer for $T {
  419. /// Unsigned integer division. Returns the same result as `div` (`/`).
  420. #[inline]
  421. fn div_floor(&self, other: &$T) -> $T { *self / *other }
  422. /// Unsigned integer modulo operation. Returns the same result as `rem` (`%`).
  423. #[inline]
  424. fn mod_floor(&self, other: &$T) -> $T { *self % *other }
  425. /// Calculates the Greatest Common Divisor (GCD) of the number and `other`
  426. #[inline]
  427. fn gcd(&self, other: &$T) -> $T {
  428. // Use Stein's algorithm
  429. let mut m = *self;
  430. let mut n = *other;
  431. if m == 0 || n == 0 { return m | n }
  432. // find common factors of 2
  433. let shift = (m | n).trailing_zeros();
  434. // divide n and m by 2 until odd
  435. // m inside loop
  436. n >>= n.trailing_zeros();
  437. while m != 0 {
  438. m >>= m.trailing_zeros();
  439. if n > m { ::std::mem::swap(&mut n, &mut m) }
  440. m -= n;
  441. }
  442. n << shift
  443. }
  444. /// Calculates the Lowest Common Multiple (LCM) of the number and `other`.
  445. #[inline]
  446. fn lcm(&self, other: &$T) -> $T {
  447. (*self * *other) / self.gcd(other)
  448. }
  449. /// Deprecated, use `is_multiple_of` instead.
  450. #[inline]
  451. fn divides(&self, other: &$T) -> bool { return self.is_multiple_of(other); }
  452. /// Returns `true` if the number is a multiple of `other`.
  453. #[inline]
  454. fn is_multiple_of(&self, other: &$T) -> bool { *self % *other == 0 }
  455. /// Returns `true` if the number is divisible by `2`.
  456. #[inline]
  457. fn is_even(&self) -> bool { (*self) & 1 == 0 }
  458. /// Returns `true` if the number is not divisible by `2`.
  459. #[inline]
  460. fn is_odd(&self) -> bool { !(*self).is_even() }
  461. /// Simultaneous truncated integer division and modulus.
  462. #[inline]
  463. fn div_rem(&self, other: &$T) -> ($T, $T) {
  464. (*self / *other, *self % *other)
  465. }
  466. }
  467. #[cfg(test)]
  468. mod $test_mod {
  469. use Integer;
  470. #[test]
  471. fn test_div_mod_floor() {
  472. assert_eq!((10 as $T).div_floor(&(3 as $T)), 3 as $T);
  473. assert_eq!((10 as $T).mod_floor(&(3 as $T)), 1 as $T);
  474. assert_eq!((10 as $T).div_mod_floor(&(3 as $T)), (3 as $T, 1 as $T));
  475. assert_eq!((5 as $T).div_floor(&(5 as $T)), 1 as $T);
  476. assert_eq!((5 as $T).mod_floor(&(5 as $T)), 0 as $T);
  477. assert_eq!((5 as $T).div_mod_floor(&(5 as $T)), (1 as $T, 0 as $T));
  478. assert_eq!((3 as $T).div_floor(&(7 as $T)), 0 as $T);
  479. assert_eq!((3 as $T).mod_floor(&(7 as $T)), 3 as $T);
  480. assert_eq!((3 as $T).div_mod_floor(&(7 as $T)), (0 as $T, 3 as $T));
  481. }
  482. #[test]
  483. fn test_gcd() {
  484. assert_eq!((10 as $T).gcd(&2), 2 as $T);
  485. assert_eq!((10 as $T).gcd(&3), 1 as $T);
  486. assert_eq!((0 as $T).gcd(&3), 3 as $T);
  487. assert_eq!((3 as $T).gcd(&3), 3 as $T);
  488. assert_eq!((56 as $T).gcd(&42), 14 as $T);
  489. }
  490. #[test]
  491. fn test_gcd_cmp_with_euclidean() {
  492. fn euclidean_gcd(mut m: $T, mut n: $T) -> $T {
  493. while m != 0 {
  494. ::std::mem::swap(&mut m, &mut n);
  495. m %= n;
  496. }
  497. n
  498. }
  499. for i in 0..255 {
  500. for j in 0..255 {
  501. assert_eq!(euclidean_gcd(i,j), i.gcd(&j));
  502. }
  503. }
  504. // last value
  505. // FIXME: Use inclusive ranges for above loop when implemented
  506. let i = 255;
  507. for j in 0..255 {
  508. assert_eq!(euclidean_gcd(i,j), i.gcd(&j));
  509. }
  510. assert_eq!(255.gcd(&255), 255);
  511. }
  512. #[test]
  513. fn test_lcm() {
  514. assert_eq!((1 as $T).lcm(&0), 0 as $T);
  515. assert_eq!((0 as $T).lcm(&1), 0 as $T);
  516. assert_eq!((1 as $T).lcm(&1), 1 as $T);
  517. assert_eq!((8 as $T).lcm(&9), 72 as $T);
  518. assert_eq!((11 as $T).lcm(&5), 55 as $T);
  519. assert_eq!((15 as $T).lcm(&17), 255 as $T);
  520. }
  521. #[test]
  522. fn test_is_multiple_of() {
  523. assert!((6 as $T).is_multiple_of(&(6 as $T)));
  524. assert!((6 as $T).is_multiple_of(&(3 as $T)));
  525. assert!((6 as $T).is_multiple_of(&(1 as $T)));
  526. }
  527. #[test]
  528. fn test_even() {
  529. assert_eq!((0 as $T).is_even(), true);
  530. assert_eq!((1 as $T).is_even(), false);
  531. assert_eq!((2 as $T).is_even(), true);
  532. assert_eq!((3 as $T).is_even(), false);
  533. assert_eq!((4 as $T).is_even(), true);
  534. }
  535. #[test]
  536. fn test_odd() {
  537. assert_eq!((0 as $T).is_odd(), false);
  538. assert_eq!((1 as $T).is_odd(), true);
  539. assert_eq!((2 as $T).is_odd(), false);
  540. assert_eq!((3 as $T).is_odd(), true);
  541. assert_eq!((4 as $T).is_odd(), false);
  542. }
  543. }
  544. )
  545. }
  546. impl_integer_for_usize!(u8, test_integer_u8);
  547. impl_integer_for_usize!(u16, test_integer_u16);
  548. impl_integer_for_usize!(u32, test_integer_u32);
  549. impl_integer_for_usize!(u64, test_integer_u64);
  550. impl_integer_for_usize!(usize, test_integer_usize);