Cleanups in the int and uint templates.

This commit is contained in:
Graydon Hoare 2012-08-02 17:14:26 -07:00
parent 4019d3a86b
commit b14a6aca9f
12 changed files with 122 additions and 106 deletions

View File

@ -12,8 +12,12 @@ export compl;
export abs;
export parse_buf, from_str, to_str, to_str_bytes, str;
export num, ord, eq, times, timesi;
export bits, bytes;
const min_value: T = -1 as T << (inst::bits - 1 as T);
const bits : uint = inst::bits;
const bytes : uint = (inst::bits / 8);
const min_value: T = (-1 as T) << (bits - 1);
const max_value: T = min_value - 1 as T;
pure fn min(&&x: T, &&y: T) -> T { if x < y { x } else { y } }
@ -58,6 +62,68 @@ pure fn abs(i: T) -> T {
if is_negative(i) { -i } else { i }
}
impl ord of ord for T {
pure fn lt(&&other: T) -> bool {
return self < other;
}
}
impl eq of eq for T {
pure fn eq(&&other: T) -> bool {
return self == other;
}
}
impl num of num::num for T {
pure fn add(&&other: T) -> T { return self + other; }
pure fn sub(&&other: T) -> T { return self - other; }
pure fn mul(&&other: T) -> T { return self * other; }
pure fn div(&&other: T) -> T { return self / other; }
pure fn modulo(&&other: T) -> T { return self % other; }
pure fn neg() -> T { return -self; }
pure fn to_int() -> int { return self as int; }
pure fn from_int(n: int) -> T { return n as T; }
}
impl times of iter::times for T {
#[inline(always)]
#[doc = "A convenience form for basic iteration. Given a variable `x` \
of any numeric type, the expression `for x.times { /* anything */ }` \
will execute the given function exactly x times. If we assume that \
`x` is an int, this is functionally equivalent to \
`for int::range(0, x) |_i| { /* anything */ }`."]
fn times(it: fn() -> bool) {
if self < 0 {
fail fmt!{"The .times method expects a nonnegative number, \
but found %?", self};
}
let mut i = self;
while i > 0 {
if !it() { break }
i -= 1;
}
}
}
impl timesi of iter::timesi for T {
#[inline(always)]
/// Like `times`, but provides an index
fn timesi(it: fn(uint) -> bool) {
let slf = self as uint;
if slf < 0u {
fail fmt!{"The .timesi method expects a nonnegative number, \
but found %?", self};
}
let mut i = 0u;
while i < slf {
if !it(i) { break }
i += 1u;
}
}
}
/**
* Parse a buffer of bytes
*
@ -111,67 +177,6 @@ fn to_str_bytes<U>(n: T, radix: uint, f: fn(v: &[u8]) -> U) -> U {
/// Convert to a string
fn str(i: T) -> ~str { return to_str(i, 10u); }
impl ord of ord for T {
pure fn lt(&&other: T) -> bool {
return self < other;
}
}
impl eq of eq for T {
pure fn eq(&&other: T) -> bool {
return self == other;
}
}
impl num of num::num for T {
pure fn add(&&other: T) -> T { return self + other; }
pure fn sub(&&other: T) -> T { return self - other; }
pure fn mul(&&other: T) -> T { return self * other; }
pure fn div(&&other: T) -> T { return self / other; }
pure fn modulo(&&other: T) -> T { return self % other; }
pure fn neg() -> T { return -self; }
pure fn to_int() -> int { return self as int; }
pure fn from_int(n: int) -> T { return n as T; }
}
impl times of iter::times for T {
#[inline(always)]
#[doc = "A convenience form for basic iteration. Given a variable `x` \
of any numeric type, the expression `for x.times { /* anything */ }` \
will execute the given function exactly x times. If we assume that \
`x` is an int, this is functionally equivalent to \
`for int::range(0, x) |_i| { /* anything */ }`."]
fn times(it: fn() -> bool) {
if self < 0 {
fail fmt!{"The .times method expects a nonnegative number, \
but found %?", self};
}
let mut i = self;
while i > 0 {
if !it() { break }
i -= 1;
}
}
}
impl timesi of iter::timesi for T {
#[inline(always)]
/// Like `times`, but provides an index
fn timesi(it: fn(uint) -> bool) {
let slf = self as uint;
if slf < 0u {
fail fmt!{"The .timesi method expects a nonnegative number, \
but found %?", self};
}
let mut i = 0u;
while i < slf {
if !it(i) { break }
i += 1u;
}
}
}
// FIXME: Has alignment issues on windows and 32-bit linux (#2609)
#[test]
#[ignore]

View File

@ -1,3 +1,2 @@
type T = i16;
const bits: T = 16 as T;
const bits: uint = u16::bits;

View File

@ -1,3 +1,2 @@
type T = i32;
const bits: T = 32 as T;
const bits: uint = u32::bits;

View File

@ -1,3 +1,2 @@
type T = i64;
const bits: T = 64 as T;
const bits: uint = u64::bits;

View File

@ -1,3 +1,2 @@
type T = i8;
const bits: T = 8 as T;
const bits: uint = u8::bits;

View File

@ -1,13 +1,11 @@
type T = int;
#[cfg(target_arch = "x86")]
const bits: T = 32 as T;
#[cfg(target_arch = "x86_64")]
const bits: T = 64 as T;
const bits: uint = uint::bits;
/// Produce a uint suitable for use in a hash table
pure fn hash(x: &int) -> uint { *x as uint }
pure fn hash(x: &int) -> uint {
let u : uint = *x as uint;
uint::hash(&u)
}
/// Returns `base` raised to the power of `exponent`
fn pow(base: int, exponent: uint) -> int {

View File

@ -12,6 +12,10 @@ export compl;
export to_str, to_str_bytes;
export from_str, from_str_radix, str, parse_buf;
export num, ord, eq, times, timesi;
export bits, bytes;
const bits : uint = inst::bits;
const bytes : uint = (inst::bits / 8);
const min_value: T = 0 as T;
const max_value: T = 0 as T - 1 as T;
@ -76,34 +80,6 @@ impl num of num::num for T {
pure fn from_int(n: int) -> T { return n as T; }
}
/**
* Parse a buffer of bytes
*
* # Arguments
*
* * buf - A byte buffer
* * radix - The base of the number
*
* # Failure
*
* `buf` must not be empty
*/
fn parse_buf(buf: ~[u8], radix: uint) -> option<T> {
if vec::len(buf) == 0u { return none; }
let mut i = vec::len(buf) - 1u;
let mut power = 1u as T;
let mut n = 0u as T;
loop {
alt char::to_digit(buf[i] as char, radix) {
some(d) { n += d as T * power; }
none { return none; }
}
power *= radix as T;
if i == 0u { return some(n); }
i -= 1u;
};
}
impl times of iter::times for T {
#[inline(always)]
#[doc = "A convenience form for basic iteration. Given a variable `x` \
@ -133,6 +109,34 @@ impl timesi of iter::timesi for T {
}
}
/**
* Parse a buffer of bytes
*
* # Arguments
*
* * buf - A byte buffer
* * radix - The base of the number
*
* # Failure
*
* `buf` must not be empty
*/
fn parse_buf(buf: ~[u8], radix: uint) -> option<T> {
if vec::len(buf) == 0u { return none; }
let mut i = vec::len(buf) - 1u;
let mut power = 1u as T;
let mut n = 0u as T;
loop {
alt char::to_digit(buf[i] as char, radix) {
some(d) { n += d as T * power; }
none { return none; }
}
power *= radix as T;
if i == 0u { return some(n); }
i -= 1u;
};
}
/// Parse a string to an int
fn from_str(s: ~str) -> option<T> { parse_buf(str::bytes(s), 10u) }

View File

@ -1 +1,2 @@
type T = u16;
const bits: uint = 16;

View File

@ -1 +1,2 @@
type T = u32;
const bits: uint = 32;

View File

@ -1 +1,2 @@
type T = u64;
const bits: uint = 64;

View File

@ -1,4 +1,5 @@
type T = u8;
const bits: uint = 8;
// Type-specific functions here. These must be reexported by the
// parent module so that they appear in core::u8 and not core::u8::u8;

View File

@ -1,5 +1,12 @@
type T = uint;
#[cfg(target_arch = "x86")]
#[cfg(target_arch = "arm")]
const bits: uint = 32;
#[cfg(target_arch = "x86_64")]
const bits: uint = 64;
/**
* Divide two numbers, return the result, rounded up.
*
@ -54,7 +61,9 @@ pure fn div_round(x: uint, y: uint) -> uint {
pure fn div_floor(x: uint, y: uint) -> uint { return x / y; }
/// Produce a uint suitable for use in a hash table
pure fn hash(x: &uint) -> uint { *x }
pure fn hash(x: &uint) -> uint {
hash::hash_uint(*x) as uint
}
/**
* Iterate over the range [`lo`..`hi`), or stop when requested