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