2012-12-03 18:48:01 -06:00
|
|
|
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2012-12-13 15:05:22 -06:00
|
|
|
use T = self::inst::T;
|
2013-01-23 17:08:47 -06:00
|
|
|
use T_SIGNED = self::inst::T_SIGNED;
|
2012-12-13 15:05:22 -06:00
|
|
|
|
2013-01-24 14:47:57 -06:00
|
|
|
use num::{ToStrRadix, FromStrRadix};
|
2013-04-25 00:30:56 -05:00
|
|
|
use num::{Zero, One, strconv};
|
2013-01-24 14:47:57 -06:00
|
|
|
use prelude::*;
|
2012-04-15 00:07:45 -05:00
|
|
|
|
2013-01-15 19:30:01 -06:00
|
|
|
pub use cmp::{min, max};
|
|
|
|
|
2013-03-22 16:00:15 -05:00
|
|
|
pub static bits : uint = inst::bits;
|
|
|
|
pub static bytes : uint = (inst::bits / 8);
|
2012-04-15 00:07:45 -05:00
|
|
|
|
2013-03-22 16:00:15 -05:00
|
|
|
pub static min_value: T = 0 as T;
|
|
|
|
pub static max_value: T = 0 as T - 1 as T;
|
2012-04-15 00:07:45 -05:00
|
|
|
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn add(x: T, y: T) -> T { x + y }
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn sub(x: T, y: T) -> T { x - y }
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn mul(x: T, y: T) -> T { x * y }
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-05-01 00:40:05 -05:00
|
|
|
pub fn div(x: T, y: T) -> T { x / y }
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn rem(x: T, y: T) -> T { x % y }
|
2012-08-30 14:54:50 -05:00
|
|
|
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn lt(x: T, y: T) -> bool { x < y }
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn le(x: T, y: T) -> bool { x <= y }
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn eq(x: T, y: T) -> bool { x == y }
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn ne(x: T, y: T) -> bool { x != y }
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn ge(x: T, y: T) -> bool { x >= y }
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn gt(x: T, y: T) -> bool { x > y }
|
2012-04-15 00:07:45 -05:00
|
|
|
|
2012-12-09 20:57:41 -06:00
|
|
|
#[inline(always)]
|
2013-04-25 18:55:49 -05:00
|
|
|
///
|
|
|
|
/// Iterate over the range [`start`,`start`+`step`..`stop`)
|
|
|
|
///
|
2013-05-02 17:33:18 -05:00
|
|
|
pub fn _range_step(start: T,
|
|
|
|
stop: T,
|
|
|
|
step: T_SIGNED,
|
|
|
|
it: &fn(T) -> bool) -> bool {
|
2012-12-09 20:57:41 -06:00
|
|
|
let mut i = start;
|
|
|
|
if step == 0 {
|
2013-05-05 17:18:51 -05:00
|
|
|
fail!("range_step called with step == 0");
|
2013-01-10 14:18:01 -06:00
|
|
|
}
|
2013-01-23 17:08:47 -06:00
|
|
|
if step >= 0 {
|
|
|
|
while i < stop {
|
2013-05-02 17:33:18 -05:00
|
|
|
if !it(i) { return false; }
|
2013-04-07 05:51:34 -05:00
|
|
|
// avoiding overflow. break if i + step > max_value
|
2013-05-02 17:33:18 -05:00
|
|
|
if i > max_value - (step as T) { return true; }
|
2013-01-23 17:08:47 -06:00
|
|
|
i += step as T;
|
|
|
|
}
|
2013-04-07 05:51:34 -05:00
|
|
|
} else {
|
2013-01-23 17:08:47 -06:00
|
|
|
while i > stop {
|
2013-05-02 17:33:18 -05:00
|
|
|
if !it(i) { return false; }
|
2013-04-07 05:51:34 -05:00
|
|
|
// avoiding underflow. break if i + step < min_value
|
2013-05-02 17:33:18 -05:00
|
|
|
if i < min_value + ((-step) as T) { return true; }
|
2013-01-23 17:08:47 -06:00
|
|
|
i -= -step as T;
|
|
|
|
}
|
2012-12-09 20:57:41 -06:00
|
|
|
}
|
2013-05-02 17:33:18 -05:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn range_step(start: T, stop: T, step: T_SIGNED, it: &fn(T) -> bool) -> bool {
|
|
|
|
_range_step(start, stop, step, it)
|
2012-12-09 20:57:41 -06:00
|
|
|
}
|
|
|
|
|
2012-06-08 20:49:50 -05:00
|
|
|
#[inline(always)]
|
2013-05-02 17:33:18 -05:00
|
|
|
/// Iterate over the range [`lo`..`hi`)
|
|
|
|
pub fn range(lo: T, hi: T, it: &fn(T) -> bool) -> bool {
|
|
|
|
range_step(lo, hi, 1 as T_SIGNED, it)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
/// Iterate over the range [`hi`..`lo`)
|
|
|
|
pub fn range_rev(hi: T, lo: T, it: &fn(T) -> bool) -> bool {
|
|
|
|
range_step(hi, lo, -1 as T_SIGNED, it)
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Computes the bitwise complement
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn compl(i: T) -> T {
|
2012-04-15 00:07:45 -05:00
|
|
|
max_value ^ i
|
|
|
|
}
|
2012-05-16 00:50:29 -05:00
|
|
|
|
2013-04-24 05:08:08 -05:00
|
|
|
impl Num for T {}
|
|
|
|
|
2013-05-08 06:11:23 -05:00
|
|
|
#[cfg(not(test))]
|
2013-02-14 13:47:00 -06:00
|
|
|
impl Ord for T {
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
fn lt(&self, other: &T) -> bool { (*self) < (*other) }
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
fn le(&self, other: &T) -> bool { (*self) <= (*other) }
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
fn ge(&self, other: &T) -> bool { (*self) >= (*other) }
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
fn gt(&self, other: &T) -> bool { (*self) > (*other) }
|
2012-09-19 20:00:26 -05:00
|
|
|
}
|
2012-06-06 16:19:52 -05:00
|
|
|
|
2013-05-08 06:11:23 -05:00
|
|
|
#[cfg(not(test))]
|
2013-02-14 13:47:00 -06:00
|
|
|
impl Eq for T {
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
fn eq(&self, other: &T) -> bool { return (*self) == (*other); }
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
fn ne(&self, other: &T) -> bool { return (*self) != (*other); }
|
2012-09-19 20:00:26 -05:00
|
|
|
}
|
2012-06-06 16:19:52 -05:00
|
|
|
|
2013-04-26 10:01:53 -05:00
|
|
|
impl Orderable for T {
|
|
|
|
#[inline(always)]
|
|
|
|
fn min(&self, other: &T) -> T {
|
|
|
|
if *self < *other { *self } else { *other }
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
fn max(&self, other: &T) -> T {
|
|
|
|
if *self > *other { *self } else { *other }
|
|
|
|
}
|
|
|
|
|
2013-05-18 00:02:58 -05:00
|
|
|
/// Returns the number constrained within the range `mn <= self <= mx`.
|
|
|
|
#[inline(always)]
|
|
|
|
fn clamp(&self, mn: &T, mx: &T) -> T {
|
|
|
|
cond!(
|
|
|
|
(*self > *mx) { *mx }
|
|
|
|
(*self < *mn) { *mn }
|
|
|
|
_ { *self }
|
|
|
|
)
|
|
|
|
}
|
2013-04-26 10:01:53 -05:00
|
|
|
}
|
|
|
|
|
2013-04-25 00:30:56 -05:00
|
|
|
impl Zero for T {
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
fn zero() -> T { 0 }
|
2013-04-25 00:30:56 -05:00
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
fn is_zero(&self) -> bool { *self == 0 }
|
2012-12-20 09:14:38 -06:00
|
|
|
}
|
|
|
|
|
2013-04-25 00:30:56 -05:00
|
|
|
impl One for T {
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
fn one() -> T { 1 }
|
2012-12-20 09:14:38 -06:00
|
|
|
}
|
|
|
|
|
2013-05-08 06:11:23 -05:00
|
|
|
#[cfg(not(test))]
|
2013-04-21 10:58:53 -05:00
|
|
|
impl Add<T,T> for T {
|
2013-04-23 12:56:49 -05:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
fn add(&self, other: &T) -> T { *self + *other }
|
2013-02-12 19:07:26 -06:00
|
|
|
}
|
2013-04-23 12:56:49 -05:00
|
|
|
|
2013-05-08 06:11:23 -05:00
|
|
|
#[cfg(not(test))]
|
2013-04-21 10:58:53 -05:00
|
|
|
impl Sub<T,T> for T {
|
2013-04-23 12:56:49 -05:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
fn sub(&self, other: &T) -> T { *self - *other }
|
2013-02-12 19:07:26 -06:00
|
|
|
}
|
2013-04-23 12:56:49 -05:00
|
|
|
|
2013-05-08 06:11:23 -05:00
|
|
|
#[cfg(not(test))]
|
2013-04-21 10:58:53 -05:00
|
|
|
impl Mul<T,T> for T {
|
2013-04-23 12:56:49 -05:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
fn mul(&self, other: &T) -> T { *self * *other }
|
2013-02-12 19:07:26 -06:00
|
|
|
}
|
2013-04-23 12:56:49 -05:00
|
|
|
|
2013-05-08 06:11:23 -05:00
|
|
|
#[cfg(not(test))]
|
2013-04-21 10:58:53 -05:00
|
|
|
impl Div<T,T> for T {
|
2013-04-23 12:56:49 -05:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
fn div(&self, other: &T) -> T { *self / *other }
|
2013-02-12 19:07:26 -06:00
|
|
|
}
|
2013-04-23 12:56:49 -05:00
|
|
|
|
2013-05-08 06:11:23 -05:00
|
|
|
#[cfg(not(test))]
|
2013-04-21 10:58:53 -05:00
|
|
|
impl Rem<T,T> for T {
|
2013-04-18 08:24:24 -05:00
|
|
|
#[inline(always)]
|
2013-04-21 10:58:53 -05:00
|
|
|
fn rem(&self, other: &T) -> T { *self % *other }
|
|
|
|
}
|
2013-04-23 12:56:49 -05:00
|
|
|
|
2013-05-08 06:11:23 -05:00
|
|
|
#[cfg(not(test))]
|
2013-04-21 10:58:53 -05:00
|
|
|
impl Neg<T> for T {
|
2013-04-23 12:56:49 -05:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
fn neg(&self) -> T { -*self }
|
2013-02-12 19:07:26 -06:00
|
|
|
}
|
2013-04-18 08:24:24 -05:00
|
|
|
|
2013-04-23 02:59:49 -05:00
|
|
|
impl Unsigned for T {}
|
|
|
|
|
2013-04-24 07:45:57 -05:00
|
|
|
impl Integer for T {
|
2013-05-01 00:40:05 -05:00
|
|
|
/// Calculates `div` (`\`) and `rem` (`%`) simultaneously
|
2013-04-23 21:54:11 -05:00
|
|
|
#[inline(always)]
|
2013-05-01 00:40:05 -05:00
|
|
|
fn div_rem(&self, other: &T) -> (T,T) {
|
|
|
|
(*self / *other, *self % *other)
|
|
|
|
}
|
2013-04-23 21:54:11 -05:00
|
|
|
|
2013-05-01 00:40:05 -05:00
|
|
|
/// Unsigned integer division. Returns the same result as `div` (`/`).
|
2013-04-23 21:54:11 -05:00
|
|
|
#[inline(always)]
|
2013-05-01 00:40:05 -05:00
|
|
|
fn div_floor(&self, other: &T) -> T { *self / *other }
|
2013-04-23 21:54:11 -05:00
|
|
|
|
2013-05-01 00:40:05 -05:00
|
|
|
/// Unsigned integer modulo operation. Returns the same result as `rem` (`%`).
|
2013-04-23 21:54:11 -05:00
|
|
|
#[inline(always)]
|
2013-05-01 00:40:05 -05:00
|
|
|
fn mod_floor(&self, other: &T) -> T { *self / *other }
|
2013-04-23 21:54:11 -05:00
|
|
|
|
2013-05-01 00:40:05 -05:00
|
|
|
/// Calculates `div_floor` and `modulo_floor` simultaneously
|
2013-04-23 21:54:11 -05:00
|
|
|
#[inline(always)]
|
2013-05-01 00:40:05 -05:00
|
|
|
fn div_mod_floor(&self, other: &T) -> (T,T) {
|
2013-04-24 07:50:56 -05:00
|
|
|
(*self / *other, *self % *other)
|
2013-04-23 21:54:11 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Calculates the Greatest Common Divisor (GCD) of the number and `other`
|
|
|
|
#[inline(always)]
|
2013-04-24 07:50:56 -05:00
|
|
|
fn gcd(&self, other: &T) -> T {
|
2013-04-23 21:54:11 -05:00
|
|
|
// Use Euclid's algorithm
|
2013-04-24 07:50:56 -05:00
|
|
|
let mut m = *self, n = *other;
|
2013-04-23 21:54:11 -05:00
|
|
|
while m != 0 {
|
|
|
|
let temp = m;
|
|
|
|
m = n % temp;
|
|
|
|
n = temp;
|
|
|
|
}
|
|
|
|
n
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Calculates the Lowest Common Multiple (LCM) of the number and `other`
|
|
|
|
#[inline(always)]
|
2013-04-24 07:50:56 -05:00
|
|
|
fn lcm(&self, other: &T) -> T {
|
|
|
|
(*self * *other) / self.gcd(other)
|
2013-04-23 21:54:11 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns `true` if the number can be divided by `other` without leaving a remainder
|
|
|
|
#[inline(always)]
|
2013-04-29 01:02:43 -05:00
|
|
|
fn is_multiple_of(&self, other: &T) -> bool { *self % *other == 0 }
|
2013-04-23 21:54:11 -05:00
|
|
|
|
|
|
|
/// Returns `true` if the number is divisible by `2`
|
|
|
|
#[inline(always)]
|
2013-04-29 01:02:43 -05:00
|
|
|
fn is_even(&self) -> bool { self.is_multiple_of(&2) }
|
2013-04-23 21:54:11 -05:00
|
|
|
|
|
|
|
/// Returns `true` if the number is not divisible by `2`
|
|
|
|
#[inline(always)]
|
|
|
|
fn is_odd(&self) -> bool { !self.is_even() }
|
|
|
|
}
|
|
|
|
|
2013-04-25 19:02:00 -05:00
|
|
|
impl Bitwise for T {}
|
|
|
|
|
2013-05-08 06:11:23 -05:00
|
|
|
#[cfg(not(test))]
|
2013-04-21 10:58:53 -05:00
|
|
|
impl BitOr<T,T> for T {
|
2013-04-18 08:24:24 -05:00
|
|
|
#[inline(always)]
|
2013-04-18 05:58:58 -05:00
|
|
|
fn bitor(&self, other: &T) -> T { *self | *other }
|
|
|
|
}
|
2013-04-23 12:56:49 -05:00
|
|
|
|
2013-05-08 06:11:23 -05:00
|
|
|
#[cfg(not(test))]
|
2013-04-21 10:58:53 -05:00
|
|
|
impl BitAnd<T,T> for T {
|
2013-04-18 08:24:24 -05:00
|
|
|
#[inline(always)]
|
2013-04-18 05:58:58 -05:00
|
|
|
fn bitand(&self, other: &T) -> T { *self & *other }
|
|
|
|
}
|
2013-04-23 12:56:49 -05:00
|
|
|
|
2013-05-08 06:11:23 -05:00
|
|
|
#[cfg(not(test))]
|
2013-04-21 10:58:53 -05:00
|
|
|
impl BitXor<T,T> for T {
|
2013-04-18 08:24:24 -05:00
|
|
|
#[inline(always)]
|
2013-04-18 05:58:58 -05:00
|
|
|
fn bitxor(&self, other: &T) -> T { *self ^ *other }
|
|
|
|
}
|
2013-04-23 12:56:49 -05:00
|
|
|
|
2013-05-08 06:11:23 -05:00
|
|
|
#[cfg(not(test))]
|
2013-04-21 10:58:53 -05:00
|
|
|
impl Shl<T,T> for T {
|
2013-04-18 08:24:24 -05:00
|
|
|
#[inline(always)]
|
2013-04-18 05:58:58 -05:00
|
|
|
fn shl(&self, other: &T) -> T { *self << *other }
|
|
|
|
}
|
2013-04-23 12:56:49 -05:00
|
|
|
|
2013-05-08 06:11:23 -05:00
|
|
|
#[cfg(not(test))]
|
2013-04-21 10:58:53 -05:00
|
|
|
impl Shr<T,T> for T {
|
2013-04-18 08:24:24 -05:00
|
|
|
#[inline(always)]
|
2013-04-18 05:58:58 -05:00
|
|
|
fn shr(&self, other: &T) -> T { *self >> *other }
|
|
|
|
}
|
2013-04-23 12:56:49 -05:00
|
|
|
|
2013-05-08 06:11:23 -05:00
|
|
|
#[cfg(not(test))]
|
2013-04-21 10:58:53 -05:00
|
|
|
impl Not<T> for T {
|
2013-04-18 08:24:24 -05:00
|
|
|
#[inline(always)]
|
2013-04-18 05:58:58 -05:00
|
|
|
fn not(&self) -> T { !*self }
|
|
|
|
}
|
2013-02-12 19:07:26 -06:00
|
|
|
|
2013-04-25 19:02:00 -05:00
|
|
|
impl Bounded for T {
|
|
|
|
#[inline(always)]
|
|
|
|
fn min_value() -> T { min_value }
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
fn max_value() -> T { max_value }
|
|
|
|
}
|
|
|
|
|
2013-04-26 04:56:11 -05:00
|
|
|
impl Int for T {}
|
2013-04-25 19:22:08 -05:00
|
|
|
|
2013-01-24 14:47:57 -06:00
|
|
|
// String conversion functions and impl str -> num
|
2012-08-02 19:14:26 -05:00
|
|
|
|
2013-01-24 14:47:57 -06:00
|
|
|
/// Parse a string as a number in base 10.
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn from_str(s: &str) -> Option<T> {
|
2013-02-14 20:29:36 -06:00
|
|
|
strconv::from_str_common(s, 10u, false, false, false,
|
2013-04-07 09:23:42 -05:00
|
|
|
strconv::ExpNone, false, false)
|
2012-11-17 13:01:08 -06:00
|
|
|
}
|
2012-05-16 00:50:29 -05:00
|
|
|
|
2013-01-24 14:47:57 -06:00
|
|
|
/// Parse a string as a number in the given base.
|
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn from_str_radix(s: &str, radix: uint) -> Option<T> {
|
2013-02-14 20:29:36 -06:00
|
|
|
strconv::from_str_common(s, radix, false, false, false,
|
2013-04-07 09:23:42 -05:00
|
|
|
strconv::ExpNone, false, false)
|
2012-09-03 15:09:24 -05:00
|
|
|
}
|
|
|
|
|
2013-01-24 14:47:57 -06:00
|
|
|
/// Parse a byte slice as a number in the given base.
|
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<T> {
|
2013-02-14 20:29:36 -06:00
|
|
|
strconv::from_str_bytes_common(buf, radix, false, false, false,
|
2013-04-07 09:23:42 -05:00
|
|
|
strconv::ExpNone, false, false)
|
2012-05-16 00:50:29 -05:00
|
|
|
}
|
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl FromStr for T {
|
2013-01-24 14:47:57 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
fn from_str(s: &str) -> Option<T> {
|
2013-01-24 14:47:57 -06:00
|
|
|
from_str(s)
|
2012-06-04 20:05:34 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl FromStrRadix for T {
|
2012-06-04 20:05:34 -05:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
fn from_str_radix(s: &str, radix: uint) -> Option<T> {
|
2013-01-24 14:47:57 -06:00
|
|
|
from_str_radix(s, radix)
|
2012-05-16 00:50:29 -05:00
|
|
|
}
|
2013-01-24 14:47:57 -06:00
|
|
|
}
|
2012-06-04 16:20:57 -05:00
|
|
|
|
2013-01-24 14:47:57 -06:00
|
|
|
// String conversion functions and impl num -> str
|
2012-12-14 19:03:35 -06:00
|
|
|
|
2013-01-24 14:47:57 -06:00
|
|
|
/// Convert to a string as a byte slice in a given base.
|
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn to_str_bytes<U>(n: T, radix: uint, f: &fn(v: &[u8]) -> U) -> U {
|
2013-02-14 22:20:36 -06:00
|
|
|
let (buf, _) = strconv::to_str_bytes_common(&n, radix, false,
|
2013-02-14 20:29:36 -06:00
|
|
|
strconv::SignNeg, strconv::DigAll);
|
2013-01-24 14:47:57 -06:00
|
|
|
f(buf)
|
|
|
|
}
|
2012-12-14 19:03:35 -06:00
|
|
|
|
2013-01-24 14:47:57 -06:00
|
|
|
/// Convert to a string in base 10.
|
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn to_str(num: T) -> ~str {
|
2013-02-14 22:20:36 -06:00
|
|
|
let (buf, _) = strconv::to_str_common(&num, 10u, false,
|
2013-02-14 20:29:36 -06:00
|
|
|
strconv::SignNeg, strconv::DigAll);
|
2013-01-24 14:47:57 -06:00
|
|
|
buf
|
|
|
|
}
|
2012-12-14 19:03:35 -06:00
|
|
|
|
2013-01-24 14:47:57 -06:00
|
|
|
/// Convert to a string in a given base.
|
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn to_str_radix(num: T, radix: uint) -> ~str {
|
2013-02-14 22:20:36 -06:00
|
|
|
let (buf, _) = strconv::to_str_common(&num, radix, false,
|
2013-02-14 20:29:36 -06:00
|
|
|
strconv::SignNeg, strconv::DigAll);
|
2013-01-24 14:47:57 -06:00
|
|
|
buf
|
2012-05-16 00:50:29 -05:00
|
|
|
}
|
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl ToStr for T {
|
2013-01-24 14:47:57 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
fn to_str(&self) -> ~str {
|
2013-02-03 22:47:26 -06:00
|
|
|
to_str(*self)
|
2013-01-24 14:47:57 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl ToStrRadix for T {
|
2013-01-24 14:47:57 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
fn to_str_radix(&self, radix: uint) -> ~str {
|
2013-01-24 14:47:57 -06:00
|
|
|
to_str_radix(*self, radix)
|
|
|
|
}
|
|
|
|
}
|
2012-05-16 00:50:29 -05:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
use super::inst::T;
|
|
|
|
use prelude::*;
|
2013-04-18 05:58:58 -05:00
|
|
|
|
2013-04-24 05:08:08 -05:00
|
|
|
#[test]
|
|
|
|
fn test_num() {
|
|
|
|
num::test_num(10 as T, 2 as T);
|
|
|
|
}
|
|
|
|
|
2013-04-26 10:01:53 -05:00
|
|
|
#[test]
|
|
|
|
fn test_orderable() {
|
|
|
|
assert_eq!((1 as T).min(&(2 as T)), 1 as T);
|
|
|
|
assert_eq!((2 as T).min(&(1 as T)), 1 as T);
|
|
|
|
assert_eq!((1 as T).max(&(2 as T)), 2 as T);
|
|
|
|
assert_eq!((2 as T).max(&(1 as T)), 2 as T);
|
|
|
|
assert_eq!((1 as T).clamp(&(2 as T), &(4 as T)), 2 as T);
|
|
|
|
assert_eq!((8 as T).clamp(&(2 as T), &(4 as T)), 4 as T);
|
|
|
|
assert_eq!((3 as T).clamp(&(2 as T), &(4 as T)), 3 as T);
|
|
|
|
}
|
|
|
|
|
2013-04-23 21:54:11 -05:00
|
|
|
#[test]
|
|
|
|
fn test_gcd() {
|
2013-04-24 07:50:56 -05:00
|
|
|
assert_eq!((10 as T).gcd(&2), 2 as T);
|
|
|
|
assert_eq!((10 as T).gcd(&3), 1 as T);
|
|
|
|
assert_eq!((0 as T).gcd(&3), 3 as T);
|
|
|
|
assert_eq!((3 as T).gcd(&3), 3 as T);
|
|
|
|
assert_eq!((56 as T).gcd(&42), 14 as T);
|
2013-04-23 21:54:11 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_lcm() {
|
2013-04-24 07:50:56 -05:00
|
|
|
assert_eq!((1 as T).lcm(&0), 0 as T);
|
|
|
|
assert_eq!((0 as T).lcm(&1), 0 as T);
|
|
|
|
assert_eq!((1 as T).lcm(&1), 1 as T);
|
|
|
|
assert_eq!((8 as T).lcm(&9), 72 as T);
|
|
|
|
assert_eq!((11 as T).lcm(&5), 55 as T);
|
|
|
|
assert_eq!((99 as T).lcm(&17), 1683 as T);
|
2013-04-23 21:54:11 -05:00
|
|
|
}
|
|
|
|
|
2013-04-29 01:02:43 -05:00
|
|
|
#[test]
|
|
|
|
fn test_multiple_of() {
|
|
|
|
assert!((6 as T).is_multiple_of(&(6 as T)));
|
|
|
|
assert!((6 as T).is_multiple_of(&(3 as T)));
|
|
|
|
assert!((6 as T).is_multiple_of(&(1 as T)));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_even() {
|
|
|
|
assert_eq!((0 as T).is_even(), true);
|
|
|
|
assert_eq!((1 as T).is_even(), false);
|
|
|
|
assert_eq!((2 as T).is_even(), true);
|
|
|
|
assert_eq!((3 as T).is_even(), false);
|
|
|
|
assert_eq!((4 as T).is_even(), true);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_odd() {
|
|
|
|
assert_eq!((0 as T).is_odd(), false);
|
|
|
|
assert_eq!((1 as T).is_odd(), true);
|
|
|
|
assert_eq!((2 as T).is_odd(), false);
|
|
|
|
assert_eq!((3 as T).is_odd(), true);
|
|
|
|
assert_eq!((4 as T).is_odd(), false);
|
|
|
|
}
|
|
|
|
|
2013-04-18 05:58:58 -05:00
|
|
|
#[test]
|
2013-04-26 01:27:51 -05:00
|
|
|
fn test_bitwise() {
|
2013-04-18 10:37:21 -05:00
|
|
|
assert_eq!(0b1110 as T, (0b1100 as T).bitor(&(0b1010 as T)));
|
|
|
|
assert_eq!(0b1000 as T, (0b1100 as T).bitand(&(0b1010 as T)));
|
|
|
|
assert_eq!(0b0110 as T, (0b1100 as T).bitxor(&(0b1010 as T)));
|
|
|
|
assert_eq!(0b1110 as T, (0b0111 as T).shl(&(1 as T)));
|
|
|
|
assert_eq!(0b0111 as T, (0b1110 as T).shr(&(1 as T)));
|
|
|
|
assert_eq!(max_value - (0b1011 as T), (0b1011 as T).not());
|
2013-04-18 05:58:58 -05:00
|
|
|
}
|
|
|
|
|
2013-04-26 01:27:51 -05:00
|
|
|
#[test]
|
|
|
|
fn test_bitcount() {
|
|
|
|
assert_eq!((0b010101 as T).population_count(), 3);
|
|
|
|
}
|
|
|
|
|
2013-04-25 19:02:00 -05:00
|
|
|
#[test]
|
|
|
|
fn test_primitive() {
|
|
|
|
assert_eq!(Primitive::bits::<T>(), sys::size_of::<T>() * 8);
|
|
|
|
assert_eq!(Primitive::bytes::<T>(), sys::size_of::<T>());
|
|
|
|
}
|
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
#[test]
|
|
|
|
pub fn test_to_str() {
|
2013-04-18 10:37:21 -05:00
|
|
|
assert_eq!(to_str_radix(0 as T, 10u), ~"0");
|
|
|
|
assert_eq!(to_str_radix(1 as T, 10u), ~"1");
|
|
|
|
assert_eq!(to_str_radix(2 as T, 10u), ~"2");
|
|
|
|
assert_eq!(to_str_radix(11 as T, 10u), ~"11");
|
|
|
|
assert_eq!(to_str_radix(11 as T, 16u), ~"b");
|
|
|
|
assert_eq!(to_str_radix(255 as T, 16u), ~"ff");
|
|
|
|
assert_eq!(to_str_radix(0xff as T, 10u), ~"255");
|
2013-04-15 10:08:52 -05:00
|
|
|
}
|
2012-06-04 20:05:34 -05:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
#[test]
|
|
|
|
pub fn test_from_str() {
|
2013-05-23 11:39:17 -05:00
|
|
|
assert_eq!(from_str("0"), Some(0u as T));
|
|
|
|
assert_eq!(from_str("3"), Some(3u as T));
|
|
|
|
assert_eq!(from_str("10"), Some(10u as T));
|
|
|
|
assert_eq!(u32::from_str("123456789"), Some(123456789 as u32));
|
|
|
|
assert_eq!(from_str("00100"), Some(100u as T));
|
|
|
|
|
|
|
|
assert!(from_str("").is_none());
|
|
|
|
assert!(from_str(" ").is_none());
|
|
|
|
assert!(from_str("x").is_none());
|
2013-04-15 10:08:52 -05:00
|
|
|
}
|
2012-05-16 00:50:29 -05:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
#[test]
|
|
|
|
pub fn test_parse_bytes() {
|
|
|
|
use str::to_bytes;
|
2013-05-23 11:39:17 -05:00
|
|
|
assert_eq!(parse_bytes(to_bytes("123"), 10u), Some(123u as T));
|
|
|
|
assert_eq!(parse_bytes(to_bytes("1001"), 2u), Some(9u as T));
|
|
|
|
assert_eq!(parse_bytes(to_bytes("123"), 8u), Some(83u as T));
|
|
|
|
assert_eq!(u16::parse_bytes(to_bytes("123"), 16u), Some(291u as u16));
|
|
|
|
assert_eq!(u16::parse_bytes(to_bytes("ffff"), 16u), Some(65535u as u16));
|
|
|
|
assert_eq!(parse_bytes(to_bytes("z"), 36u), Some(35u as T));
|
|
|
|
|
|
|
|
assert!(parse_bytes(to_bytes("Z"), 10u).is_none());
|
|
|
|
assert!(parse_bytes(to_bytes("_"), 2u).is_none());
|
2013-04-15 10:08:52 -05:00
|
|
|
}
|
2012-06-04 17:22:40 -05:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
#[test]
|
|
|
|
fn test_uint_to_str_overflow() {
|
|
|
|
let mut u8_val: u8 = 255_u8;
|
2013-04-18 10:37:21 -05:00
|
|
|
assert_eq!(u8::to_str(u8_val), ~"255");
|
2013-01-24 14:47:57 -06:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
u8_val += 1 as u8;
|
2013-04-18 10:37:21 -05:00
|
|
|
assert_eq!(u8::to_str(u8_val), ~"0");
|
2013-01-24 14:47:57 -06:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
let mut u16_val: u16 = 65_535_u16;
|
2013-04-18 10:37:21 -05:00
|
|
|
assert_eq!(u16::to_str(u16_val), ~"65535");
|
2013-01-24 14:47:57 -06:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
u16_val += 1 as u16;
|
2013-04-18 10:37:21 -05:00
|
|
|
assert_eq!(u16::to_str(u16_val), ~"0");
|
2013-01-24 14:47:57 -06:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
let mut u32_val: u32 = 4_294_967_295_u32;
|
2013-04-18 10:37:21 -05:00
|
|
|
assert_eq!(u32::to_str(u32_val), ~"4294967295");
|
2013-01-24 14:47:57 -06:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
u32_val += 1 as u32;
|
2013-04-18 10:37:21 -05:00
|
|
|
assert_eq!(u32::to_str(u32_val), ~"0");
|
2013-01-24 14:47:57 -06:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
let mut u64_val: u64 = 18_446_744_073_709_551_615_u64;
|
2013-04-18 10:37:21 -05:00
|
|
|
assert_eq!(u64::to_str(u64_val), ~"18446744073709551615");
|
2013-01-24 14:47:57 -06:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
u64_val += 1 as u64;
|
2013-04-18 10:37:21 -05:00
|
|
|
assert_eq!(u64::to_str(u64_val), ~"0");
|
2013-04-15 10:08:52 -05:00
|
|
|
}
|
2013-01-24 14:47:57 -06:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
#[test]
|
|
|
|
fn test_uint_from_str_overflow() {
|
|
|
|
let mut u8_val: u8 = 255_u8;
|
2013-05-23 11:39:17 -05:00
|
|
|
assert_eq!(u8::from_str("255"), Some(u8_val));
|
|
|
|
assert!(u8::from_str("256").is_none());
|
2013-01-24 14:47:57 -06:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
u8_val += 1 as u8;
|
2013-05-23 11:39:17 -05:00
|
|
|
assert_eq!(u8::from_str("0"), Some(u8_val));
|
|
|
|
assert!(u8::from_str("-1").is_none());
|
2013-01-24 14:47:57 -06:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
let mut u16_val: u16 = 65_535_u16;
|
2013-05-23 11:39:17 -05:00
|
|
|
assert_eq!(u16::from_str("65535"), Some(u16_val));
|
|
|
|
assert!(u16::from_str("65536").is_none());
|
2013-01-24 14:47:57 -06:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
u16_val += 1 as u16;
|
2013-05-23 11:39:17 -05:00
|
|
|
assert_eq!(u16::from_str("0"), Some(u16_val));
|
|
|
|
assert!(u16::from_str("-1").is_none());
|
2013-01-24 14:47:57 -06:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
let mut u32_val: u32 = 4_294_967_295_u32;
|
2013-05-23 11:39:17 -05:00
|
|
|
assert_eq!(u32::from_str("4294967295"), Some(u32_val));
|
|
|
|
assert!(u32::from_str("4294967296").is_none());
|
2013-01-24 14:47:57 -06:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
u32_val += 1 as u32;
|
2013-05-23 11:39:17 -05:00
|
|
|
assert_eq!(u32::from_str("0"), Some(u32_val));
|
|
|
|
assert!(u32::from_str("-1").is_none());
|
2013-01-24 14:47:57 -06:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
let mut u64_val: u64 = 18_446_744_073_709_551_615_u64;
|
2013-05-23 11:39:17 -05:00
|
|
|
assert_eq!(u64::from_str("18446744073709551615"), Some(u64_val));
|
|
|
|
assert!(u64::from_str("18446744073709551616").is_none());
|
2013-01-24 14:47:57 -06:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
u64_val += 1 as u64;
|
2013-05-23 11:39:17 -05:00
|
|
|
assert_eq!(u64::from_str("0"), Some(u64_val));
|
|
|
|
assert!(u64::from_str("-1").is_none());
|
2013-04-15 10:08:52 -05:00
|
|
|
}
|
2013-01-24 14:47:57 -06:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
#[test]
|
|
|
|
#[should_fail]
|
|
|
|
#[ignore(cfg(windows))]
|
|
|
|
pub fn to_str_radix1() {
|
|
|
|
uint::to_str_radix(100u, 1u);
|
|
|
|
}
|
2012-06-04 17:22:40 -05:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
#[test]
|
|
|
|
#[should_fail]
|
|
|
|
#[ignore(cfg(windows))]
|
|
|
|
pub fn to_str_radix37() {
|
|
|
|
uint::to_str_radix(100u, 37u);
|
|
|
|
}
|
A new `times` method on numeric types
This method is intended to elegantly subsume two common iteration functions.
The first is `iter::range`, which is used identically to the method introduced
in this commit, but currently works only on uints. The second is a common case
of `{int, i8, uint, etc.}::range`, in the case where the inductive variable is
ignored. Compare the usage of the three:
```
for iter::range(100u) {
// do whatever
}
for int::range(0, 100) |_i| {
// do whatever
}
for 100.times {
// do whatever
}
```
I feel that the latter reads much more nicely than the first two approaches,
and unlike the first two the new method allows the user to ignore the specific
type of the number (ineed, if we're throwing away the inductive variable, who
cares what type it is?). A minor benefit is that this new method will be
somewhat familiar to users of Ruby, from which we borrow the name "times".
2012-07-05 21:12:26 -05:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
#[test]
|
|
|
|
pub fn test_ranges() {
|
|
|
|
let mut l = ~[];
|
2013-01-10 14:18:01 -06:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
for range(0,3) |i| {
|
|
|
|
l.push(i);
|
|
|
|
}
|
|
|
|
for range_rev(13,10) |i| {
|
|
|
|
l.push(i);
|
|
|
|
}
|
|
|
|
for range_step(20,26,2) |i| {
|
|
|
|
l.push(i);
|
|
|
|
}
|
|
|
|
for range_step(36,30,-2) |i| {
|
|
|
|
l.push(i);
|
|
|
|
}
|
|
|
|
for range_step(max_value - 2, max_value, 2) |i| {
|
|
|
|
l.push(i);
|
|
|
|
}
|
|
|
|
for range_step(max_value - 3, max_value, 2) |i| {
|
|
|
|
l.push(i);
|
|
|
|
}
|
|
|
|
for range_step(min_value + 2, min_value, -2) |i| {
|
|
|
|
l.push(i);
|
|
|
|
}
|
|
|
|
for range_step(min_value + 3, min_value, -2) |i| {
|
|
|
|
l.push(i);
|
|
|
|
}
|
2013-01-10 14:18:01 -06:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
assert_eq!(l, ~[0,1,2,
|
|
|
|
13,12,11,
|
|
|
|
20,22,24,
|
|
|
|
36,34,32,
|
|
|
|
max_value-2,
|
|
|
|
max_value-3,max_value-1,
|
|
|
|
min_value+2,
|
|
|
|
min_value+3,min_value+1]);
|
|
|
|
|
|
|
|
// None of the `fail`s should execute.
|
|
|
|
for range(0,0) |_i| {
|
2013-05-05 17:18:51 -05:00
|
|
|
fail!("unreachable");
|
2013-04-15 10:08:52 -05:00
|
|
|
}
|
|
|
|
for range_rev(0,0) |_i| {
|
2013-05-05 17:18:51 -05:00
|
|
|
fail!("unreachable");
|
2013-04-15 10:08:52 -05:00
|
|
|
}
|
|
|
|
for range_step(10,0,1) |_i| {
|
2013-05-05 17:18:51 -05:00
|
|
|
fail!("unreachable");
|
2013-04-15 10:08:52 -05:00
|
|
|
}
|
|
|
|
for range_step(0,1,-10) |_i| {
|
2013-05-05 17:18:51 -05:00
|
|
|
fail!("unreachable");
|
2013-04-15 10:08:52 -05:00
|
|
|
}
|
2013-01-10 14:18:01 -06:00
|
|
|
}
|
2013-04-15 10:08:52 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[should_fail]
|
|
|
|
#[ignore(cfg(windows))]
|
|
|
|
fn test_range_step_zero_step_up() {
|
|
|
|
for range_step(0,10,0) |_i| {}
|
2013-01-10 14:18:01 -06:00
|
|
|
}
|
2013-04-15 10:08:52 -05:00
|
|
|
#[test]
|
|
|
|
#[should_fail]
|
|
|
|
#[ignore(cfg(windows))]
|
|
|
|
fn test_range_step_zero_step_down() {
|
|
|
|
for range_step(0,-10,0) |_i| {}
|
2013-01-10 14:18:01 -06:00
|
|
|
}
|
2013-04-18 17:53:29 -05:00
|
|
|
}
|