]> git.lizzy.rs Git - rust.git/blob - src/libstd/num/int_macros.rs
9842a570d7ea7e3c405245d5af9f9e4a17857bf7
[rust.git] / src / libstd / num / int_macros.rs
1 // Copyright 2012 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
11 // FIXME(#4375): this shouldn't have to be a nested module named 'generated'
12
13 #[macro_escape];
14
15 macro_rules! int_module (($T:ty, $bits:expr) => (mod generated {
16
17 #[allow(non_uppercase_statics)];
18
19 use num::{ToStrRadix, FromStrRadix};
20 use num::{Zero, One, strconv};
21 use prelude::*;
22 use str;
23
24 pub use cmp::{min, max};
25
26 pub static bits : uint = $bits;
27 pub static bytes : uint = ($bits / 8);
28
29 pub static min_value: $T = (-1 as $T) << (bits - 1);
30 pub static max_value: $T = min_value - 1 as $T;
31
32 enum Range { Closed, HalfOpen }
33
34 #[inline]
35 ///
36 /// Iterate through a range with a given step value.
37 ///
38 /// Let `term` denote the closed interval `[stop-step,stop]` if `r` is Closed;
39 /// otherwise `term` denotes the half-open interval `[stop-step,stop)`.
40 /// Iterates through the range `[x_0, x_1, ..., x_n]` where
41 /// `x_j == start + step*j`, and `x_n` lies in the interval `term`.
42 ///
43 /// If no such nonnegative integer `n` exists, then the iteration range
44 /// is empty.
45 ///
46 fn range_step_core(start: $T, stop: $T, step: $T, r: Range, it: &fn($T) -> bool) -> bool {
47     let mut i = start;
48     if step == 0 {
49         fail!(~"range_step called with step == 0");
50     } else if step == (1 as $T) { // elide bounds check to tighten loop
51         while i < stop {
52             if !it(i) { return false; }
53             // no need for overflow check;
54             // cannot have i + 1 > max_value because i < stop <= max_value
55             i += (1 as $T);
56         }
57     } else if step == (-1 as $T) { // elide bounds check to tighten loop
58         while i > stop {
59             if !it(i) { return false; }
60             // no need for underflow check;
61             // cannot have i - 1 < min_value because i > stop >= min_value
62             i -= (1 as $T);
63         }
64     } else if step > 0 { // ascending
65         while i < stop {
66             if !it(i) { return false; }
67             // avoiding overflow. break if i + step > max_value
68             if i > max_value - step { return true; }
69             i += step;
70         }
71     } else { // descending
72         while i > stop {
73             if !it(i) { return false; }
74             // avoiding underflow. break if i + step < min_value
75             if i < min_value - step { return true; }
76             i += step;
77         }
78     }
79     match r {
80         HalfOpen => return true,
81         Closed => return (i != stop || it(i))
82     }
83 }
84
85 #[inline]
86 ///
87 /// Iterate through the range [`start`..`stop`) with a given step value.
88 ///
89 /// Iterates through the range `[x_0, x_1, ..., x_n]` where
90 /// * `x_i == start + step*i`, and
91 /// * `n` is the greatest nonnegative integer such that `x_n < stop`
92 ///
93 /// (If no such `n` exists, then the iteration range is empty.)
94 ///
95 /// # Arguments
96 ///
97 /// * `start` - lower bound, inclusive
98 /// * `stop` - higher bound, exclusive
99 ///
100 /// # Examples
101 /// ~~~
102 /// let mut sum = 0;
103 /// for int::range(1, 5) |i| {
104 ///     sum += i;
105 /// }
106 /// assert!(sum == 10);
107 /// ~~~
108 ///
109 pub fn range_step(start: $T, stop: $T, step: $T, it: &fn($T) -> bool) -> bool {
110     range_step_core(start, stop, step, HalfOpen, it)
111 }
112
113 #[inline]
114 ///
115 /// Iterate through a range with a given step value.
116 ///
117 /// Iterates through the range `[x_0, x_1, ..., x_n]` where
118 /// `x_i == start + step*i` and `x_n <= last < step + x_n`.
119 ///
120 /// (If no such nonnegative integer `n` exists, then the iteration
121 ///  range is empty.)
122 ///
123 pub fn range_step_inclusive(start: $T, last: $T, step: $T, it: &fn($T) -> bool) -> bool {
124     range_step_core(start, last, step, Closed, it)
125 }
126
127
128 #[inline]
129 /// Iterate over the range (`hi`..`lo`]
130 pub fn range_rev(hi: $T, lo: $T, it: &fn($T) -> bool) -> bool {
131     if hi == min_value { return true; }
132     range_step_inclusive(hi-1, lo, -1 as $T, it)
133 }
134
135 impl Num for $T {}
136
137 #[cfg(not(test))]
138 impl Ord for $T {
139     #[inline]
140     fn lt(&self, other: &$T) -> bool { return (*self) < (*other); }
141     #[inline]
142     fn le(&self, other: &$T) -> bool { return (*self) <= (*other); }
143     #[inline]
144     fn ge(&self, other: &$T) -> bool { return (*self) >= (*other); }
145     #[inline]
146     fn gt(&self, other: &$T) -> bool { return (*self) > (*other); }
147 }
148
149 #[cfg(not(test))]
150 impl Eq for $T {
151     #[inline]
152     fn eq(&self, other: &$T) -> bool { return (*self) == (*other); }
153     #[inline]
154     fn ne(&self, other: &$T) -> bool { return (*self) != (*other); }
155 }
156
157 impl Orderable for $T {
158     #[inline]
159     fn min(&self, other: &$T) -> $T {
160         if *self < *other { *self } else { *other }
161     }
162
163     #[inline]
164     fn max(&self, other: &$T) -> $T {
165         if *self > *other { *self } else { *other }
166     }
167
168     #[inline]
169     fn clamp(&self, mn: &$T, mx: &$T) -> $T {
170         if *self > *mx { *mx } else
171         if *self < *mn { *mn } else { *self }
172     }
173 }
174
175 impl Zero for $T {
176     #[inline]
177     fn zero() -> $T { 0 }
178
179     #[inline]
180     fn is_zero(&self) -> bool { *self == 0 }
181 }
182
183 impl One for $T {
184     #[inline]
185     fn one() -> $T { 1 }
186 }
187
188 #[cfg(not(test))]
189 impl Add<$T,$T> for $T {
190     #[inline]
191     fn add(&self, other: &$T) -> $T { *self + *other }
192 }
193
194 #[cfg(not(test))]
195 impl Sub<$T,$T> for $T {
196     #[inline]
197     fn sub(&self, other: &$T) -> $T { *self - *other }
198 }
199
200 #[cfg(not(test))]
201 impl Mul<$T,$T> for $T {
202     #[inline]
203     fn mul(&self, other: &$T) -> $T { *self * *other }
204 }
205
206 #[cfg(not(test))]
207 impl Div<$T,$T> for $T {
208     ///
209     /// Integer division, truncated towards 0. As this behaviour reflects the underlying
210     /// machine implementation it is more efficient than `Integer::div_floor`.
211     ///
212     /// # Examples
213     ///
214     /// ~~~
215     /// assert!( 8 /  3 ==  2);
216     /// assert!( 8 / -3 == -2);
217     /// assert!(-8 /  3 == -2);
218     /// assert!(-8 / -3 ==  2);
219
220     /// assert!( 1 /  2 ==  0);
221     /// assert!( 1 / -2 ==  0);
222     /// assert!(-1 /  2 ==  0);
223     /// assert!(-1 / -2 ==  0);
224     /// ~~~
225     ///
226     #[inline]
227     fn div(&self, other: &$T) -> $T { *self / *other }
228 }
229
230 #[cfg(not(test))]
231 impl Rem<$T,$T> for $T {
232     ///
233     /// Returns the integer remainder after division, satisfying:
234     ///
235     /// ~~~
236     /// assert!((n / d) * d + (n % d) == n)
237     /// ~~~
238     ///
239     /// # Examples
240     ///
241     /// ~~~
242     /// assert!( 8 %  3 ==  2);
243     /// assert!( 8 % -3 ==  2);
244     /// assert!(-8 %  3 == -2);
245     /// assert!(-8 % -3 == -2);
246
247     /// assert!( 1 %  2 ==  1);
248     /// assert!( 1 % -2 ==  1);
249     /// assert!(-1 %  2 == -1);
250     /// assert!(-1 % -2 == -1);
251     /// ~~~
252     ///
253     #[inline]
254     fn rem(&self, other: &$T) -> $T { *self % *other }
255 }
256
257 #[cfg(not(test))]
258 impl Neg<$T> for $T {
259     #[inline]
260     fn neg(&self) -> $T { -*self }
261 }
262
263 impl Signed for $T {
264     /// Computes the absolute value
265     #[inline]
266     fn abs(&self) -> $T {
267         if self.is_negative() { -*self } else { *self }
268     }
269
270     ///
271     /// The positive difference of two numbers. Returns `0` if the number is less than or
272     /// equal to `other`, otherwise the difference between`self` and `other` is returned.
273     ///
274     #[inline]
275     fn abs_sub(&self, other: &$T) -> $T {
276         if *self <= *other { 0 } else { *self - *other }
277     }
278
279     ///
280     /// # Returns
281     ///
282     /// - `0` if the number is zero
283     /// - `1` if the number is positive
284     /// - `-1` if the number is negative
285     ///
286     #[inline]
287     fn signum(&self) -> $T {
288         match *self {
289             n if n > 0 =>  1,
290             0          =>  0,
291             _          => -1,
292         }
293     }
294
295     /// Returns true if the number is positive
296     #[inline]
297     fn is_positive(&self) -> bool { *self > 0 }
298
299     /// Returns true if the number is negative
300     #[inline]
301     fn is_negative(&self) -> bool { *self < 0 }
302 }
303
304 impl Integer for $T {
305     ///
306     /// Floored integer division
307     ///
308     /// # Examples
309     ///
310     /// ~~~
311     /// assert!(( 8).div_floor( 3) ==  2);
312     /// assert!(( 8).div_floor(-3) == -3);
313     /// assert!((-8).div_floor( 3) == -3);
314     /// assert!((-8).div_floor(-3) ==  2);
315     ///
316     /// assert!(( 1).div_floor( 2) ==  0);
317     /// assert!(( 1).div_floor(-2) == -1);
318     /// assert!((-1).div_floor( 2) == -1);
319     /// assert!((-1).div_floor(-2) ==  0);
320     /// ~~~
321     ///
322     #[inline]
323     fn div_floor(&self, other: &$T) -> $T {
324         // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
325         // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
326         match self.div_rem(other) {
327             (d, r) if (r > 0 && *other < 0)
328                    || (r < 0 && *other > 0) => d - 1,
329             (d, _)                          => d,
330         }
331     }
332
333     ///
334     /// Integer modulo, satisfying:
335     ///
336     /// ~~~
337     /// assert!(n.div_floor(d) * d + n.mod_floor(d) == n)
338     /// ~~~
339     ///
340     /// # Examples
341     ///
342     /// ~~~
343     /// assert!(( 8).mod_floor( 3) ==  2);
344     /// assert!(( 8).mod_floor(-3) == -1);
345     /// assert!((-8).mod_floor( 3) ==  1);
346     /// assert!((-8).mod_floor(-3) == -2);
347     ///
348     /// assert!(( 1).mod_floor( 2) ==  1);
349     /// assert!(( 1).mod_floor(-2) == -1);
350     /// assert!((-1).mod_floor( 2) ==  1);
351     /// assert!((-1).mod_floor(-2) == -1);
352     /// ~~~
353     ///
354     #[inline]
355     fn mod_floor(&self, other: &$T) -> $T {
356         // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
357         // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
358         match *self % *other {
359             r if (r > 0 && *other < 0)
360               || (r < 0 && *other > 0) => r + *other,
361             r                          => r,
362         }
363     }
364
365     /// Calculates `div_floor` and `mod_floor` simultaneously
366     #[inline]
367     fn div_mod_floor(&self, other: &$T) -> ($T,$T) {
368         // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
369         // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
370         match self.div_rem(other) {
371             (d, r) if (r > 0 && *other < 0)
372                    || (r < 0 && *other > 0) => (d - 1, r + *other),
373             (d, r)                          => (d, r),
374         }
375     }
376
377     /// Calculates `div` (`\`) and `rem` (`%`) simultaneously
378     #[inline]
379     fn div_rem(&self, other: &$T) -> ($T,$T) {
380         (*self / *other, *self % *other)
381     }
382
383     ///
384     /// Calculates the Greatest Common Divisor (GCD) of the number and `other`
385     ///
386     /// The result is always positive
387     ///
388     #[inline]
389     fn gcd(&self, other: &$T) -> $T {
390         // Use Euclid's algorithm
391         let mut m = *self;
392         let mut n = *other;
393         while m != 0 {
394             let temp = m;
395             m = n % temp;
396             n = temp;
397         }
398         n.abs()
399     }
400
401     ///
402     /// Calculates the Lowest Common Multiple (LCM) of the number and `other`
403     ///
404     #[inline]
405     fn lcm(&self, other: &$T) -> $T {
406         ((*self * *other) / self.gcd(other)).abs() // should not have to recaluculate abs
407     }
408
409     /// Returns `true` if the number can be divided by `other` without leaving a remainder
410     #[inline]
411     fn is_multiple_of(&self, other: &$T) -> bool { *self % *other == 0 }
412
413     /// Returns `true` if the number is divisible by `2`
414     #[inline]
415     fn is_even(&self) -> bool { self.is_multiple_of(&2) }
416
417     /// Returns `true` if the number is not divisible by `2`
418     #[inline]
419     fn is_odd(&self) -> bool { !self.is_even() }
420 }
421
422 impl Bitwise for $T {}
423
424 #[cfg(not(test))]
425 impl BitOr<$T,$T> for $T {
426     #[inline]
427     fn bitor(&self, other: &$T) -> $T { *self | *other }
428 }
429
430 #[cfg(not(test))]
431 impl BitAnd<$T,$T> for $T {
432     #[inline]
433     fn bitand(&self, other: &$T) -> $T { *self & *other }
434 }
435
436 #[cfg(not(test))]
437 impl BitXor<$T,$T> for $T {
438     #[inline]
439     fn bitxor(&self, other: &$T) -> $T { *self ^ *other }
440 }
441
442 #[cfg(not(test))]
443 impl Shl<$T,$T> for $T {
444     #[inline]
445     fn shl(&self, other: &$T) -> $T { *self << *other }
446 }
447
448 #[cfg(not(test))]
449 impl Shr<$T,$T> for $T {
450     #[inline]
451     fn shr(&self, other: &$T) -> $T { *self >> *other }
452 }
453
454 #[cfg(not(test))]
455 impl Not<$T> for $T {
456     #[inline]
457     fn not(&self) -> $T { !*self }
458 }
459
460 impl Bounded for $T {
461     #[inline]
462     fn min_value() -> $T { min_value }
463
464     #[inline]
465     fn max_value() -> $T { max_value }
466 }
467
468 impl Int for $T {}
469
470 impl Primitive for $T {
471     #[inline]
472     fn bits() -> uint { bits }
473
474     #[inline]
475     fn bytes() -> uint { bits / 8 }
476 }
477
478 // String conversion functions and impl str -> num
479
480 /// Parse a string as a number in base 10.
481 #[inline]
482 pub fn from_str(s: &str) -> Option<$T> {
483     strconv::from_str_common(s, 10u, true, false, false,
484                          strconv::ExpNone, false, false)
485 }
486
487 /// Parse a string as a number in the given base.
488 #[inline]
489 pub fn from_str_radix(s: &str, radix: uint) -> Option<$T> {
490     strconv::from_str_common(s, radix, true, false, false,
491                          strconv::ExpNone, false, false)
492 }
493
494 /// Parse a byte slice as a number in the given base.
495 #[inline]
496 pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<$T> {
497     strconv::from_str_bytes_common(buf, radix, true, false, false,
498                                strconv::ExpNone, false, false)
499 }
500
501 impl FromStr for $T {
502     #[inline]
503     fn from_str(s: &str) -> Option<$T> {
504         from_str(s)
505     }
506 }
507
508 impl FromStrRadix for $T {
509     #[inline]
510     fn from_str_radix(s: &str, radix: uint) -> Option<$T> {
511         from_str_radix(s, radix)
512     }
513 }
514
515 // String conversion functions and impl num -> str
516
517 /// Convert to a string as a byte slice in a given base.
518 #[inline]
519 pub fn to_str_bytes<U>(n: $T, radix: uint, f: &fn(v: &[u8]) -> U) -> U {
520     // The radix can be as low as 2, so we need at least 64 characters for a
521     // base 2 number, and then we need another for a possible '-' character.
522     let mut buf = [0u8, ..65];
523     let mut cur = 0;
524     do strconv::int_to_str_bytes_common(n, radix, strconv::SignNeg) |i| {
525         buf[cur] = i;
526         cur += 1;
527     }
528     f(buf.slice(0, cur))
529 }
530
531 /// Convert to a string in base 10.
532 #[inline]
533 pub fn to_str(num: $T) -> ~str {
534     to_str_radix(num, 10u)
535 }
536
537 /// Convert to a string in a given base.
538 #[inline]
539 pub fn to_str_radix(num: $T, radix: uint) -> ~str {
540     let mut buf: ~[u8] = ~[];
541     do strconv::int_to_str_bytes_common(num, radix, strconv::SignNeg) |i| {
542         buf.push(i);
543     }
544     // We know we generated valid utf-8, so we don't need to go through that
545     // check.
546     unsafe { str::raw::from_bytes_owned(buf) }
547 }
548
549 impl ToStr for $T {
550     #[inline]
551     fn to_str(&self) -> ~str {
552         to_str(*self)
553     }
554 }
555
556 impl ToStrRadix for $T {
557     #[inline]
558     fn to_str_radix(&self, radix: uint) -> ~str {
559         to_str_radix(*self, radix)
560     }
561 }
562
563 #[cfg(test)]
564 mod tests {
565     use super::*;
566     use prelude::*;
567
568     use i16;
569     use i32;
570     use i64;
571     use i8;
572     use num;
573     use sys;
574
575     #[test]
576     fn test_num() {
577         num::test_num(10 as $T, 2 as $T);
578     }
579
580     #[test]
581     fn test_orderable() {
582         assert_eq!((1 as $T).min(&(2 as $T)), 1 as $T);
583         assert_eq!((2 as $T).min(&(1 as $T)), 1 as $T);
584         assert_eq!((1 as $T).max(&(2 as $T)), 2 as $T);
585         assert_eq!((2 as $T).max(&(1 as $T)), 2 as $T);
586         assert_eq!((1 as $T).clamp(&(2 as $T), &(4 as $T)), 2 as $T);
587         assert_eq!((8 as $T).clamp(&(2 as $T), &(4 as $T)), 4 as $T);
588         assert_eq!((3 as $T).clamp(&(2 as $T), &(4 as $T)), 3 as $T);
589     }
590
591     #[test]
592     pub fn test_abs() {
593         assert_eq!((1 as $T).abs(), 1 as $T);
594         assert_eq!((0 as $T).abs(), 0 as $T);
595         assert_eq!((-1 as $T).abs(), 1 as $T);
596     }
597
598     #[test]
599     fn test_abs_sub() {
600         assert_eq!((-1 as $T).abs_sub(&(1 as $T)), 0 as $T);
601         assert_eq!((1 as $T).abs_sub(&(1 as $T)), 0 as $T);
602         assert_eq!((1 as $T).abs_sub(&(0 as $T)), 1 as $T);
603         assert_eq!((1 as $T).abs_sub(&(-1 as $T)), 2 as $T);
604     }
605
606     #[test]
607     fn test_signum() {
608         assert_eq!((1 as $T).signum(), 1 as $T);
609         assert_eq!((0 as $T).signum(), 0 as $T);
610         assert_eq!((-0 as $T).signum(), 0 as $T);
611         assert_eq!((-1 as $T).signum(), -1 as $T);
612     }
613
614     #[test]
615     fn test_is_positive() {
616         assert!((1 as $T).is_positive());
617         assert!(!(0 as $T).is_positive());
618         assert!(!(-0 as $T).is_positive());
619         assert!(!(-1 as $T).is_positive());
620     }
621
622     #[test]
623     fn test_is_negative() {
624         assert!(!(1 as $T).is_negative());
625         assert!(!(0 as $T).is_negative());
626         assert!(!(-0 as $T).is_negative());
627         assert!((-1 as $T).is_negative());
628     }
629
630     ///
631     /// Checks that the division rule holds for:
632     ///
633     /// - `n`: numerator (dividend)
634     /// - `d`: denominator (divisor)
635     /// - `qr`: quotient and remainder
636     ///
637     #[cfg(test)]
638     fn test_division_rule((n,d): ($T,$T), (q,r): ($T,$T)) {
639         assert_eq!(d * q + r, n);
640     }
641
642     #[test]
643     fn test_div_rem() {
644         fn test_nd_dr(nd: ($T,$T), qr: ($T,$T)) {
645             let (n,d) = nd;
646             let separate_div_rem = (n / d, n % d);
647             let combined_div_rem = n.div_rem(&d);
648
649             assert_eq!(separate_div_rem, qr);
650             assert_eq!(combined_div_rem, qr);
651
652             test_division_rule(nd, separate_div_rem);
653             test_division_rule(nd, combined_div_rem);
654         }
655
656         test_nd_dr(( 8,  3), ( 2,  2));
657         test_nd_dr(( 8, -3), (-2,  2));
658         test_nd_dr((-8,  3), (-2, -2));
659         test_nd_dr((-8, -3), ( 2, -2));
660
661         test_nd_dr(( 1,  2), ( 0,  1));
662         test_nd_dr(( 1, -2), ( 0,  1));
663         test_nd_dr((-1,  2), ( 0, -1));
664         test_nd_dr((-1, -2), ( 0, -1));
665     }
666
667     #[test]
668     fn test_div_mod_floor() {
669         fn test_nd_dm(nd: ($T,$T), dm: ($T,$T)) {
670             let (n,d) = nd;
671             let separate_div_mod_floor = (n.div_floor(&d), n.mod_floor(&d));
672             let combined_div_mod_floor = n.div_mod_floor(&d);
673
674             assert_eq!(separate_div_mod_floor, dm);
675             assert_eq!(combined_div_mod_floor, dm);
676
677             test_division_rule(nd, separate_div_mod_floor);
678             test_division_rule(nd, combined_div_mod_floor);
679         }
680
681         test_nd_dm(( 8,  3), ( 2,  2));
682         test_nd_dm(( 8, -3), (-3, -1));
683         test_nd_dm((-8,  3), (-3,  1));
684         test_nd_dm((-8, -3), ( 2, -2));
685
686         test_nd_dm(( 1,  2), ( 0,  1));
687         test_nd_dm(( 1, -2), (-1, -1));
688         test_nd_dm((-1,  2), (-1,  1));
689         test_nd_dm((-1, -2), ( 0, -1));
690     }
691
692     #[test]
693     fn test_gcd() {
694         assert_eq!((10 as $T).gcd(&2), 2 as $T);
695         assert_eq!((10 as $T).gcd(&3), 1 as $T);
696         assert_eq!((0 as $T).gcd(&3), 3 as $T);
697         assert_eq!((3 as $T).gcd(&3), 3 as $T);
698         assert_eq!((56 as $T).gcd(&42), 14 as $T);
699         assert_eq!((3 as $T).gcd(&-3), 3 as $T);
700         assert_eq!((-6 as $T).gcd(&3), 3 as $T);
701         assert_eq!((-4 as $T).gcd(&-2), 2 as $T);
702     }
703
704     #[test]
705     fn test_lcm() {
706         assert_eq!((1 as $T).lcm(&0), 0 as $T);
707         assert_eq!((0 as $T).lcm(&1), 0 as $T);
708         assert_eq!((1 as $T).lcm(&1), 1 as $T);
709         assert_eq!((-1 as $T).lcm(&1), 1 as $T);
710         assert_eq!((1 as $T).lcm(&-1), 1 as $T);
711         assert_eq!((-1 as $T).lcm(&-1), 1 as $T);
712         assert_eq!((8 as $T).lcm(&9), 72 as $T);
713         assert_eq!((11 as $T).lcm(&5), 55 as $T);
714     }
715
716     #[test]
717     fn test_bitwise() {
718         assert_eq!(0b1110 as $T, (0b1100 as $T).bitor(&(0b1010 as $T)));
719         assert_eq!(0b1000 as $T, (0b1100 as $T).bitand(&(0b1010 as $T)));
720         assert_eq!(0b0110 as $T, (0b1100 as $T).bitxor(&(0b1010 as $T)));
721         assert_eq!(0b1110 as $T, (0b0111 as $T).shl(&(1 as $T)));
722         assert_eq!(0b0111 as $T, (0b1110 as $T).shr(&(1 as $T)));
723         assert_eq!(-(0b11 as $T) - (1 as $T), (0b11 as $T).not());
724     }
725
726     #[test]
727     fn test_multiple_of() {
728         assert!((6 as $T).is_multiple_of(&(6 as $T)));
729         assert!((6 as $T).is_multiple_of(&(3 as $T)));
730         assert!((6 as $T).is_multiple_of(&(1 as $T)));
731         assert!((-8 as $T).is_multiple_of(&(4 as $T)));
732         assert!((8 as $T).is_multiple_of(&(-1 as $T)));
733         assert!((-8 as $T).is_multiple_of(&(-2 as $T)));
734     }
735
736     #[test]
737     fn test_even() {
738         assert_eq!((-4 as $T).is_even(), true);
739         assert_eq!((-3 as $T).is_even(), false);
740         assert_eq!((-2 as $T).is_even(), true);
741         assert_eq!((-1 as $T).is_even(), false);
742         assert_eq!((0 as $T).is_even(), true);
743         assert_eq!((1 as $T).is_even(), false);
744         assert_eq!((2 as $T).is_even(), true);
745         assert_eq!((3 as $T).is_even(), false);
746         assert_eq!((4 as $T).is_even(), true);
747     }
748
749     #[test]
750     fn test_odd() {
751         assert_eq!((-4 as $T).is_odd(), false);
752         assert_eq!((-3 as $T).is_odd(), true);
753         assert_eq!((-2 as $T).is_odd(), false);
754         assert_eq!((-1 as $T).is_odd(), true);
755         assert_eq!((0 as $T).is_odd(), false);
756         assert_eq!((1 as $T).is_odd(), true);
757         assert_eq!((2 as $T).is_odd(), false);
758         assert_eq!((3 as $T).is_odd(), true);
759         assert_eq!((4 as $T).is_odd(), false);
760     }
761
762     #[test]
763     fn test_bitcount() {
764         assert_eq!((0b010101 as $T).population_count(), 3);
765     }
766
767     #[test]
768     fn test_primitive() {
769         assert_eq!(Primitive::bits::<$T>(), sys::size_of::<$T>() * 8);
770         assert_eq!(Primitive::bytes::<$T>(), sys::size_of::<$T>());
771     }
772
773     #[test]
774     fn test_from_str() {
775         assert_eq!(from_str("0"), Some(0 as $T));
776         assert_eq!(from_str("3"), Some(3 as $T));
777         assert_eq!(from_str("10"), Some(10 as $T));
778         assert_eq!(i32::from_str("123456789"), Some(123456789 as i32));
779         assert_eq!(from_str("00100"), Some(100 as $T));
780
781         assert_eq!(from_str("-1"), Some(-1 as $T));
782         assert_eq!(from_str("-3"), Some(-3 as $T));
783         assert_eq!(from_str("-10"), Some(-10 as $T));
784         assert_eq!(i32::from_str("-123456789"), Some(-123456789 as i32));
785         assert_eq!(from_str("-00100"), Some(-100 as $T));
786
787         assert!(from_str(" ").is_none());
788         assert!(from_str("x").is_none());
789     }
790
791     #[test]
792     fn test_parse_bytes() {
793         use str::StrSlice;
794         assert_eq!(parse_bytes("123".as_bytes(), 10u), Some(123 as $T));
795         assert_eq!(parse_bytes("1001".as_bytes(), 2u), Some(9 as $T));
796         assert_eq!(parse_bytes("123".as_bytes(), 8u), Some(83 as $T));
797         assert_eq!(i32::parse_bytes("123".as_bytes(), 16u), Some(291 as i32));
798         assert_eq!(i32::parse_bytes("ffff".as_bytes(), 16u), Some(65535 as i32));
799         assert_eq!(i32::parse_bytes("FFFF".as_bytes(), 16u), Some(65535 as i32));
800         assert_eq!(parse_bytes("z".as_bytes(), 36u), Some(35 as $T));
801         assert_eq!(parse_bytes("Z".as_bytes(), 36u), Some(35 as $T));
802
803         assert_eq!(parse_bytes("-123".as_bytes(), 10u), Some(-123 as $T));
804         assert_eq!(parse_bytes("-1001".as_bytes(), 2u), Some(-9 as $T));
805         assert_eq!(parse_bytes("-123".as_bytes(), 8u), Some(-83 as $T));
806         assert_eq!(i32::parse_bytes("-123".as_bytes(), 16u), Some(-291 as i32));
807         assert_eq!(i32::parse_bytes("-ffff".as_bytes(), 16u), Some(-65535 as i32));
808         assert_eq!(i32::parse_bytes("-FFFF".as_bytes(), 16u), Some(-65535 as i32));
809         assert_eq!(parse_bytes("-z".as_bytes(), 36u), Some(-35 as $T));
810         assert_eq!(parse_bytes("-Z".as_bytes(), 36u), Some(-35 as $T));
811
812         assert!(parse_bytes("Z".as_bytes(), 35u).is_none());
813         assert!(parse_bytes("-9".as_bytes(), 2u).is_none());
814     }
815
816     #[test]
817     fn test_to_str() {
818         assert_eq!(to_str_radix(0 as $T, 10u), ~"0");
819         assert_eq!(to_str_radix(1 as $T, 10u), ~"1");
820         assert_eq!(to_str_radix(-1 as $T, 10u), ~"-1");
821         assert_eq!(to_str_radix(127 as $T, 16u), ~"7f");
822         assert_eq!(to_str_radix(100 as $T, 10u), ~"100");
823
824     }
825
826     #[test]
827     fn test_int_to_str_overflow() {
828         let mut i8_val: i8 = 127_i8;
829         assert_eq!(i8::to_str(i8_val), ~"127");
830
831         i8_val += 1 as i8;
832         assert_eq!(i8::to_str(i8_val), ~"-128");
833
834         let mut i16_val: i16 = 32_767_i16;
835         assert_eq!(i16::to_str(i16_val), ~"32767");
836
837         i16_val += 1 as i16;
838         assert_eq!(i16::to_str(i16_val), ~"-32768");
839
840         let mut i32_val: i32 = 2_147_483_647_i32;
841         assert_eq!(i32::to_str(i32_val), ~"2147483647");
842
843         i32_val += 1 as i32;
844         assert_eq!(i32::to_str(i32_val), ~"-2147483648");
845
846         let mut i64_val: i64 = 9_223_372_036_854_775_807_i64;
847         assert_eq!(i64::to_str(i64_val), ~"9223372036854775807");
848
849         i64_val += 1 as i64;
850         assert_eq!(i64::to_str(i64_val), ~"-9223372036854775808");
851     }
852
853     #[test]
854     fn test_int_from_str_overflow() {
855         let mut i8_val: i8 = 127_i8;
856         assert_eq!(i8::from_str("127"), Some(i8_val));
857         assert!(i8::from_str("128").is_none());
858
859         i8_val += 1 as i8;
860         assert_eq!(i8::from_str("-128"), Some(i8_val));
861         assert!(i8::from_str("-129").is_none());
862
863         let mut i16_val: i16 = 32_767_i16;
864         assert_eq!(i16::from_str("32767"), Some(i16_val));
865         assert!(i16::from_str("32768").is_none());
866
867         i16_val += 1 as i16;
868         assert_eq!(i16::from_str("-32768"), Some(i16_val));
869         assert!(i16::from_str("-32769").is_none());
870
871         let mut i32_val: i32 = 2_147_483_647_i32;
872         assert_eq!(i32::from_str("2147483647"), Some(i32_val));
873         assert!(i32::from_str("2147483648").is_none());
874
875         i32_val += 1 as i32;
876         assert_eq!(i32::from_str("-2147483648"), Some(i32_val));
877         assert!(i32::from_str("-2147483649").is_none());
878
879         let mut i64_val: i64 = 9_223_372_036_854_775_807_i64;
880         assert_eq!(i64::from_str("9223372036854775807"), Some(i64_val));
881         assert!(i64::from_str("9223372036854775808").is_none());
882
883         i64_val += 1 as i64;
884         assert_eq!(i64::from_str("-9223372036854775808"), Some(i64_val));
885         assert!(i64::from_str("-9223372036854775809").is_none());
886     }
887
888     #[test]
889     fn test_ranges() {
890         let mut l = ~[];
891
892         do range_rev(14,11) |i| {
893             l.push(i);
894             true
895         };
896         do range_step(20,26,2) |i| {
897             l.push(i);
898             true
899         };
900         do range_step(36,30,-2) |i| {
901             l.push(i);
902             true
903         };
904         do range_step(max_value - 2, max_value, 2) |i| {
905             l.push(i);
906             true
907         };
908         do range_step(max_value - 3, max_value, 2) |i| {
909             l.push(i);
910             true
911         };
912         do range_step(min_value + 2, min_value, -2) |i| {
913             l.push(i);
914             true
915         };
916         do range_step(min_value + 3, min_value, -2) |i| {
917             l.push(i);
918             true
919         };
920         assert_eq!(l, ~[13,12,11,
921                         20,22,24,
922                         36,34,32,
923                         max_value-2,
924                         max_value-3,max_value-1,
925                         min_value+2,
926                         min_value+3,min_value+1]);
927
928         // None of the `fail`s should execute.
929         do range_rev(0,10) |_i| {
930             fail!(~"unreachable");
931         };
932         do range_step(10,0,1) |_i| {
933             fail!(~"unreachable");
934         };
935         do range_step(0,10,-1) |_i| {
936             fail!(~"unreachable");
937         };
938     }
939
940     #[test]
941     #[should_fail]
942     #[ignore(cfg(windows))]
943     fn test_range_step_zero_step() {
944         do range_step(0,10,0) |_i| { true };
945     }
946 }
947
948 }))