From 0369a41f0e668eda5622055253b91dbb5254f0b4 Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Tue, 29 Oct 2013 17:22:49 +1100 Subject: Rename files to match current recommendations. New standards have arisen in recent months, mostly for the use of rustpkg, but the main Rust codebase has not been altered to match these new specifications. This changeset rectifies most of these issues. - Renamed the crate source files `src/libX/X.rs` to `lib.rs`, for consistency with current styles; this affects extra, rustc, rustdoc, rustpkg, rustuv, std, syntax. - Renamed `X/X.rs` to `X/mod.rs,` as is now recommended style, for `std::num` and `std::terminfo`. - Shifted `src/libstd/str/ascii.rs` out of the otherwise unused `str` directory, to be consistent with its import path of `std::ascii`; libstd is flat at present so it's more appropriate thus. While this removes some `#[path = "..."]` directives, it does not remove all of them, and leaves certain other inconsistencies, such as `std::u8` et al. which are actually stored in `src/libstd/num/` (one subdirectory down). No quorum has been reached on this issue, so I felt it best to leave them all alone at present. #9208 deals with the possibility of making libstd more hierarchical (such as changing the crate to match the current filesystem structure, which would make the module path `std::num::u8`). There is one thing remaining in which this repository is not rustpkg-compliant: rustpkg would have `src/std/` et al. rather than `src/libstd/` et al. I have not endeavoured to change that at this point as it would guarantee prompt bitrot and confusion. A change of that magnitude needs to be discussed first. --- src/libstd/ascii.rs | 582 +++++++++++++++++ src/libstd/lib.rs | 230 +++++++ src/libstd/num/mod.rs | 1596 +++++++++++++++++++++++++++++++++++++++++++++++ src/libstd/num/num.rs | 1596 ----------------------------------------------- src/libstd/std.rs | 232 ------- src/libstd/str/ascii.rs | 582 ----------------- 6 files changed, 2408 insertions(+), 2410 deletions(-) create mode 100644 src/libstd/ascii.rs create mode 100644 src/libstd/lib.rs create mode 100644 src/libstd/num/mod.rs delete mode 100644 src/libstd/num/num.rs delete mode 100644 src/libstd/std.rs delete mode 100644 src/libstd/str/ascii.rs (limited to 'src/libstd') diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs new file mode 100644 index 00000000000..ec2d7566177 --- /dev/null +++ b/src/libstd/ascii.rs @@ -0,0 +1,582 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Operations on ASCII strings and characters. + +use to_str::{ToStr,ToStrConsume}; +use str; +use str::StrSlice; +use str::OwnedStr; +use container::Container; +use cast; +use iter::Iterator; +use vec::{CopyableVector, ImmutableVector, MutableVector}; +use to_bytes::IterBytes; +use option::{Some, None}; + +/// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero. +#[deriving(Clone, Eq, Ord, TotalOrd, TotalEq)] +pub struct Ascii { priv chr: u8 } + +impl Ascii { + /// Converts a ascii character into a `u8`. + #[inline] + pub fn to_byte(self) -> u8 { + self.chr + } + + /// Converts a ascii character into a `char`. + #[inline] + pub fn to_char(self) -> char { + self.chr as char + } + + /// Convert to lowercase. + #[inline] + pub fn to_lower(self) -> Ascii { + Ascii{chr: ASCII_LOWER_MAP[self.chr]} + } + + /// Convert to uppercase. + #[inline] + pub fn to_upper(self) -> Ascii { + Ascii{chr: ASCII_UPPER_MAP[self.chr]} + } + + /// Compares two ascii characters of equality, ignoring case. + #[inline] + pub fn eq_ignore_case(self, other: Ascii) -> bool { + ASCII_LOWER_MAP[self.chr] == ASCII_LOWER_MAP[other.chr] + } +} + +impl ToStr for Ascii { + #[inline] + fn to_str(&self) -> ~str { + // self.chr is always a valid utf8 byte, no need for the check + unsafe { str::raw::from_byte(self.chr) } + } +} + +/// Trait for converting into an ascii type. +pub trait AsciiCast { + /// Convert to an ascii type + fn to_ascii(&self) -> T; + + /// Convert to an ascii type, not doing any range asserts + unsafe fn to_ascii_nocheck(&self) -> T; + + /// Check if convertible to ascii + fn is_ascii(&self) -> bool; +} + +impl<'self> AsciiCast<&'self[Ascii]> for &'self [u8] { + #[inline] + fn to_ascii(&self) -> &'self[Ascii] { + assert!(self.is_ascii()); + unsafe {self.to_ascii_nocheck()} + } + + #[inline] + unsafe fn to_ascii_nocheck(&self) -> &'self[Ascii] { + cast::transmute(*self) + } + + #[inline] + fn is_ascii(&self) -> bool { + for b in self.iter() { + if !b.is_ascii() { return false; } + } + true + } +} + +impl<'self> AsciiCast<&'self [Ascii]> for &'self str { + #[inline] + fn to_ascii(&self) -> &'self [Ascii] { + assert!(self.is_ascii()); + unsafe { self.to_ascii_nocheck() } + } + + #[inline] + unsafe fn to_ascii_nocheck(&self) -> &'self [Ascii] { + cast::transmute(*self) + } + + #[inline] + fn is_ascii(&self) -> bool { + self.byte_iter().all(|b| b.is_ascii()) + } +} + +impl AsciiCast for u8 { + #[inline] + fn to_ascii(&self) -> Ascii { + assert!(self.is_ascii()); + unsafe {self.to_ascii_nocheck()} + } + + #[inline] + unsafe fn to_ascii_nocheck(&self) -> Ascii { + Ascii{ chr: *self } + } + + #[inline] + fn is_ascii(&self) -> bool { + *self & 128 == 0u8 + } +} + +impl AsciiCast for char { + #[inline] + fn to_ascii(&self) -> Ascii { + assert!(self.is_ascii()); + unsafe {self.to_ascii_nocheck()} + } + + #[inline] + unsafe fn to_ascii_nocheck(&self) -> Ascii { + Ascii{ chr: *self as u8 } + } + + #[inline] + fn is_ascii(&self) -> bool { + *self as u32 - ('\x7F' as u32 & *self as u32) == 0 + } +} + +/// Trait for copyless casting to an ascii vector. +pub trait OwnedAsciiCast { + /// Take ownership and cast to an ascii vector without trailing zero element. + fn into_ascii(self) -> ~[Ascii]; + + /// Take ownership and cast to an ascii vector without trailing zero element. + /// Does not perform validation checks. + unsafe fn into_ascii_nocheck(self) -> ~[Ascii]; +} + +impl OwnedAsciiCast for ~[u8] { + #[inline] + fn into_ascii(self) -> ~[Ascii] { + assert!(self.is_ascii()); + unsafe {self.into_ascii_nocheck()} + } + + #[inline] + unsafe fn into_ascii_nocheck(self) -> ~[Ascii] { + cast::transmute(self) + } +} + +impl OwnedAsciiCast for ~str { + #[inline] + fn into_ascii(self) -> ~[Ascii] { + assert!(self.is_ascii()); + unsafe {self.into_ascii_nocheck()} + } + + #[inline] + unsafe fn into_ascii_nocheck(self) -> ~[Ascii] { + cast::transmute(self) + } +} + +/// Trait for converting an ascii type to a string. Needed to convert `&[Ascii]` to `~str` +pub trait AsciiStr { + /// Convert to a string. + fn to_str_ascii(&self) -> ~str; + + /// Convert to vector representing a lower cased ascii string. + fn to_lower(&self) -> ~[Ascii]; + + /// Convert to vector representing a upper cased ascii string. + fn to_upper(&self) -> ~[Ascii]; + + /// Compares two Ascii strings ignoring case + fn eq_ignore_case(self, other: &[Ascii]) -> bool; +} + +impl<'self> AsciiStr for &'self [Ascii] { + #[inline] + fn to_str_ascii(&self) -> ~str { + let cpy = self.to_owned(); + unsafe { cast::transmute(cpy) } + } + + #[inline] + fn to_lower(&self) -> ~[Ascii] { + self.map(|a| a.to_lower()) + } + + #[inline] + fn to_upper(&self) -> ~[Ascii] { + self.map(|a| a.to_upper()) + } + + #[inline] + fn eq_ignore_case(self, other: &[Ascii]) -> bool { + do self.iter().zip(other.iter()).all |(&a, &b)| { a.eq_ignore_case(b) } + } +} + +impl ToStrConsume for ~[Ascii] { + #[inline] + fn into_str(self) -> ~str { + unsafe { cast::transmute(self) } + } +} + +impl IterBytes for Ascii { + #[inline] + fn iter_bytes(&self, _lsb0: bool, f: &fn(buf: &[u8]) -> bool) -> bool { + f([self.to_byte()]) + } +} + +/// Trait to convert to a owned byte array by consuming self +pub trait ToBytesConsume { + /// Converts to a owned byte array by consuming self + fn into_bytes(self) -> ~[u8]; +} + +impl ToBytesConsume for ~[Ascii] { + fn into_bytes(self) -> ~[u8] { + unsafe { cast::transmute(self) } + } +} + +/// Extension methods for ASCII-subset only operations on owned strings +pub trait OwnedStrAsciiExt { + /// Convert the string to ASCII upper case: + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', + /// but non-ASCII letters are unchanged. + fn into_ascii_upper(self) -> ~str; + + /// Convert the string to ASCII lower case: + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', + /// but non-ASCII letters are unchanged. + fn into_ascii_lower(self) -> ~str; +} + +/// Extension methods for ASCII-subset only operations on string slices +pub trait StrAsciiExt { + /// Makes a copy of the string in ASCII upper case: + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', + /// but non-ASCII letters are unchanged. + fn to_ascii_upper(&self) -> ~str; + + /// Makes a copy of the string in ASCII lower case: + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', + /// but non-ASCII letters are unchanged. + fn to_ascii_lower(&self) -> ~str; + + /// Check that two strings are an ASCII case-insensitive match. + /// Same as `to_ascii_lower(a) == to_ascii_lower(b)`, + /// but without allocating and copying temporary strings. + fn eq_ignore_ascii_case(&self, other: &str) -> bool; +} + +impl<'self> StrAsciiExt for &'self str { + #[inline] + fn to_ascii_upper(&self) -> ~str { + unsafe { str_copy_map_bytes(*self, ASCII_UPPER_MAP) } + } + + #[inline] + fn to_ascii_lower(&self) -> ~str { + unsafe { str_copy_map_bytes(*self, ASCII_LOWER_MAP) } + } + + #[inline] + fn eq_ignore_ascii_case(&self, other: &str) -> bool { + self.len() == other.len() && self.as_bytes().iter().zip(other.as_bytes().iter()).all( + |(byte_self, byte_other)| ASCII_LOWER_MAP[*byte_self] == ASCII_LOWER_MAP[*byte_other]) + } +} + +impl OwnedStrAsciiExt for ~str { + #[inline] + fn into_ascii_upper(self) -> ~str { + unsafe { str_map_bytes(self, ASCII_UPPER_MAP) } + } + + #[inline] + fn into_ascii_lower(self) -> ~str { + unsafe { str_map_bytes(self, ASCII_LOWER_MAP) } + } +} + +#[inline] +unsafe fn str_map_bytes(string: ~str, map: &'static [u8]) -> ~str { + let mut bytes = string.into_bytes(); + + for b in bytes.mut_iter() { + *b = map[*b]; + } + + str::raw::from_utf8_owned(bytes) +} + +#[inline] +unsafe fn str_copy_map_bytes(string: &str, map: &'static [u8]) -> ~str { + let bytes = string.byte_iter().map(|b| map[b]).to_owned_vec(); + + str::raw::from_utf8_owned(bytes) +} + +static ASCII_LOWER_MAP: &'static [u8] = &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, +]; + +static ASCII_UPPER_MAP: &'static [u8] = &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, +]; + + +#[cfg(test)] +mod tests { + use super::*; + use str::from_char; + use char::from_u32; + + macro_rules! v2ascii ( + ( [$($e:expr),*]) => ( [$(Ascii{chr:$e}),*]); + (~[$($e:expr),*]) => (~[$(Ascii{chr:$e}),*]); + ) + + #[test] + fn test_ascii() { + assert_eq!(65u8.to_ascii().to_byte(), 65u8); + assert_eq!(65u8.to_ascii().to_char(), 'A'); + assert_eq!('A'.to_ascii().to_char(), 'A'); + assert_eq!('A'.to_ascii().to_byte(), 65u8); + + assert_eq!('A'.to_ascii().to_lower().to_char(), 'a'); + assert_eq!('Z'.to_ascii().to_lower().to_char(), 'z'); + assert_eq!('a'.to_ascii().to_upper().to_char(), 'A'); + assert_eq!('z'.to_ascii().to_upper().to_char(), 'Z'); + + assert_eq!('@'.to_ascii().to_lower().to_char(), '@'); + assert_eq!('['.to_ascii().to_lower().to_char(), '['); + assert_eq!('`'.to_ascii().to_upper().to_char(), '`'); + assert_eq!('{'.to_ascii().to_upper().to_char(), '{'); + + assert!("banana".iter().all(|c| c.is_ascii())); + assert!(!"ประเทศไทย中华Việt Nam".iter().all(|c| c.is_ascii())); + } + + #[test] + fn test_ascii_vec() { + assert_eq!((&[40u8, 32u8, 59u8]).to_ascii(), v2ascii!([40, 32, 59])); + assert_eq!("( ;".to_ascii(), v2ascii!([40, 32, 59])); + // FIXME: #5475 borrowchk error, owned vectors do not live long enough + // if chained-from directly + let v = ~[40u8, 32u8, 59u8]; assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59])); + let v = ~"( ;"; assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59])); + + assert_eq!("abCDef&?#".to_ascii().to_lower().to_str_ascii(), ~"abcdef&?#"); + assert_eq!("abCDef&?#".to_ascii().to_upper().to_str_ascii(), ~"ABCDEF&?#"); + + assert_eq!("".to_ascii().to_lower().to_str_ascii(), ~""); + assert_eq!("YMCA".to_ascii().to_lower().to_str_ascii(), ~"ymca"); + assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().to_str_ascii(), ~"ABCDEFXYZ:.;"); + + assert!("aBcDeF&?#".to_ascii().eq_ignore_case("AbCdEf&?#".to_ascii())); + + assert!("".is_ascii()); + assert!("a".is_ascii()); + assert!(!"\u2009".is_ascii()); + + } + + #[test] + fn test_owned_ascii_vec() { + assert_eq!((~"( ;").into_ascii(), v2ascii!(~[40, 32, 59])); + assert_eq!((~[40u8, 32u8, 59u8]).into_ascii(), v2ascii!(~[40, 32, 59])); + } + + #[test] + fn test_ascii_to_str() { assert_eq!(v2ascii!([40, 32, 59]).to_str_ascii(), ~"( ;"); } + + #[test] + fn test_ascii_into_str() { + assert_eq!(v2ascii!(~[40, 32, 59]).into_str(), ~"( ;"); + } + + #[test] + fn test_ascii_to_bytes() { + assert_eq!(v2ascii!(~[40, 32, 59]).into_bytes(), ~[40u8, 32u8, 59u8]); + } + + #[test] #[should_fail] + fn test_ascii_vec_fail_u8_slice() { (&[127u8, 128u8, 255u8]).to_ascii(); } + + #[test] #[should_fail] + fn test_ascii_vec_fail_str_slice() { "zoä华".to_ascii(); } + + #[test] #[should_fail] + fn test_ascii_fail_u8_slice() { 255u8.to_ascii(); } + + #[test] #[should_fail] + fn test_ascii_fail_char_slice() { 'λ'.to_ascii(); } + + #[test] + fn test_to_ascii_upper() { + assert_eq!("url()URL()uRl()ürl".to_ascii_upper(), ~"URL()URL()URL()üRL"); + assert_eq!("hıKß".to_ascii_upper(), ~"HıKß"); + + let mut i = 0; + while i <= 500 { + let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 } + else { i }; + assert_eq!(from_char(from_u32(i).unwrap()).to_ascii_upper(), + from_char(from_u32(upper).unwrap())) + i += 1; + } + } + + #[test] + fn test_to_ascii_lower() { + assert_eq!("url()URL()uRl()Ürl".to_ascii_lower(), ~"url()url()url()Ürl"); + // Dotted capital I, Kelvin sign, Sharp S. + assert_eq!("HİKß".to_ascii_lower(), ~"hİKß"); + + let mut i = 0; + while i <= 500 { + let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } + else { i }; + assert_eq!(from_char(from_u32(i).unwrap()).to_ascii_lower(), + from_char(from_u32(lower).unwrap())) + i += 1; + } + } + + #[test] + fn test_into_ascii_upper() { + assert_eq!((~"url()URL()uRl()ürl").into_ascii_upper(), ~"URL()URL()URL()üRL"); + assert_eq!((~"hıKß").into_ascii_upper(), ~"HıKß"); + + let mut i = 0; + while i <= 500 { + let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 } + else { i }; + assert_eq!(from_char(from_u32(i).unwrap()).into_ascii_upper(), + from_char(from_u32(upper).unwrap())) + i += 1; + } + } + + #[test] + fn test_into_ascii_lower() { + assert_eq!((~"url()URL()uRl()Ürl").into_ascii_lower(), ~"url()url()url()Ürl"); + // Dotted capital I, Kelvin sign, Sharp S. + assert_eq!((~"HİKß").into_ascii_lower(), ~"hİKß"); + + let mut i = 0; + while i <= 500 { + let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } + else { i }; + assert_eq!(from_char(from_u32(i).unwrap()).into_ascii_lower(), + from_char(from_u32(lower).unwrap())) + i += 1; + } + } + + #[test] + fn test_eq_ignore_ascii_case() { + assert!("url()URL()uRl()Ürl".eq_ignore_ascii_case("url()url()url()Ürl")); + assert!(!"Ürl".eq_ignore_ascii_case("ürl")); + // Dotted capital I, Kelvin sign, Sharp S. + assert!("HİKß".eq_ignore_ascii_case("hİKß")); + assert!(!"İ".eq_ignore_ascii_case("i")); + assert!(!"K".eq_ignore_ascii_case("k")); + assert!(!"ß".eq_ignore_ascii_case("s")); + + let mut i = 0; + while i <= 500 { + let c = i; + let lower = if 'A' as u32 <= c && c <= 'Z' as u32 { c + 'a' as u32 - 'A' as u32 } + else { c }; + assert!(from_char(from_u32(i).unwrap()). + eq_ignore_ascii_case(from_char(from_u32(lower).unwrap()))); + i += 1; + } + } + + #[test] + fn test_to_str() { + let s = Ascii{ chr: 't' as u8 }.to_str(); + assert_eq!(s, ~"t"); + } + + +} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs new file mode 100644 index 00000000000..68f13dc8992 --- /dev/null +++ b/src/libstd/lib.rs @@ -0,0 +1,230 @@ +// Copyright 2012-2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! # The Rust standard library +//! +//! The Rust standard library is a group of interrelated modules defining +//! the core language traits, operations on built-in data types, collections, +//! platform abstractions, the task scheduler, runtime support for language +//! features and other common functionality. +//! +//! `std` includes modules corresponding to each of the integer types, +//! each of the floating point types, the `bool` type, tuples, characters, +//! strings (`str`), vectors (`vec`), managed boxes (`managed`), owned +//! boxes (`owned`), and unsafe and borrowed pointers (`ptr`, `borrowed`). +//! Additionally, `std` provides pervasive types (`option` and `result`), +//! task creation and communication primitives (`task`, `comm`), platform +//! abstractions (`os` and `path`), basic I/O abstractions (`io`), common +//! traits (`kinds`, `ops`, `cmp`, `num`, `to_str`), and complete bindings +//! to the C standard library (`libc`). +//! +//! # Standard library injection and the Rust prelude +//! +//! `std` is imported at the topmost level of every crate by default, as +//! if the first line of each crate was +//! +//! extern mod std; +//! +//! This means that the contents of std can be accessed from any context +//! with the `std::` path prefix, as in `use std::vec`, `use std::task::spawn`, +//! etc. +//! +//! Additionally, `std` contains a `prelude` module that reexports many of the +//! most common types, traits and functions. The contents of the prelude are +//! imported into every *module* by default. Implicitly, all modules behave as if +//! they contained the following prologue: +//! +//! use std::prelude::*; + +#[link(name = "std", + vers = "0.9-pre", + uuid = "c70c24a7-5551-4f73-8e37-380b11d80be8", + url = "https://github.com/mozilla/rust/tree/master/src/libstd")]; + +#[comment = "The Rust standard library"]; +#[license = "MIT/ASL2"]; +#[crate_type = "lib"]; + +#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk.png", + html_favicon_url = "http://www.rust-lang.org/favicon.ico", + html_root_url = "http://static.rust-lang.org/doc/master")]; + +#[feature(macro_rules, globs, asm, managed_boxes)]; + +// Don't link to std. We are std. +#[no_std]; + +#[deny(non_camel_case_types)]; +#[deny(missing_doc)]; + +// When testing libstd, bring in libuv as the I/O backend so tests can print +// things and all of the std::rt::io tests have an I/O interface to run on top +// of +#[cfg(test)] extern mod rustuv(vers = "0.9-pre"); + +// Make extra accessible for benchmarking +#[cfg(test)] extern mod extra(vers = "0.9-pre"); + +// Make std testable by not duplicating lang items. See #2912 +#[cfg(test)] extern mod realstd(name = "std"); +#[cfg(test)] pub use kinds = realstd::kinds; +#[cfg(test)] pub use ops = realstd::ops; +#[cfg(test)] pub use cmp = realstd::cmp; + +// On Linux, link to the runtime with -lrt. +#[cfg(target_os = "linux")] +#[doc(hidden)] +pub mod linkhack { + #[link_args="-lrustrt -lrt"] + #[link_args = "-lpthread"] + extern { + } +} + +/* The Prelude. */ + +pub mod prelude; + + +/* Primitive types */ + +#[path = "num/int_macros.rs"] mod int_macros; +#[path = "num/uint_macros.rs"] mod uint_macros; + +#[path = "num/int.rs"] pub mod int; +#[path = "num/i8.rs"] pub mod i8; +#[path = "num/i16.rs"] pub mod i16; +#[path = "num/i32.rs"] pub mod i32; +#[path = "num/i64.rs"] pub mod i64; + +#[path = "num/uint.rs"] pub mod uint; +#[path = "num/u8.rs"] pub mod u8; +#[path = "num/u16.rs"] pub mod u16; +#[path = "num/u32.rs"] pub mod u32; +#[path = "num/u64.rs"] pub mod u64; + +#[path = "num/f32.rs"] pub mod f32; +#[path = "num/f64.rs"] pub mod f64; + +pub mod unit; +pub mod bool; +pub mod char; +pub mod tuple; + +pub mod vec; +pub mod at_vec; +pub mod str; + +pub mod ascii; +pub mod send_str; + +pub mod ptr; +pub mod owned; +pub mod managed; +pub mod borrow; +pub mod rc; + + +/* Core language traits */ + +#[cfg(not(test))] pub mod kinds; +#[cfg(not(test))] pub mod ops; +#[cfg(not(test))] pub mod cmp; + + +/* Common traits */ + +pub mod from_str; +pub mod num; +pub mod iter; +pub mod to_str; +pub mod to_bytes; +pub mod clone; +pub mod hash; +pub mod container; +pub mod default; +pub mod any; + + +/* Common data structures */ + +pub mod option; +pub mod result; +pub mod either; +pub mod hashmap; +pub mod cell; +pub mod trie; + + +/* Tasks and communication */ + +pub mod task; +pub mod comm; +pub mod select; +pub mod local_data; + + +/* Runtime and platform support */ + +pub mod libc; +pub mod c_str; +pub mod os; +pub mod path; +pub mod rand; +pub mod run; +pub mod cast; +pub mod fmt; +pub mod repr; +pub mod cleanup; +pub mod reflect; +pub mod condition; +pub mod logging; +pub mod util; +pub mod routine; +pub mod mem; + + +/* Unsupported interfaces */ + +// Private APIs +pub mod unstable; + + +/* For internal use, not exported */ + +mod unicode; +#[path = "num/cmath.rs"] +mod cmath; + +// FIXME #7809: This shouldn't be pub, and it should be reexported under 'unstable' +// but name resolution doesn't work without it being pub. +pub mod rt; + +// A curious inner-module that's not exported that contains the binding +// 'std' so that macro-expanded references to std::error and such +// can be resolved within libstd. +#[doc(hidden)] +mod std { + pub use clone; + pub use cmp; + pub use condition; + pub use fmt; + pub use kinds; + pub use local_data; + pub use logging; + pub use logging; + pub use option; + pub use os; + pub use rt; + pub use str; + pub use to_bytes; + pub use to_str; + pub use unstable; +} diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs new file mode 100644 index 00000000000..3097a8e138e --- /dev/null +++ b/src/libstd/num/mod.rs @@ -0,0 +1,1596 @@ +// Copyright 2012-2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Numeric traits and functions for generic mathematics. +//! +//! These are implemented for the primitive numeric types in `std::{u8, u16, +//! u32, u64, uint, i8, i16, i32, i64, int, f32, f64, float}`. + +#[allow(missing_doc)]; + +use clone::{Clone, DeepClone}; +use cmp::{Eq, ApproxEq, Ord}; +use ops::{Add, Sub, Mul, Div, Rem, Neg}; +use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr}; +use option::{Option, Some, None}; + +pub mod strconv; + +/// The base trait for numeric types +pub trait Num: Eq + Zero + One + + Neg + + Add + + Sub + + Mul + + Div + + Rem {} + +pub trait Orderable: Ord { + // These should be methods on `Ord`, with overridable default implementations. We don't want + // to encumber all implementors of Ord by requiring them to implement these functions, but at + // the same time we want to be able to take advantage of the speed of the specific numeric + // functions (like the `fmin` and `fmax` intrinsics). + fn min(&self, other: &Self) -> Self; + fn max(&self, other: &Self) -> Self; + fn clamp(&self, mn: &Self, mx: &Self) -> Self; +} + +/// Return the smaller number. +#[inline(always)] pub fn min(x: T, y: T) -> T { x.min(&y) } +/// Return the larger number. +#[inline(always)] pub fn max(x: T, y: T) -> T { x.max(&y) } +/// Returns the number constrained within the range `mn <= self <= mx`. +#[inline(always)] pub fn clamp(value: T, mn: T, mx: T) -> T { value.clamp(&mn, &mx) } + +pub trait Zero { + fn zero() -> Self; // FIXME (#5527): This should be an associated constant + fn is_zero(&self) -> bool; +} + +/// Returns `0` of appropriate type. +#[inline(always)] pub fn zero() -> T { Zero::zero() } + +pub trait One { + fn one() -> Self; // FIXME (#5527): This should be an associated constant +} + +/// Returns `1` of appropriate type. +#[inline(always)] pub fn one() -> T { One::one() } + +pub trait Signed: Num + + Neg { + fn abs(&self) -> Self; + fn abs_sub(&self, other: &Self) -> Self; + fn signum(&self) -> Self; + + fn is_positive(&self) -> bool; + fn is_negative(&self) -> bool; +} + +/// Computes the absolute value. +/// +/// For float, f32, and f64, `NaN` will be returned if the number is `NaN` +#[inline(always)] pub fn abs(value: T) -> T { value.abs() } +/// The positive difference of two numbers. +/// +/// Returns `zero` if the number is less than or equal to `other`, +/// otherwise the difference between `self` and `other` is returned. +#[inline(always)] pub fn abs_sub(x: T, y: T) -> T { x.abs_sub(&y) } +/// Returns the sign of the number. +/// +/// For float, f32, f64: +/// - `1.0` if the number is positive, `+0.0` or `INFINITY` +/// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY` +/// - `NAN` if the number is `NAN` +/// +/// For int: +/// - `0` if the number is zero +/// - `1` if the number is positive +/// - `-1` if the number is negative +#[inline(always)] pub fn signum(value: T) -> T { value.signum() } + +pub trait Unsigned: Num {} + +/// Times trait +/// +/// ```rust +/// use num::Times; +/// let ten = 10 as uint; +/// let mut accum = 0; +/// do ten.times { accum += 1; } +/// ``` +/// +pub trait Times { + fn times(&self, it: &fn()); +} + +pub trait Integer: Num + + Orderable + + Div + + Rem { + fn div_rem(&self, other: &Self) -> (Self,Self); + + fn div_floor(&self, other: &Self) -> Self; + fn mod_floor(&self, other: &Self) -> Self; + fn div_mod_floor(&self, other: &Self) -> (Self,Self); + + fn gcd(&self, other: &Self) -> Self; + fn lcm(&self, other: &Self) -> Self; + + fn is_multiple_of(&self, other: &Self) -> bool; + fn is_even(&self) -> bool; + fn is_odd(&self) -> bool; +} + +/// Calculates the Greatest Common Divisor (GCD) of the number and `other`. +/// +/// The result is always positive. +#[inline(always)] pub fn gcd(x: T, y: T) -> T { x.gcd(&y) } +/// Calculates the Lowest Common Multiple (LCM) of the number and `other`. +#[inline(always)] pub fn lcm(x: T, y: T) -> T { x.lcm(&y) } + +pub trait Round { + fn floor(&self) -> Self; + fn ceil(&self) -> Self; + fn round(&self) -> Self; + fn trunc(&self) -> Self; + fn fract(&self) -> Self; +} + +pub trait Fractional: Num + + Orderable + + Round + + Div { + fn recip(&self) -> Self; +} + +pub trait Algebraic { + fn pow(&self, n: &Self) -> Self; + fn sqrt(&self) -> Self; + fn rsqrt(&self) -> Self; + fn cbrt(&self) -> Self; + fn hypot(&self, other: &Self) -> Self; +} + +/// Raise a number to a power. +/// +/// # Example +/// +/// ```rust +/// let sixteen: float = num::pow(2.0, 4.0); +/// assert_eq!(sixteen, 16.0); +/// ``` +#[inline(always)] pub fn pow(value: T, n: T) -> T { value.pow(&n) } +/// Take the squre root of a number. +#[inline(always)] pub fn sqrt(value: T) -> T { value.sqrt() } +/// Take the reciprocal (inverse) square root of a number, `1/sqrt(x)`. +#[inline(always)] pub fn rsqrt(value: T) -> T { value.rsqrt() } +/// Take the cubic root of a number. +#[inline(always)] pub fn cbrt(value: T) -> T { value.cbrt() } +/// Calculate the length of the hypotenuse of a right-angle triangle given legs of length `x` and +/// `y`. +#[inline(always)] pub fn hypot(x: T, y: T) -> T { x.hypot(&y) } + +pub trait Trigonometric { + fn sin(&self) -> Self; + fn cos(&self) -> Self; + fn tan(&self) -> Self; + + fn asin(&self) -> Self; + fn acos(&self) -> Self; + fn atan(&self) -> Self; + + fn atan2(&self, other: &Self) -> Self; + fn sin_cos(&self) -> (Self, Self); +} + +/// Sine function. +#[inline(always)] pub fn sin(value: T) -> T { value.sin() } +/// Cosine function. +#[inline(always)] pub fn cos(value: T) -> T { value.cos() } +/// Tangent function. +#[inline(always)] pub fn tan(value: T) -> T { value.tan() } + +/// Compute the arcsine of the number. +#[inline(always)] pub fn asin(value: T) -> T { value.asin() } +/// Compute the arccosine of the number. +#[inline(always)] pub fn acos(value: T) -> T { value.acos() } +/// Compute the arctangent of the number. +#[inline(always)] pub fn atan(value: T) -> T { value.atan() } + +/// Compute the arctangent with 2 arguments. +#[inline(always)] pub fn atan2(x: T, y: T) -> T { x.atan2(&y) } +/// Simultaneously computes the sine and cosine of the number. +#[inline(always)] pub fn sin_cos(value: T) -> (T, T) { value.sin_cos() } + +pub trait Exponential { + fn exp(&self) -> Self; + fn exp2(&self) -> Self; + + fn ln(&self) -> Self; + fn log(&self, base: &Self) -> Self; + fn log2(&self) -> Self; + fn log10(&self) -> Self; +} + +/// Returns `e^(value)`, (the exponential function). +#[inline(always)] pub fn exp(value: T) -> T { value.exp() } +/// Returns 2 raised to the power of the number, `2^(value)`. +#[inline(always)] pub fn exp2(value: T) -> T { value.exp2() } + +/// Returns the natural logarithm of the number. +#[inline(always)] pub fn ln(value: T) -> T { value.ln() } +/// Returns the logarithm of the number with respect to an arbitrary base. +#[inline(always)] pub fn log(value: T, base: T) -> T { value.log(&base) } +/// Returns the base 2 logarithm of the number. +#[inline(always)] pub fn log2(value: T) -> T { value.log2() } +/// Returns the base 10 logarithm of the number. +#[inline(always)] pub fn log10(value: T) -> T { value.log10() } + +pub trait Hyperbolic: Exponential { + fn sinh(&self) -> Self; + fn cosh(&self) -> Self; + fn tanh(&self) -> Self; + + fn asinh(&self) -> Self; + fn acosh(&self) -> Self; + fn atanh(&self) -> Self; +} + +/// Hyperbolic cosine function. +#[inline(always)] pub fn sinh(value: T) -> T { value.sinh() } +/// Hyperbolic sine function. +#[inline(always)] pub fn cosh(value: T) -> T { value.cosh() } +/// Hyperbolic tangent function. +#[inline(always)] pub fn tanh(value: T) -> T { value.tanh() } + +/// Inverse hyperbolic sine function. +#[inline(always)] pub fn asinh(value: T) -> T { value.asinh() } +/// Inverse hyperbolic cosine function. +#[inline(always)] pub fn acosh(value: T) -> T { value.acosh() } +/// Inverse hyperbolic tangent function. +#[inline(always)] pub fn atanh(value: T) -> T { value.atanh() } + +/// Defines constants and methods common to real numbers +pub trait Real: Signed + + Fractional + + Algebraic + + Trigonometric + + Hyperbolic { + // Common Constants + // FIXME (#5527): These should be associated constants + fn pi() -> Self; + fn two_pi() -> Self; + fn frac_pi_2() -> Self; + fn frac_pi_3() -> Self; + fn frac_pi_4() -> Self; + fn frac_pi_6() -> Self; + fn frac_pi_8() -> Self; + fn frac_1_pi() -> Self; + fn frac_2_pi() -> Self; + fn frac_2_sqrtpi() -> Self; + fn sqrt2() -> Self; + fn frac_1_sqrt2() -> Self; + fn e() -> Self; + fn log2_e() -> Self; + fn log10_e() -> Self; + fn ln_2() -> Self; + fn ln_10() -> Self; + + // Angular conversions + fn to_degrees(&self) -> Self; + fn to_radians(&self) -> Self; +} + +/// Methods that are harder to implement and not commonly used. +pub trait RealExt: Real { + // FIXME (#5527): usages of `int` should be replaced with an associated + // integer type once these are implemented + + // Gamma functions + fn lgamma(&self) -> (int, Self); + fn tgamma(&self) -> Self; + + // Bessel functions + fn j0(&self) -> Self; + fn j1(&self) -> Self; + fn jn(&self, n: int) -> Self; + fn y0(&self) -> Self; + fn y1(&self) -> Self; + fn yn(&self, n: int) -> Self; +} + +/// Collects the bitwise operators under one trait. +pub trait Bitwise: Not + + BitAnd + + BitOr + + BitXor + + Shl + + Shr {} + +pub trait BitCount { + fn population_count(&self) -> Self; + fn leading_zeros(&self) -> Self; + fn trailing_zeros(&self) -> Self; +} + +pub trait Bounded { + // FIXME (#5527): These should be associated constants + fn min_value() -> Self; + fn max_value() -> Self; +} + +/// Specifies the available operations common to all of Rust's core numeric primitives. +/// These may not always make sense from a purely mathematical point of view, but +/// may be useful for systems programming. +pub trait Primitive: Clone + + DeepClone + + Num + + NumCast + + Orderable + + Bounded + + Neg + + Add + + Sub + + Mul + + Div + + Rem { + // FIXME (#5527): These should be associated constants + // FIXME (#8888): Removing `unused_self` requires #8888 to be fixed. + fn bits(unused_self: Option) -> uint; + fn bytes(unused_self: Option) -> uint; + fn is_signed(unused_self: Option) -> bool; +} + +/// A collection of traits relevant to primitive signed and unsigned integers +pub trait Int: Integer + + Primitive + + Bitwise + + BitCount {} + +/// Used for representing the classification of floating point numbers +#[deriving(Eq)] +pub enum FPCategory { + /// "Not a Number", often obtained by dividing by zero + FPNaN, + /// Positive or negative infinity + FPInfinite , + /// Positive or negative zero + FPZero, + /// De-normalized floating point representation (less precise than `FPNormal`) + FPSubnormal, + /// A regular floating point number + FPNormal, +} + +/// Primitive floating point numbers +pub trait Float: Real + + Signed + + Primitive + + ApproxEq { + // FIXME (#5527): These should be associated constants + fn nan() -> Self; + fn infinity() -> Self; + fn neg_infinity() -> Self; + fn neg_zero() -> Self; + + fn is_nan(&self) -> bool; + fn is_infinite(&self) -> bool; + fn is_finite(&self) -> bool; + fn is_normal(&self) -> bool; + fn classify(&self) -> FPCategory; + + // FIXME (#8888): Removing `unused_self` requires #8888 to be fixed. + fn mantissa_digits(unused_self: Option) -> uint; + fn digits(unused_self: Option) -> uint; + fn epsilon() -> Self; + fn min_exp(unused_self: Option) -> int; + fn max_exp(unused_self: Option) -> int; + fn min_10_exp(unused_self: Option) -> int; + fn max_10_exp(unused_self: Option) -> int; + + fn ldexp(x: Self, exp: int) -> Self; + fn frexp(&self) -> (Self, int); + + fn exp_m1(&self) -> Self; + fn ln_1p(&self) -> Self; + fn mul_add(&self, a: Self, b: Self) -> Self; + fn next_after(&self, other: Self) -> Self; +} + +/// Returns the exponential of the number, minus `1`, `exp(n) - 1`, in a way +/// that is accurate even if the number is close to zero. +#[inline(always)] pub fn exp_m1(value: T) -> T { value.exp_m1() } +/// Returns the natural logarithm of the number plus `1`, `ln(n + 1)`, more +/// accurately than if the operations were performed separately. +#[inline(always)] pub fn ln_1p(value: T) -> T { value.ln_1p() } +/// Fused multiply-add. Computes `(a * b) + c` with only one rounding error. +/// +/// This produces a more accurate result with better performance (on some +/// architectures) than a separate multiplication operation followed by an add. +#[inline(always)] pub fn mul_add(a: T, b: T, c: T) -> T { a.mul_add(b, c) } + +/// A generic trait for converting a value to a number. +pub trait ToPrimitive { + /// Converts the value of `self` to an `int`. + #[inline] + fn to_int(&self) -> Option { + self.to_i64().and_then(|x| x.to_int()) + } + + /// Converts the value of `self` to an `i8`. + #[inline] + fn to_i8(&self) -> Option { + self.to_i64().and_then(|x| x.to_i8()) + } + + /// Converts the value of `self` to an `i16`. + #[inline] + fn to_i16(&self) -> Option { + self.to_i64().and_then(|x| x.to_i16()) + } + + /// Converts the value of `self` to an `i32`. + #[inline] + fn to_i32(&self) -> Option { + self.to_i64().and_then(|x| x.to_i32()) + } + + /// Converts the value of `self` to an `i64`. + fn to_i64(&self) -> Option; + + /// Converts the value of `self` to an `uint`. + #[inline] + fn to_uint(&self) -> Option { + self.to_u64().and_then(|x| x.to_uint()) + } + + /// Converts the value of `self` to an `u8`. + #[inline] + fn to_u8(&self) -> Option { + self.to_u64().and_then(|x| x.to_u8()) + } + + /// Converts the value of `self` to an `u16`. + #[inline] + fn to_u16(&self) -> Option { + self.to_u64().and_then(|x| x.to_u16()) + } + + /// Converts the value of `self` to an `u32`. + #[inline] + fn to_u32(&self) -> Option { + self.to_u64().and_then(|x| x.to_u32()) + } + + /// Converts the value of `self` to an `u64`. + #[inline] + fn to_u64(&self) -> Option; + + /// Converts the value of `self` to an `f32`. + #[inline] + fn to_f32(&self) -> Option { + self.to_f64().and_then(|x| x.to_f32()) + } + + /// Converts the value of `self` to an `f64`. + #[inline] + fn to_f64(&self) -> Option { + self.to_i64().and_then(|x| x.to_f64()) + } +} + +macro_rules! impl_to_primitive_int_to_int( + ($SrcT:ty, $DstT:ty) => ( + { + if Primitive::bits(None::<$SrcT>) <= Primitive::bits(None::<$DstT>) { + Some(*self as $DstT) + } else { + let n = *self as i64; + let min_value: $DstT = Bounded::min_value(); + let max_value: $DstT = Bounded::max_value(); + if min_value as i64 <= n && n <= max_value as i64 { + Some(*self as $DstT) + } else { + None + } + } + } + ) +) + +macro_rules! impl_to_primitive_int_to_uint( + ($SrcT:ty, $DstT:ty) => ( + { + let zero: $SrcT = Zero::zero(); + let max_value: $DstT = Bounded::max_value(); + if zero <= *self && *self as u64 <= max_value as u64 { + Some(*self as $DstT) + } else { + None + } + } + ) +) + +macro_rules! impl_to_primitive_int( + ($T:ty) => ( + impl ToPrimitive for $T { + #[inline] + fn to_int(&self) -> Option { impl_to_primitive_int_to_int!($T, int) } + #[inline] + fn to_i8(&self) -> Option { impl_to_primitive_int_to_int!($T, i8) } + #[inline] + fn to_i16(&self) -> Option { impl_to_primitive_int_to_int!($T, i16) } + #[inline] + fn to_i32(&self) -> Option { impl_to_primitive_int_to_int!($T, i32) } + #[inline] + fn to_i64(&self) -> Option { impl_to_primitive_int_to_int!($T, i64) } + + #[inline] + fn to_uint(&self) -> Option { impl_to_primitive_int_to_uint!($T, uint) } + #[inline] + fn to_u8(&self) -> Option { impl_to_primitive_int_to_uint!($T, u8) } + #[inline] + fn to_u16(&self) -> Option { impl_to_primitive_int_to_uint!($T, u16) } + #[inline] + fn to_u32(&self) -> Option { impl_to_primitive_int_to_uint!($T, u32) } + #[inline] + fn to_u64(&self) -> Option { impl_to_primitive_int_to_uint!($T, u64) } + + #[inline] + fn to_f32(&self) -> Option { Some(*self as f32) } + #[inline] + fn to_f64(&self) -> Option { Some(*self as f64) } + } + ) +) + +impl_to_primitive_int!(int) +impl_to_primitive_int!(i8) +impl_to_primitive_int!(i16) +impl_to_primitive_int!(i32) +impl_to_primitive_int!(i64) + +macro_rules! impl_to_primitive_uint_to_int( + ($DstT:ty) => ( + { + let max_value: $DstT = Bounded::max_value(); + if *self as u64 <= max_value as u64 { + Some(*self as $DstT) + } else { + None + } + } + ) +) + +macro_rules! impl_to_primitive_uint_to_uint( + ($SrcT:ty, $DstT:ty) => ( + { + if Primitive::bits(None::<$SrcT>) <= Primitive::bits(None::<$DstT>) { + Some(*self as $DstT) + } else { + let zero: $SrcT = Zero::zero(); + let max_value: $DstT = Bounded::max_value(); + if zero <= *self && *self as u64 <= max_value as u64 { + Some(*self as $DstT) + } else { + None + } + } + } + ) +) + +macro_rules! impl_to_primitive_uint( + ($T:ty) => ( + impl ToPrimitive for $T { + #[inline] + fn to_int(&self) -> Option { impl_to_primitive_uint_to_int!(int) } + #[inline] + fn to_i8(&self) -> Option { impl_to_primitive_uint_to_int!(i8) } + #[inline] + fn to_i16(&self) -> Option { impl_to_primitive_uint_to_int!(i16) } + #[inline] + fn to_i32(&self) -> Option { impl_to_primitive_uint_to_int!(i32) } + #[inline] + fn to_i64(&self) -> Option { impl_to_primitive_uint_to_int!(i64) } + + #[inline] + fn to_uint(&self) -> Option { impl_to_primitive_uint_to_uint!($T, uint) } + #[inline] + fn to_u8(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u8) } + #[inline] + fn to_u16(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u16) } + #[inline] + fn to_u32(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u32) } + #[inline] + fn to_u64(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u64) } + + #[inline] + fn to_f32(&self) -> Option { Some(*self as f32) } + #[inline] + fn to_f64(&self) -> Option { Some(*self as f64) } + } + ) +) + +impl_to_primitive_uint!(uint) +impl_to_primitive_uint!(u8) +impl_to_primitive_uint!(u16) +impl_to_primitive_uint!(u32) +impl_to_primitive_uint!(u64) + +macro_rules! impl_to_primitive_float_to_float( + ($SrcT:ty, $DstT:ty) => ( + if Primitive::bits(None::<$SrcT>) <= Primitive::bits(None::<$DstT>) { + Some(*self as $DstT) + } else { + let n = *self as f64; + let max_value: $SrcT = Bounded::max_value(); + if -max_value as f64 <= n && n <= max_value as f64 { + Some(*self as $DstT) + } else { + None + } + } + ) +) + +macro_rules! impl_to_primitive_float( + ($T:ty) => ( + impl ToPrimitive for $T { + #[inline] + fn to_int(&self) -> Option { Some(*self as int) } + #[inline] + fn to_i8(&self) -> Option { Some(*self as i8) } + #[inline] + fn to_i16(&self) -> Option { Some(*self as i16) } + #[inline] + fn to_i32(&self) -> Option { Some(*self as i32) } + #[inline] + fn to_i64(&self) -> Option { Some(*self as i64) } + + #[inline] + fn to_uint(&self) -> Option { Some(*self as uint) } + #[inline] + fn to_u8(&self) -> Option { Some(*self as u8) } + #[inline] + fn to_u16(&self) -> Option { Some(*self as u16) } + #[inline] + fn to_u32(&self) -> Option { Some(*self as u32) } + #[inline] + fn to_u64(&self) -> Option { Some(*self as u64) } + + #[inline] + fn to_f32(&self) -> Option { impl_to_primitive_float_to_float!($T, f32) } + #[inline] + fn to_f64(&self) -> Option { impl_to_primitive_float_to_float!($T, f64) } + } + ) +) + +impl_to_primitive_float!(f32) +impl_to_primitive_float!(f64) + +/// A generic trait for converting a number to a value. +pub trait FromPrimitive { + /// Convert an `int` to return an optional value of this type. If the + /// value cannot be represented by this value, the `None` is returned. + #[inline] + fn from_int(n: int) -> Option { + FromPrimitive::from_i64(n as i64) + } + + /// Convert an `i8` to return an optional value of this type. If the + /// type cannot be represented by this value, the `None` is returned. + #[inline] + fn from_i8(n: i8) -> Option { + FromPrimitive::from_i64(n as i64) + } + + /// Convert an `i16` to return an optional value of this type. If the + /// type cannot be represented by this value, the `None` is returned. + #[inline] + fn from_i16(n: i16) -> Option { + FromPrimitive::from_i64(n as i64) + } + + /// Convert an `i32` to return an optional value of this type. If the + /// type cannot be represented by this value, the `None` is returned. + #[inline] + fn from_i32(n: i32) -> Option { + FromPrimitive::from_i64(n as i64) + } + + /// Convert an `i64` to return an optional value of this type. If the + /// type cannot be represented by this value, the `None` is returned. + fn from_i64(n: i64) -> Option; + + /// Convert an `uint` to return an optional value of this type. If the + /// type cannot be represented by this value, the `None` is returned. + #[inline] + fn from_uint(n: uint) -> Option { + FromPrimitive::from_u64(n as u64) + } + + /// Convert an `u8` to return an optional value of this type. If the + /// type cannot be represented by this value, the `None` is returned. + #[inline] + fn from_u8(n: u8) -> Option { + FromPrimitive::from_u64(n as u64) + } + + /// Convert an `u16` to return an optional value of this type. If the + /// type cannot be represented by this value, the `None` is returned. + #[inline] + fn from_u16(n: u16) -> Option { + FromPrimitive::from_u64(n as u64) + } + + /// Convert an `u32` to return an optional value of this type. If the + /// type cannot be represented by this value, the `None` is returned. + #[inline] + fn from_u32(n: u32) -> Option { + FromPrimitive::from_u64(n as u64) + } + + /// Convert an `u64` to return an optional value of this type. If the + /// type cannot be represented by this value, the `None` is returned. + fn from_u64(n: u64) -> Option; + + /// Convert a `f32` to return an optional value of this type. If the + /// type cannot be represented by this value, the `None` is returned. + #[inline] + fn from_f32(n: f32) -> Option { + FromPrimitive::from_f64(n as f64) + } + + /// Convert a `f64` to return an optional value of this type. If the + /// type cannot be represented by this value, the `None` is returned. + #[inline] + fn from_f64(n: f64) -> Option { + FromPrimitive::from_i64(n as i64) + } +} + +/// A utility function that just calls `FromPrimitive::from_int`. +pub fn from_int(n: int) -> Option { + FromPrimitive::from_int(n) +} + +/// A utility function that just calls `FromPrimitive::from_i8`. +pub fn from_i8(n: i8) -> Option { + FromPrimitive::from_i8(n) +} + +/// A utility function that just calls `FromPrimitive::from_i16`. +pub fn from_i16(n: i16) -> Option { + FromPrimitive::from_i16(n) +} + +/// A utility function that just calls `FromPrimitive::from_i32`. +pub fn from_i32(n: i32) -> Option { + FromPrimitive::from_i32(n) +} + +/// A utility function that just calls `FromPrimitive::from_i64`. +pub fn from_i64(n: i64) -> Option { + FromPrimitive::from_i64(n) +} + +/// A utility function that just calls `FromPrimitive::from_uint`. +pub fn from_uint(n: uint) -> Option { + FromPrimitive::from_uint(n) +} + +/// A utility function that just calls `FromPrimitive::from_u8`. +pub fn from_u8(n: u8) -> Option { + FromPrimitive::from_u8(n) +} + +/// A utility function that just calls `FromPrimitive::from_u16`. +pub fn from_u16(n: u16) -> Option { + FromPrimitive::from_u16(n) +} + +/// A utility function that just calls `FromPrimitive::from_u32`. +pub fn from_u32(n: u32) -> Option { + FromPrimitive::from_u32(n) +} + +/// A utility function that just calls `FromPrimitive::from_u64`. +pub fn from_u64(n: u64) -> Option { + FromPrimitive::from_u64(n) +} + +/// A utility function that just calls `FromPrimitive::from_f32`. +pub fn from_f32(n: f32) -> Option { + FromPrimitive::from_f32(n) +} + +/// A utility function that just calls `FromPrimitive::from_f64`. +pub fn from_f64(n: f64) -> Option { + FromPrimitive::from_f64(n) +} + +macro_rules! impl_from_primitive( + ($T:ty, $to_ty:expr) => ( + impl FromPrimitive for $T { + #[inline] fn from_int(n: int) -> Option<$T> { $to_ty } + #[inline] fn from_i8(n: i8) -> Option<$T> { $to_ty } + #[inline] fn from_i16(n: i16) -> Option<$T> { $to_ty } + #[inline] fn from_i32(n: i32) -> Option<$T> { $to_ty } + #[inline] fn from_i64(n: i64) -> Option<$T> { $to_ty } + + #[inline] fn from_uint(n: uint) -> Option<$T> { $to_ty } + #[inline] fn from_u8(n: u8) -> Option<$T> { $to_ty } + #[inline] fn from_u16(n: u16) -> Option<$T> { $to_ty } + #[inline] fn from_u32(n: u32) -> Option<$T> { $to_ty } + #[inline] fn from_u64(n: u64) -> Option<$T> { $to_ty } + + #[inline] fn from_f32(n: f32) -> Option<$T> { $to_ty } + #[inline] fn from_f64(n: f64) -> Option<$T> { $to_ty } + } + ) +) + +impl_from_primitive!(int, n.to_int()) +impl_from_primitive!(i8, n.to_i8()) +impl_from_primitive!(i16, n.to_i16()) +impl_from_primitive!(i32, n.to_i32()) +impl_from_primitive!(i64, n.to_i64()) +impl_from_primitive!(uint, n.to_uint()) +impl_from_primitive!(u8, n.to_u8()) +impl_from_primitive!(u16, n.to_u16()) +impl_from_primitive!(u32, n.to_u32()) +impl_from_primitive!(u64, n.to_u64()) +impl_from_primitive!(f32, n.to_f32()) +impl_from_primitive!(f64, n.to_f64()) + +/// Cast from one machine scalar to another. +/// +/// # Example +/// +/// ``` +/// let twenty: f32 = num::cast(0x14).unwrap(); +/// assert_eq!(twenty, 20f32); +/// ``` +/// +#[inline] +pub fn cast(n: T) -> Option { + NumCast::from(n) +} + +/// An interface for casting between machine scalars +pub trait NumCast: ToPrimitive { + fn from(n: T) -> Option; +} + +macro_rules! impl_num_cast( + ($T:ty, $conv:ident) => ( + impl NumCast for $T { + #[inline] + fn from(n: N) -> Option<$T> { + // `$conv` could be generated using `concat_idents!`, but that + // macro seems to be broken at the moment + n.$conv() + } + } + ) +) + +impl_num_cast!(u8, to_u8) +impl_num_cast!(u16, to_u16) +impl_num_cast!(u32, to_u32) +impl_num_cast!(u64, to_u64) +impl_num_cast!(uint, to_uint) +impl_num_cast!(i8, to_i8) +impl_num_cast!(i16, to_i16) +impl_num_cast!(i32, to_i32) +impl_num_cast!(i64, to_i64) +impl_num_cast!(int, to_int) +impl_num_cast!(f32, to_f32) +impl_num_cast!(f64, to_f64) + +pub trait ToStrRadix { + fn to_str_radix(&self, radix: uint) -> ~str; +} + +pub trait FromStrRadix { + fn from_str_radix(str: &str, radix: uint) -> Option; +} + +/// A utility function that just calls FromStrRadix::from_str_radix. +pub fn from_str_radix(str: &str, radix: uint) -> Option { + FromStrRadix::from_str_radix(str, radix) +} + +/// Calculates a power to a given radix, optimized for uint `pow` and `radix`. +/// +/// Returns `radix^pow` as `T`. +/// +/// Note: +/// Also returns `1` for `0^0`, despite that technically being an +/// undefined number. The reason for this is twofold: +/// - If code written to use this function cares about that special case, it's +/// probably going to catch it before making the call. +/// - If code written to use this function doesn't care about it, it's +/// probably assuming that `x^0` always equals `1`. +/// +pub fn pow_with_uint+Mul>(radix: uint, pow: uint) -> T { + let _0: T = Zero::zero(); + let _1: T = One::one(); + + if pow == 0u { return _1; } + if radix == 0u { return _0; } + let mut my_pow = pow; + let mut total = _1; + let mut multiplier = cast(radix).unwrap(); + while (my_pow > 0u) { + if my_pow % 2u == 1u { + total = total * multiplier; + } + my_pow = my_pow / 2u; + multiplier = multiplier * multiplier; + } + total +} + +impl Zero for @mut T { + fn zero() -> @mut T { @mut Zero::zero() } + fn is_zero(&self) -> bool { (**self).is_zero() } +} + +impl Zero for @T { + fn zero() -> @T { @Zero::zero() } + fn is_zero(&self) -> bool { (**self).is_zero() } +} + +impl Zero for ~T { + fn zero() -> ~T { ~Zero::zero() } + fn is_zero(&self) -> bool { (**self).is_zero() } +} + +/// Saturating math operations +pub trait Saturating { + /// Saturating addition operator. + /// Returns a+b, saturating at the numeric bounds instead of overflowing. + fn saturating_add(self, v: Self) -> Self; + + /// Saturating subtraction operator. + /// Returns a-b, saturating at the numeric bounds instead of overflowing. + fn saturating_sub(self, v: Self) -> Self; +} + +impl Saturating for T { + #[inline] + fn saturating_add(self, v: T) -> T { + match self.checked_add(&v) { + Some(x) => x, + None => if v >= Zero::zero() { + Bounded::max_value() + } else { + Bounded::min_value() + } + } + } + + #[inline] + fn saturating_sub(self, v: T) -> T { + match self.checked_sub(&v) { + Some(x) => x, + None => if v >= Zero::zero() { + Bounded::min_value() + } else { + Bounded::max_value() + } + } + } +} + +pub trait CheckedAdd: Add { + fn checked_add(&self, v: &Self) -> Option; +} + +pub trait CheckedSub: Sub { + fn checked_sub(&self, v: &Self) -> Option; +} + +pub trait CheckedMul: Mul { + fn checked_mul(&self, v: &Self) -> Option; +} + +pub trait CheckedDiv: Div { + fn checked_div(&self, v: &Self) -> Option; +} + +/// Helper function for testing numeric operations +#[cfg(test)] +pub fn test_num(ten: T, two: T) { + assert_eq!(ten.add(&two), cast(12).unwrap()); + assert_eq!(ten.sub(&two), cast(8).unwrap()); + assert_eq!(ten.mul(&two), cast(20).unwrap()); + assert_eq!(ten.div(&two), cast(5).unwrap()); + assert_eq!(ten.rem(&two), cast(0).unwrap()); + + assert_eq!(ten.add(&two), ten + two); + assert_eq!(ten.sub(&two), ten - two); + assert_eq!(ten.mul(&two), ten * two); + assert_eq!(ten.div(&two), ten / two); + assert_eq!(ten.rem(&two), ten % two); +} + +#[cfg(test)] +mod tests { + use prelude::*; + use super::*; + use i8; + use i16; + use i32; + use i64; + use int; + use u8; + use u16; + use u32; + use u64; + use uint; + + macro_rules! test_cast_20( + ($_20:expr) => ({ + let _20 = $_20; + + assert_eq!(20u, _20.to_uint().unwrap()); + assert_eq!(20u8, _20.to_u8().unwrap()); + assert_eq!(20u16, _20.to_u16().unwrap()); + assert_eq!(20u32, _20.to_u32().unwrap()); + assert_eq!(20u64, _20.to_u64().unwrap()); + assert_eq!(20i, _20.to_int().unwrap()); + assert_eq!(20i8, _20.to_i8().unwrap()); + assert_eq!(20i16, _20.to_i16().unwrap()); + assert_eq!(20i32, _20.to_i32().unwrap()); + assert_eq!(20i64, _20.to_i64().unwrap()); + assert_eq!(20f32, _20.to_f32().unwrap()); + assert_eq!(20f64, _20.to_f64().unwrap()); + + assert_eq!(_20, NumCast::from(20u).unwrap()); + assert_eq!(_20, NumCast::from(20u8).unwrap()); + assert_eq!(_20, NumCast::from(20u16).unwrap()); + assert_eq!(_20, NumCast::from(20u32).unwrap()); + assert_eq!(_20, NumCast::from(20u64).unwrap()); + assert_eq!(_20, NumCast::from(20i).unwrap()); + assert_eq!(_20, NumCast::from(20i8).unwrap()); + assert_eq!(_20, NumCast::from(20i16).unwrap()); + assert_eq!(_20, NumCast::from(20i32).unwrap()); + assert_eq!(_20, NumCast::from(20i64).unwrap()); + assert_eq!(_20, NumCast::from(20f32).unwrap()); + assert_eq!(_20, NumCast::from(20f64).unwrap()); + + assert_eq!(_20, cast(20u).unwrap()); + assert_eq!(_20, cast(20u8).unwrap()); + assert_eq!(_20, cast(20u16).unwrap()); + assert_eq!(_20, cast(20u32).unwrap()); + assert_eq!(_20, cast(20u64).unwrap()); + assert_eq!(_20, cast(20i).unwrap()); + assert_eq!(_20, cast(20i8).unwrap()); + assert_eq!(_20, cast(20i16).unwrap()); + assert_eq!(_20, cast(20i32).unwrap()); + assert_eq!(_20, cast(20i64).unwrap()); + assert_eq!(_20, cast(20f32).unwrap()); + assert_eq!(_20, cast(20f64).unwrap()); + }) + ) + + #[test] fn test_u8_cast() { test_cast_20!(20u8) } + #[test] fn test_u16_cast() { test_cast_20!(20u16) } + #[test] fn test_u32_cast() { test_cast_20!(20u32) } + #[test] fn test_u64_cast() { test_cast_20!(20u64) } + #[test] fn test_uint_cast() { test_cast_20!(20u) } + #[test] fn test_i8_cast() { test_cast_20!(20i8) } + #[test] fn test_i16_cast() { test_cast_20!(20i16) } + #[test] fn test_i32_cast() { test_cast_20!(20i32) } + #[test] fn test_i64_cast() { test_cast_20!(20i64) } + #[test] fn test_int_cast() { test_cast_20!(20i) } + #[test] fn test_f32_cast() { test_cast_20!(20f32) } + #[test] fn test_f64_cast() { test_cast_20!(20f64) } + + #[test] + fn test_cast_range_int_min() { + assert_eq!(int::min_value.to_int(), Some(int::min_value as int)); + assert_eq!(int::min_value.to_i8(), None); + assert_eq!(int::min_value.to_i16(), None); + // int::min_value.to_i32() is word-size specific + assert_eq!(int::min_value.to_i64(), Some(int::min_value as i64)); + assert_eq!(int::min_value.to_uint(), None); + assert_eq!(int::min_value.to_u8(), None); + assert_eq!(int::min_value.to_u16(), None); + assert_eq!(int::min_value.to_u32(), None); + assert_eq!(int::min_value.to_u64(), None); + + #[cfg(target_word_size = "32")] + fn check_word_size() { + assert_eq!(int::min_value.to_i32(), Some(int::min_value as i32)); + } + + #[cfg(target_word_size = "64")] + fn check_word_size() { + assert_eq!(int::min_value.to_i32(), None); + } + + check_word_size(); + } + + #[test] + fn test_cast_range_i8_min() { + assert_eq!(i8::min_value.to_int(), Some(i8::min_value as int)); + assert_eq!(i8::min_value.to_i8(), Some(i8::min_value as i8)); + assert_eq!(i8::min_value.to_i16(), Some(i8::min_value as i16)); + assert_eq!(i8::min_value.to_i32(), Some(i8::min_value as i32)); + assert_eq!(i8::min_value.to_i64(), Some(i8::min_value as i64)); + assert_eq!(i8::min_value.to_uint(), None); + assert_eq!(i8::min_value.to_u8(), None); + assert_eq!(i8::min_value.to_u16(), None); + assert_eq!(i8::min_value.to_u32(), None); + assert_eq!(i8::min_value.to_u64(), None); + } + + #[test] + fn test_cast_range_i16_min() { + assert_eq!(i16::min_value.to_int(), Some(i16::min_value as int)); + assert_eq!(i16::min_value.to_i8(), None); + assert_eq!(i16::min_value.to_i16(), Some(i16::min_value as i16)); + assert_eq!(i16::min_value.to_i32(), Some(i16::min_value as i32)); + assert_eq!(i16::min_value.to_i64(), Some(i16::min_value as i64)); + assert_eq!(i16::min_value.to_uint(), None); + assert_eq!(i16::min_value.to_u8(), None); + assert_eq!(i16::min_value.to_u16(), None); + assert_eq!(i16::min_value.to_u32(), None); + assert_eq!(i16::min_value.to_u64(), None); + } + + #[test] + fn test_cast_range_i32_min() { + assert_eq!(i32::min_value.to_int(), Some(i32::min_value as int)); + assert_eq!(i32::min_value.to_i8(), None); + assert_eq!(i32::min_value.to_i16(), None); + assert_eq!(i32::min_value.to_i32(), Some(i32::min_value as i32)); + assert_eq!(i32::min_value.to_i64(), Some(i32::min_value as i64)); + assert_eq!(i32::min_value.to_uint(), None); + assert_eq!(i32::min_value.to_u8(), None); + assert_eq!(i32::min_value.to_u16(), None); + assert_eq!(i32::min_value.to_u32(), None); + assert_eq!(i32::min_value.to_u64(), None); + } + + #[test] + fn test_cast_range_i64_min() { + // i64::min_value.to_int() is word-size specific + assert_eq!(i64::min_value.to_i8(), None); + assert_eq!(i64::min_value.to_i16(), None); + assert_eq!(i64::min_value.to_i32(), None); + assert_eq!(i64::min_value.to_i64(), Some(i64::min_value as i64)); + assert_eq!(i64::min_value.to_uint(), None); + assert_eq!(i64::min_value.to_u8(), None); + assert_eq!(i64::min_value.to_u16(), None); + assert_eq!(i64::min_value.to_u32(), None); + assert_eq!(i64::min_value.to_u64(), None); + + #[cfg(target_word_size = "32")] + fn check_word_size() { + assert_eq!(i64::min_value.to_int(), None); + } + + #[cfg(target_word_size = "64")] + fn check_word_size() { + assert_eq!(i64::min_value.to_int(), Some(i64::min_value as int)); + } + + check_word_size(); + } + + #[test] + fn test_cast_range_int_max() { + assert_eq!(int::max_value.to_int(), Some(int::max_value as int)); + assert_eq!(int::max_value.to_i8(), None); + assert_eq!(int::max_value.to_i16(), None); + // int::max_value.to_i32() is word-size specific + assert_eq!(int::max_value.to_i64(), Some(int::max_value as i64)); + assert_eq!(int::max_value.to_u8(), None); + assert_eq!(int::max_value.to_u16(), None); + // int::max_value.to_u32() is word-size specific + assert_eq!(int::max_value.to_u64(), Some(int::max_value as u64)); + + #[cfg(target_word_size = "32")] + fn check_word_size() { + assert_eq!(int::max_value.to_i32(), Some(int::max_value as i32)); + assert_eq!(int::max_value.to_u32(), Some(int::max_value as u32)); + } + + #[cfg(target_word_size = "64")] + fn check_word_size() { + assert_eq!(int::max_value.to_i32(), None); + assert_eq!(int::max_value.to_u32(), None); + } + + check_word_size(); + } + + #[test] + fn test_cast_range_i8_max() { + assert_eq!(i8::max_value.to_int(), Some(i8::max_value as int)); + assert_eq!(i8::max_value.to_i8(), Some(i8::max_value as i8)); + assert_eq!(i8::max_value.to_i16(), Some(i8::max_value as i16)); + assert_eq!(i8::max_value.to_i32(), Some(i8::max_value as i32)); + assert_eq!(i8::max_value.to_i64(), Some(i8::max_value as i64)); + assert_eq!(i8::max_value.to_uint(), Some(i8::max_value as uint)); + assert_eq!(i8::max_value.to_u8(), Some(i8::max_value as u8)); + assert_eq!(i8::max_value.to_u16(), Some(i8::max_value as u16)); + assert_eq!(i8::max_value.to_u32(), Some(i8::max_value as u32)); + assert_eq!(i8::max_value.to_u64(), Some(i8::max_value as u64)); + } + + #[test] + fn test_cast_range_i16_max() { + assert_eq!(i16::max_value.to_int(), Some(i16::max_value as int)); + assert_eq!(i16::max_value.to_i8(), None); + assert_eq!(i16::max_value.to_i16(), Some(i16::max_value as i16)); + assert_eq!(i16::max_value.to_i32(), Some(i16::max_value as i32)); + assert_eq!(i16::max_value.to_i64(), Some(i16::max_value as i64)); + assert_eq!(i16::max_value.to_uint(), Some(i16::max_value as uint)); + assert_eq!(i16::max_value.to_u8(), None); + assert_eq!(i16::max_value.to_u16(), Some(i16::max_value as u16)); + assert_eq!(i16::max_value.to_u32(), Some(i16::max_value as u32)); + assert_eq!(i16::max_value.to_u64(), Some(i16::max_value as u64)); + } + + #[test] + fn test_cast_range_i32_max() { + assert_eq!(i32::max_value.to_int(), Some(i32::max_value as int)); + assert_eq!(i32::max_value.to_i8(), None); + assert_eq!(i32::max_value.to_i16(), None); + assert_eq!(i32::max_value.to_i32(), Some(i32::max_value as i32)); + assert_eq!(i32::max_value.to_i64(), Some(i32::max_value as i64)); + assert_eq!(i32::max_value.to_uint(), Some(i32::max_value as uint)); + assert_eq!(i32::max_value.to_u8(), None); + assert_eq!(i32::max_value.to_u16(), None); + assert_eq!(i32::max_value.to_u32(), Some(i32::max_value as u32)); + assert_eq!(i32::max_value.to_u64(), Some(i32::max_value as u64)); + } + + #[test] + fn test_cast_range_i64_max() { + // i64::max_value.to_int() is word-size specific + assert_eq!(i64::max_value.to_i8(), None); + assert_eq!(i64::max_value.to_i16(), None); + assert_eq!(i64::max_value.to_i32(), None); + assert_eq!(i64::max_value.to_i64(), Some(i64::max_value as i64)); + // i64::max_value.to_uint() is word-size specific + assert_eq!(i64::max_value.to_u8(), None); + assert_eq!(i64::max_value.to_u16(), None); + assert_eq!(i64::max_value.to_u32(), None); + assert_eq!(i64::max_value.to_u64(), Some(i64::max_value as u64)); + + #[cfg(target_word_size = "32")] + fn check_word_size() { + assert_eq!(i64::max_value.to_int(), None); + assert_eq!(i64::max_value.to_uint(), None); + } + + #[cfg(target_word_size = "64")] + fn check_word_size() { + assert_eq!(i64::max_value.to_int(), Some(i64::max_value as int)); + assert_eq!(i64::max_value.to_uint(), Some(i64::max_value as uint)); + } + + check_word_size(); + } + + #[test] + fn test_cast_range_uint_min() { + assert_eq!(uint::min_value.to_int(), Some(uint::min_value as int)); + assert_eq!(uint::min_value.to_i8(), Some(uint::min_value as i8)); + assert_eq!(uint::min_value.to_i16(), Some(uint::min_value as i16)); + assert_eq!(uint::min_value.to_i32(), Some(uint::min_value as i32)); + assert_eq!(uint::min_value.to_i64(), Some(uint::min_value as i64)); + assert_eq!(uint::min_value.to_uint(), Some(uint::min_value as uint)); + assert_eq!(uint::min_value.to_u8(), Some(uint::min_value as u8)); + assert_eq!(uint::min_value.to_u16(), Some(uint::min_value as u16)); + assert_eq!(uint::min_value.to_u32(), Some(uint::min_value as u32)); + assert_eq!(uint::min_value.to_u64(), Some(uint::min_value as u64)); + } + + #[test] + fn test_cast_range_u8_min() { + assert_eq!(u8::min_value.to_int(), Some(u8::min_value as int)); + assert_eq!(u8::min_value.to_i8(), Some(u8::min_value as i8)); + assert_eq!(u8::min_value.to_i16(), Some(u8::min_value as i16)); + assert_eq!(u8::min_value.to_i32(), Some(u8::min_value as i32)); + assert_eq!(u8::min_value.to_i64(), Some(u8::min_value as i64)); + assert_eq!(u8::min_value.to_uint(), Some(u8::min_value as uint)); + assert_eq!(u8::min_value.to_u8(), Some(u8::min_value as u8)); + assert_eq!(u8::min_value.to_u16(), Some(u8::min_value as u16)); + assert_eq!(u8::min_value.to_u32(), Some(u8::min_value as u32)); + assert_eq!(u8::min_value.to_u64(), Some(u8::min_value as u64)); + } + + #[test] + fn test_cast_range_u16_min() { + assert_eq!(u16::min_value.to_int(), Some(u16::min_value as int)); + assert_eq!(u16::min_value.to_i8(), Some(u16::min_value as i8)); + assert_eq!(u16::min_value.to_i16(), Some(u16::min_value as i16)); + assert_eq!(u16::min_value.to_i32(), Some(u16::min_value as i32)); + assert_eq!(u16::min_value.to_i64(), Some(u16::min_value as i64)); + assert_eq!(u16::min_value.to_uint(), Some(u16::min_value as uint)); + assert_eq!(u16::min_value.to_u8(), Some(u16::min_value as u8)); + assert_eq!(u16::min_value.to_u16(), Some(u16::min_value as u16)); + assert_eq!(u16::min_value.to_u32(), Some(u16::min_value as u32)); + assert_eq!(u16::min_value.to_u64(), Some(u16::min_value as u64)); + } + + #[test] + fn test_cast_range_u32_min() { + assert_eq!(u32::min_value.to_int(), Some(u32::min_value as int)); + assert_eq!(u32::min_value.to_i8(), Some(u32::min_value as i8)); + assert_eq!(u32::min_value.to_i16(), Some(u32::min_value as i16)); + assert_eq!(u32::min_value.to_i32(), Some(u32::min_value as i32)); + assert_eq!(u32::min_value.to_i64(), Some(u32::min_value as i64)); + assert_eq!(u32::min_value.to_uint(), Some(u32::min_value as uint)); + assert_eq!(u32::min_value.to_u8(), Some(u32::min_value as u8)); + assert_eq!(u32::min_value.to_u16(), Some(u32::min_value as u16)); + assert_eq!(u32::min_value.to_u32(), Some(u32::min_value as u32)); + assert_eq!(u32::min_value.to_u64(), Some(u32::min_value as u64)); + } + + #[test] + fn test_cast_range_u64_min() { + assert_eq!(u64::min_value.to_int(), Some(u64::min_value as int)); + assert_eq!(u64::min_value.to_i8(), Some(u64::min_value as i8)); + assert_eq!(u64::min_value.to_i16(), Some(u64::min_value as i16)); + assert_eq!(u64::min_value.to_i32(), Some(u64::min_value as i32)); + assert_eq!(u64::min_value.to_i64(), Some(u64::min_value as i64)); + assert_eq!(u64::min_value.to_uint(), Some(u64::min_value as uint)); + assert_eq!(u64::min_value.to_u8(), Some(u64::min_value as u8)); + assert_eq!(u64::min_value.to_u16(), Some(u64::min_value as u16)); + assert_eq!(u64::min_value.to_u32(), Some(u64::min_value as u32)); + assert_eq!(u64::min_value.to_u64(), Some(u64::min_value as u64)); + } + + #[test] + fn test_cast_range_uint_max() { + assert_eq!(uint::max_value.to_int(), None); + assert_eq!(uint::max_value.to_i8(), None); + assert_eq!(uint::max_value.to_i16(), None); + assert_eq!(uint::max_value.to_i32(), None); + // uint::max_value.to_i64() is word-size specific + assert_eq!(uint::max_value.to_u8(), None); + assert_eq!(uint::max_value.to_u16(), None); + // uint::max_value.to_u32() is word-size specific + assert_eq!(uint::max_value.to_u64(), Some(uint::max_value as u64)); + + #[cfg(target_word_size = "32")] + fn check_word_size() { + assert_eq!(uint::max_value.to_u32(), Some(uint::max_value as u32)); + assert_eq!(uint::max_value.to_i64(), Some(uint::max_value as i64)); + } + + #[cfg(target_word_size = "64")] + fn check_word_size() { + assert_eq!(uint::max_value.to_u32(), None); + assert_eq!(uint::max_value.to_i64(), None); + } + + check_word_size(); + } + + #[test] + fn test_cast_range_u8_max() { + assert_eq!(u8::max_value.to_int(), Some(u8::max_value as int)); + assert_eq!(u8::max_value.to_i8(), None); + assert_eq!(u8::max_value.to_i16(), Some(u8::max_value as i16)); + assert_eq!(u8::max_value.to_i32(), Some(u8::max_value as i32)); + assert_eq!(u8::max_value.to_i64(), Some(u8::max_value as i64)); + assert_eq!(u8::max_value.to_uint(), Some(u8::max_value as uint)); + assert_eq!(u8::max_value.to_u8(), Some(u8::max_value as u8)); + assert_eq!(u8::max_value.to_u16(), Some(u8::max_value as u16)); + assert_eq!(u8::max_value.to_u32(), Some(u8::max_value as u32)); + assert_eq!(u8::max_value.to_u64(), Some(u8::max_value as u64)); + } + + #[test] + fn test_cast_range_u16_max() { + assert_eq!(u16::max_value.to_int(), Some(u16::max_value as int)); + assert_eq!(u16::max_value.to_i8(), None); + assert_eq!(u16::max_value.to_i16(), None); + assert_eq!(u16::max_value.to_i32(), Some(u16::max_value as i32)); + assert_eq!(u16::max_value.to_i64(), Some(u16::max_value as i64)); + assert_eq!(u16::max_value.to_uint(), Some(u16::max_value as uint)); + assert_eq!(u16::max_value.to_u8(), None); + assert_eq!(u16::max_value.to_u16(), Some(u16::max_value as u16)); + assert_eq!(u16::max_value.to_u32(), Some(u16::max_value as u32)); + assert_eq!(u16::max_value.to_u64(), Some(u16::max_value as u64)); + } + + #[test] + fn test_cast_range_u32_max() { + // u32::max_value.to_int() is word-size specific + assert_eq!(u32::max_value.to_i8(), None); + assert_eq!(u32::max_value.to_i16(), None); + assert_eq!(u32::max_value.to_i32(), None); + assert_eq!(u32::max_value.to_i64(), Some(u32::max_value as i64)); + assert_eq!(u32::max_value.to_uint(), Some(u32::max_value as uint)); + assert_eq!(u32::max_value.to_u8(), None); + assert_eq!(u32::max_value.to_u16(), None); + assert_eq!(u32::max_value.to_u32(), Some(u32::max_value as u32)); + assert_eq!(u32::max_value.to_u64(), Some(u32::max_value as u64)); + + #[cfg(target_word_size = "32")] + fn check_word_size() { + assert_eq!(u32::max_value.to_int(), None); + } + + #[cfg(target_word_size = "64")] + fn check_word_size() { + assert_eq!(u32::max_value.to_int(), Some(u32::max_value as int)); + } + + check_word_size(); + } + + #[test] + fn test_cast_range_u64_max() { + assert_eq!(u64::max_value.to_int(), None); + assert_eq!(u64::max_value.to_i8(), None); + assert_eq!(u64::max_value.to_i16(), None); + assert_eq!(u64::max_value.to_i32(), None); + assert_eq!(u64::max_value.to_i64(), None); + // u64::max_value.to_uint() is word-size specific + assert_eq!(u64::max_value.to_u8(), None); + assert_eq!(u64::max_value.to_u16(), None); + assert_eq!(u64::max_value.to_u32(), None); + assert_eq!(u64::max_value.to_u64(), Some(u64::max_value as u64)); + + #[cfg(target_word_size = "32")] + fn check_word_size() { + assert_eq!(u64::max_value.to_uint(), None); + } + + #[cfg(target_word_size = "64")] + fn check_word_size() { + assert_eq!(u64::max_value.to_uint(), Some(u64::max_value as uint)); + } + + check_word_size(); + } + + #[test] + fn test_saturating_add_uint() { + use uint::max_value; + assert_eq!(3u.saturating_add(5u), 8u); + assert_eq!(3u.saturating_add(max_value-1), max_value); + assert_eq!(max_value.saturating_add(max_value), max_value); + assert_eq!((max_value-2).saturating_add(1), max_value-1); + } + + #[test] + fn test_saturating_sub_uint() { + use uint::max_value; + assert_eq!(5u.saturating_sub(3u), 2u); + assert_eq!(3u.saturating_sub(5u), 0u); + assert_eq!(0u.saturating_sub(1u), 0u); + assert_eq!((max_value-1).saturating_sub(max_value), 0); + } + + #[test] + fn test_saturating_add_int() { + use int::{min_value,max_value}; + assert_eq!(3i.saturating_add(5i), 8i); + assert_eq!(3i.saturating_add(max_value-1), max_value); + assert_eq!(max_value.saturating_add(max_value), max_value); + assert_eq!((max_value-2).saturating_add(1), max_value-1); + assert_eq!(3i.saturating_add(-5i), -2i); + assert_eq!(min_value.saturating_add(-1i), min_value); + assert_eq!((-2i).saturating_add(-max_value), min_value); + } + + #[test] + fn test_saturating_sub_int() { + use int::{min_value,max_value}; + assert_eq!(3i.saturating_sub(5i), -2i); + assert_eq!(min_value.saturating_sub(1i), min_value); + assert_eq!((-2i).saturating_sub(max_value), min_value); + assert_eq!(3i.saturating_sub(-5i), 8i); + assert_eq!(3i.saturating_sub(-(max_value-1)), max_value); + assert_eq!(max_value.saturating_sub(-max_value), max_value); + assert_eq!((max_value-2).saturating_sub(-1), max_value-1); + } + + #[test] + fn test_checked_add() { + let five_less = uint::max_value - 5; + assert_eq!(five_less.checked_add(&0), Some(uint::max_value - 5)); + assert_eq!(five_less.checked_add(&1), Some(uint::max_value - 4)); + assert_eq!(five_less.checked_add(&2), Some(uint::max_value - 3)); + assert_eq!(five_less.checked_add(&3), Some(uint::max_value - 2)); + assert_eq!(five_less.checked_add(&4), Some(uint::max_value - 1)); + assert_eq!(five_less.checked_add(&5), Some(uint::max_value)); + assert_eq!(five_less.checked_add(&6), None); + assert_eq!(five_less.checked_add(&7), None); + } + + #[test] + fn test_checked_sub() { + assert_eq!(5u.checked_sub(&0), Some(5)); + assert_eq!(5u.checked_sub(&1), Some(4)); + assert_eq!(5u.checked_sub(&2), Some(3)); + assert_eq!(5u.checked_sub(&3), Some(2)); + assert_eq!(5u.checked_sub(&4), Some(1)); + assert_eq!(5u.checked_sub(&5), Some(0)); + assert_eq!(5u.checked_sub(&6), None); + assert_eq!(5u.checked_sub(&7), None); + } + + #[test] + fn test_checked_mul() { + let third = uint::max_value / 3; + assert_eq!(third.checked_mul(&0), Some(0)); + assert_eq!(third.checked_mul(&1), Some(third)); + assert_eq!(third.checked_mul(&2), Some(third * 2)); + assert_eq!(third.checked_mul(&3), Some(third * 3)); + assert_eq!(third.checked_mul(&4), None); + } + + + #[deriving(Eq)] + struct Value { x: int } + + impl ToPrimitive for Value { + fn to_i64(&self) -> Option { self.x.to_i64() } + fn to_u64(&self) -> Option { self.x.to_u64() } + } + + impl FromPrimitive for Value { + fn from_i64(n: i64) -> Option { Some(Value { x: n as int }) } + fn from_u64(n: u64) -> Option { Some(Value { x: n as int }) } + } + + #[test] + fn test_to_primitive() { + let value = Value { x: 5 }; + assert_eq!(value.to_int(), Some(5)); + assert_eq!(value.to_i8(), Some(5)); + assert_eq!(value.to_i16(), Some(5)); + assert_eq!(value.to_i32(), Some(5)); + assert_eq!(value.to_i64(), Some(5)); + assert_eq!(value.to_uint(), Some(5)); + assert_eq!(value.to_u8(), Some(5)); + assert_eq!(value.to_u16(), Some(5)); + assert_eq!(value.to_u32(), Some(5)); + assert_eq!(value.to_u64(), Some(5)); + assert_eq!(value.to_f32(), Some(5f32)); + assert_eq!(value.to_f64(), Some(5f64)); + } + + #[test] + fn test_from_primitive() { + assert_eq!(from_int(5), Some(Value { x: 5 })); + assert_eq!(from_i8(5), Some(Value { x: 5 })); + assert_eq!(from_i16(5), Some(Value { x: 5 })); + assert_eq!(from_i32(5), Some(Value { x: 5 })); + assert_eq!(from_i64(5), Some(Value { x: 5 })); + assert_eq!(from_uint(5), Some(Value { x: 5 })); + assert_eq!(from_u8(5), Some(Value { x: 5 })); + assert_eq!(from_u16(5), Some(Value { x: 5 })); + assert_eq!(from_u32(5), Some(Value { x: 5 })); + assert_eq!(from_u64(5), Some(Value { x: 5 })); + assert_eq!(from_f32(5f32), Some(Value { x: 5 })); + assert_eq!(from_f64(5f64), Some(Value { x: 5 })); + } +} diff --git a/src/libstd/num/num.rs b/src/libstd/num/num.rs deleted file mode 100644 index 3097a8e138e..00000000000 --- a/src/libstd/num/num.rs +++ /dev/null @@ -1,1596 +0,0 @@ -// Copyright 2012-2013 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Numeric traits and functions for generic mathematics. -//! -//! These are implemented for the primitive numeric types in `std::{u8, u16, -//! u32, u64, uint, i8, i16, i32, i64, int, f32, f64, float}`. - -#[allow(missing_doc)]; - -use clone::{Clone, DeepClone}; -use cmp::{Eq, ApproxEq, Ord}; -use ops::{Add, Sub, Mul, Div, Rem, Neg}; -use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr}; -use option::{Option, Some, None}; - -pub mod strconv; - -/// The base trait for numeric types -pub trait Num: Eq + Zero + One - + Neg - + Add - + Sub - + Mul - + Div - + Rem {} - -pub trait Orderable: Ord { - // These should be methods on `Ord`, with overridable default implementations. We don't want - // to encumber all implementors of Ord by requiring them to implement these functions, but at - // the same time we want to be able to take advantage of the speed of the specific numeric - // functions (like the `fmin` and `fmax` intrinsics). - fn min(&self, other: &Self) -> Self; - fn max(&self, other: &Self) -> Self; - fn clamp(&self, mn: &Self, mx: &Self) -> Self; -} - -/// Return the smaller number. -#[inline(always)] pub fn min(x: T, y: T) -> T { x.min(&y) } -/// Return the larger number. -#[inline(always)] pub fn max(x: T, y: T) -> T { x.max(&y) } -/// Returns the number constrained within the range `mn <= self <= mx`. -#[inline(always)] pub fn clamp(value: T, mn: T, mx: T) -> T { value.clamp(&mn, &mx) } - -pub trait Zero { - fn zero() -> Self; // FIXME (#5527): This should be an associated constant - fn is_zero(&self) -> bool; -} - -/// Returns `0` of appropriate type. -#[inline(always)] pub fn zero() -> T { Zero::zero() } - -pub trait One { - fn one() -> Self; // FIXME (#5527): This should be an associated constant -} - -/// Returns `1` of appropriate type. -#[inline(always)] pub fn one() -> T { One::one() } - -pub trait Signed: Num - + Neg { - fn abs(&self) -> Self; - fn abs_sub(&self, other: &Self) -> Self; - fn signum(&self) -> Self; - - fn is_positive(&self) -> bool; - fn is_negative(&self) -> bool; -} - -/// Computes the absolute value. -/// -/// For float, f32, and f64, `NaN` will be returned if the number is `NaN` -#[inline(always)] pub fn abs(value: T) -> T { value.abs() } -/// The positive difference of two numbers. -/// -/// Returns `zero` if the number is less than or equal to `other`, -/// otherwise the difference between `self` and `other` is returned. -#[inline(always)] pub fn abs_sub(x: T, y: T) -> T { x.abs_sub(&y) } -/// Returns the sign of the number. -/// -/// For float, f32, f64: -/// - `1.0` if the number is positive, `+0.0` or `INFINITY` -/// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY` -/// - `NAN` if the number is `NAN` -/// -/// For int: -/// - `0` if the number is zero -/// - `1` if the number is positive -/// - `-1` if the number is negative -#[inline(always)] pub fn signum(value: T) -> T { value.signum() } - -pub trait Unsigned: Num {} - -/// Times trait -/// -/// ```rust -/// use num::Times; -/// let ten = 10 as uint; -/// let mut accum = 0; -/// do ten.times { accum += 1; } -/// ``` -/// -pub trait Times { - fn times(&self, it: &fn()); -} - -pub trait Integer: Num - + Orderable - + Div - + Rem { - fn div_rem(&self, other: &Self) -> (Self,Self); - - fn div_floor(&self, other: &Self) -> Self; - fn mod_floor(&self, other: &Self) -> Self; - fn div_mod_floor(&self, other: &Self) -> (Self,Self); - - fn gcd(&self, other: &Self) -> Self; - fn lcm(&self, other: &Self) -> Self; - - fn is_multiple_of(&self, other: &Self) -> bool; - fn is_even(&self) -> bool; - fn is_odd(&self) -> bool; -} - -/// Calculates the Greatest Common Divisor (GCD) of the number and `other`. -/// -/// The result is always positive. -#[inline(always)] pub fn gcd(x: T, y: T) -> T { x.gcd(&y) } -/// Calculates the Lowest Common Multiple (LCM) of the number and `other`. -#[inline(always)] pub fn lcm(x: T, y: T) -> T { x.lcm(&y) } - -pub trait Round { - fn floor(&self) -> Self; - fn ceil(&self) -> Self; - fn round(&self) -> Self; - fn trunc(&self) -> Self; - fn fract(&self) -> Self; -} - -pub trait Fractional: Num - + Orderable - + Round - + Div { - fn recip(&self) -> Self; -} - -pub trait Algebraic { - fn pow(&self, n: &Self) -> Self; - fn sqrt(&self) -> Self; - fn rsqrt(&self) -> Self; - fn cbrt(&self) -> Self; - fn hypot(&self, other: &Self) -> Self; -} - -/// Raise a number to a power. -/// -/// # Example -/// -/// ```rust -/// let sixteen: float = num::pow(2.0, 4.0); -/// assert_eq!(sixteen, 16.0); -/// ``` -#[inline(always)] pub fn pow(value: T, n: T) -> T { value.pow(&n) } -/// Take the squre root of a number. -#[inline(always)] pub fn sqrt(value: T) -> T { value.sqrt() } -/// Take the reciprocal (inverse) square root of a number, `1/sqrt(x)`. -#[inline(always)] pub fn rsqrt(value: T) -> T { value.rsqrt() } -/// Take the cubic root of a number. -#[inline(always)] pub fn cbrt(value: T) -> T { value.cbrt() } -/// Calculate the length of the hypotenuse of a right-angle triangle given legs of length `x` and -/// `y`. -#[inline(always)] pub fn hypot(x: T, y: T) -> T { x.hypot(&y) } - -pub trait Trigonometric { - fn sin(&self) -> Self; - fn cos(&self) -> Self; - fn tan(&self) -> Self; - - fn asin(&self) -> Self; - fn acos(&self) -> Self; - fn atan(&self) -> Self; - - fn atan2(&self, other: &Self) -> Self; - fn sin_cos(&self) -> (Self, Self); -} - -/// Sine function. -#[inline(always)] pub fn sin(value: T) -> T { value.sin() } -/// Cosine function. -#[inline(always)] pub fn cos(value: T) -> T { value.cos() } -/// Tangent function. -#[inline(always)] pub fn tan(value: T) -> T { value.tan() } - -/// Compute the arcsine of the number. -#[inline(always)] pub fn asin(value: T) -> T { value.asin() } -/// Compute the arccosine of the number. -#[inline(always)] pub fn acos(value: T) -> T { value.acos() } -/// Compute the arctangent of the number. -#[inline(always)] pub fn atan(value: T) -> T { value.atan() } - -/// Compute the arctangent with 2 arguments. -#[inline(always)] pub fn atan2(x: T, y: T) -> T { x.atan2(&y) } -/// Simultaneously computes the sine and cosine of the number. -#[inline(always)] pub fn sin_cos(value: T) -> (T, T) { value.sin_cos() } - -pub trait Exponential { - fn exp(&self) -> Self; - fn exp2(&self) -> Self; - - fn ln(&self) -> Self; - fn log(&self, base: &Self) -> Self; - fn log2(&self) -> Self; - fn log10(&self) -> Self; -} - -/// Returns `e^(value)`, (the exponential function). -#[inline(always)] pub fn exp(value: T) -> T { value.exp() } -/// Returns 2 raised to the power of the number, `2^(value)`. -#[inline(always)] pub fn exp2(value: T) -> T { value.exp2() } - -/// Returns the natural logarithm of the number. -#[inline(always)] pub fn ln(value: T) -> T { value.ln() } -/// Returns the logarithm of the number with respect to an arbitrary base. -#[inline(always)] pub fn log(value: T, base: T) -> T { value.log(&base) } -/// Returns the base 2 logarithm of the number. -#[inline(always)] pub fn log2(value: T) -> T { value.log2() } -/// Returns the base 10 logarithm of the number. -#[inline(always)] pub fn log10(value: T) -> T { value.log10() } - -pub trait Hyperbolic: Exponential { - fn sinh(&self) -> Self; - fn cosh(&self) -> Self; - fn tanh(&self) -> Self; - - fn asinh(&self) -> Self; - fn acosh(&self) -> Self; - fn atanh(&self) -> Self; -} - -/// Hyperbolic cosine function. -#[inline(always)] pub fn sinh(value: T) -> T { value.sinh() } -/// Hyperbolic sine function. -#[inline(always)] pub fn cosh(value: T) -> T { value.cosh() } -/// Hyperbolic tangent function. -#[inline(always)] pub fn tanh(value: T) -> T { value.tanh() } - -/// Inverse hyperbolic sine function. -#[inline(always)] pub fn asinh(value: T) -> T { value.asinh() } -/// Inverse hyperbolic cosine function. -#[inline(always)] pub fn acosh(value: T) -> T { value.acosh() } -/// Inverse hyperbolic tangent function. -#[inline(always)] pub fn atanh(value: T) -> T { value.atanh() } - -/// Defines constants and methods common to real numbers -pub trait Real: Signed - + Fractional - + Algebraic - + Trigonometric - + Hyperbolic { - // Common Constants - // FIXME (#5527): These should be associated constants - fn pi() -> Self; - fn two_pi() -> Self; - fn frac_pi_2() -> Self; - fn frac_pi_3() -> Self; - fn frac_pi_4() -> Self; - fn frac_pi_6() -> Self; - fn frac_pi_8() -> Self; - fn frac_1_pi() -> Self; - fn frac_2_pi() -> Self; - fn frac_2_sqrtpi() -> Self; - fn sqrt2() -> Self; - fn frac_1_sqrt2() -> Self; - fn e() -> Self; - fn log2_e() -> Self; - fn log10_e() -> Self; - fn ln_2() -> Self; - fn ln_10() -> Self; - - // Angular conversions - fn to_degrees(&self) -> Self; - fn to_radians(&self) -> Self; -} - -/// Methods that are harder to implement and not commonly used. -pub trait RealExt: Real { - // FIXME (#5527): usages of `int` should be replaced with an associated - // integer type once these are implemented - - // Gamma functions - fn lgamma(&self) -> (int, Self); - fn tgamma(&self) -> Self; - - // Bessel functions - fn j0(&self) -> Self; - fn j1(&self) -> Self; - fn jn(&self, n: int) -> Self; - fn y0(&self) -> Self; - fn y1(&self) -> Self; - fn yn(&self, n: int) -> Self; -} - -/// Collects the bitwise operators under one trait. -pub trait Bitwise: Not - + BitAnd - + BitOr - + BitXor - + Shl - + Shr {} - -pub trait BitCount { - fn population_count(&self) -> Self; - fn leading_zeros(&self) -> Self; - fn trailing_zeros(&self) -> Self; -} - -pub trait Bounded { - // FIXME (#5527): These should be associated constants - fn min_value() -> Self; - fn max_value() -> Self; -} - -/// Specifies the available operations common to all of Rust's core numeric primitives. -/// These may not always make sense from a purely mathematical point of view, but -/// may be useful for systems programming. -pub trait Primitive: Clone - + DeepClone - + Num - + NumCast - + Orderable - + Bounded - + Neg - + Add - + Sub - + Mul - + Div - + Rem { - // FIXME (#5527): These should be associated constants - // FIXME (#8888): Removing `unused_self` requires #8888 to be fixed. - fn bits(unused_self: Option) -> uint; - fn bytes(unused_self: Option) -> uint; - fn is_signed(unused_self: Option) -> bool; -} - -/// A collection of traits relevant to primitive signed and unsigned integers -pub trait Int: Integer - + Primitive - + Bitwise - + BitCount {} - -/// Used for representing the classification of floating point numbers -#[deriving(Eq)] -pub enum FPCategory { - /// "Not a Number", often obtained by dividing by zero - FPNaN, - /// Positive or negative infinity - FPInfinite , - /// Positive or negative zero - FPZero, - /// De-normalized floating point representation (less precise than `FPNormal`) - FPSubnormal, - /// A regular floating point number - FPNormal, -} - -/// Primitive floating point numbers -pub trait Float: Real - + Signed - + Primitive - + ApproxEq { - // FIXME (#5527): These should be associated constants - fn nan() -> Self; - fn infinity() -> Self; - fn neg_infinity() -> Self; - fn neg_zero() -> Self; - - fn is_nan(&self) -> bool; - fn is_infinite(&self) -> bool; - fn is_finite(&self) -> bool; - fn is_normal(&self) -> bool; - fn classify(&self) -> FPCategory; - - // FIXME (#8888): Removing `unused_self` requires #8888 to be fixed. - fn mantissa_digits(unused_self: Option) -> uint; - fn digits(unused_self: Option) -> uint; - fn epsilon() -> Self; - fn min_exp(unused_self: Option) -> int; - fn max_exp(unused_self: Option) -> int; - fn min_10_exp(unused_self: Option) -> int; - fn max_10_exp(unused_self: Option) -> int; - - fn ldexp(x: Self, exp: int) -> Self; - fn frexp(&self) -> (Self, int); - - fn exp_m1(&self) -> Self; - fn ln_1p(&self) -> Self; - fn mul_add(&self, a: Self, b: Self) -> Self; - fn next_after(&self, other: Self) -> Self; -} - -/// Returns the exponential of the number, minus `1`, `exp(n) - 1`, in a way -/// that is accurate even if the number is close to zero. -#[inline(always)] pub fn exp_m1(value: T) -> T { value.exp_m1() } -/// Returns the natural logarithm of the number plus `1`, `ln(n + 1)`, more -/// accurately than if the operations were performed separately. -#[inline(always)] pub fn ln_1p(value: T) -> T { value.ln_1p() } -/// Fused multiply-add. Computes `(a * b) + c` with only one rounding error. -/// -/// This produces a more accurate result with better performance (on some -/// architectures) than a separate multiplication operation followed by an add. -#[inline(always)] pub fn mul_add(a: T, b: T, c: T) -> T { a.mul_add(b, c) } - -/// A generic trait for converting a value to a number. -pub trait ToPrimitive { - /// Converts the value of `self` to an `int`. - #[inline] - fn to_int(&self) -> Option { - self.to_i64().and_then(|x| x.to_int()) - } - - /// Converts the value of `self` to an `i8`. - #[inline] - fn to_i8(&self) -> Option { - self.to_i64().and_then(|x| x.to_i8()) - } - - /// Converts the value of `self` to an `i16`. - #[inline] - fn to_i16(&self) -> Option { - self.to_i64().and_then(|x| x.to_i16()) - } - - /// Converts the value of `self` to an `i32`. - #[inline] - fn to_i32(&self) -> Option { - self.to_i64().and_then(|x| x.to_i32()) - } - - /// Converts the value of `self` to an `i64`. - fn to_i64(&self) -> Option; - - /// Converts the value of `self` to an `uint`. - #[inline] - fn to_uint(&self) -> Option { - self.to_u64().and_then(|x| x.to_uint()) - } - - /// Converts the value of `self` to an `u8`. - #[inline] - fn to_u8(&self) -> Option { - self.to_u64().and_then(|x| x.to_u8()) - } - - /// Converts the value of `self` to an `u16`. - #[inline] - fn to_u16(&self) -> Option { - self.to_u64().and_then(|x| x.to_u16()) - } - - /// Converts the value of `self` to an `u32`. - #[inline] - fn to_u32(&self) -> Option { - self.to_u64().and_then(|x| x.to_u32()) - } - - /// Converts the value of `self` to an `u64`. - #[inline] - fn to_u64(&self) -> Option; - - /// Converts the value of `self` to an `f32`. - #[inline] - fn to_f32(&self) -> Option { - self.to_f64().and_then(|x| x.to_f32()) - } - - /// Converts the value of `self` to an `f64`. - #[inline] - fn to_f64(&self) -> Option { - self.to_i64().and_then(|x| x.to_f64()) - } -} - -macro_rules! impl_to_primitive_int_to_int( - ($SrcT:ty, $DstT:ty) => ( - { - if Primitive::bits(None::<$SrcT>) <= Primitive::bits(None::<$DstT>) { - Some(*self as $DstT) - } else { - let n = *self as i64; - let min_value: $DstT = Bounded::min_value(); - let max_value: $DstT = Bounded::max_value(); - if min_value as i64 <= n && n <= max_value as i64 { - Some(*self as $DstT) - } else { - None - } - } - } - ) -) - -macro_rules! impl_to_primitive_int_to_uint( - ($SrcT:ty, $DstT:ty) => ( - { - let zero: $SrcT = Zero::zero(); - let max_value: $DstT = Bounded::max_value(); - if zero <= *self && *self as u64 <= max_value as u64 { - Some(*self as $DstT) - } else { - None - } - } - ) -) - -macro_rules! impl_to_primitive_int( - ($T:ty) => ( - impl ToPrimitive for $T { - #[inline] - fn to_int(&self) -> Option { impl_to_primitive_int_to_int!($T, int) } - #[inline] - fn to_i8(&self) -> Option { impl_to_primitive_int_to_int!($T, i8) } - #[inline] - fn to_i16(&self) -> Option { impl_to_primitive_int_to_int!($T, i16) } - #[inline] - fn to_i32(&self) -> Option { impl_to_primitive_int_to_int!($T, i32) } - #[inline] - fn to_i64(&self) -> Option { impl_to_primitive_int_to_int!($T, i64) } - - #[inline] - fn to_uint(&self) -> Option { impl_to_primitive_int_to_uint!($T, uint) } - #[inline] - fn to_u8(&self) -> Option { impl_to_primitive_int_to_uint!($T, u8) } - #[inline] - fn to_u16(&self) -> Option { impl_to_primitive_int_to_uint!($T, u16) } - #[inline] - fn to_u32(&self) -> Option { impl_to_primitive_int_to_uint!($T, u32) } - #[inline] - fn to_u64(&self) -> Option { impl_to_primitive_int_to_uint!($T, u64) } - - #[inline] - fn to_f32(&self) -> Option { Some(*self as f32) } - #[inline] - fn to_f64(&self) -> Option { Some(*self as f64) } - } - ) -) - -impl_to_primitive_int!(int) -impl_to_primitive_int!(i8) -impl_to_primitive_int!(i16) -impl_to_primitive_int!(i32) -impl_to_primitive_int!(i64) - -macro_rules! impl_to_primitive_uint_to_int( - ($DstT:ty) => ( - { - let max_value: $DstT = Bounded::max_value(); - if *self as u64 <= max_value as u64 { - Some(*self as $DstT) - } else { - None - } - } - ) -) - -macro_rules! impl_to_primitive_uint_to_uint( - ($SrcT:ty, $DstT:ty) => ( - { - if Primitive::bits(None::<$SrcT>) <= Primitive::bits(None::<$DstT>) { - Some(*self as $DstT) - } else { - let zero: $SrcT = Zero::zero(); - let max_value: $DstT = Bounded::max_value(); - if zero <= *self && *self as u64 <= max_value as u64 { - Some(*self as $DstT) - } else { - None - } - } - } - ) -) - -macro_rules! impl_to_primitive_uint( - ($T:ty) => ( - impl ToPrimitive for $T { - #[inline] - fn to_int(&self) -> Option { impl_to_primitive_uint_to_int!(int) } - #[inline] - fn to_i8(&self) -> Option { impl_to_primitive_uint_to_int!(i8) } - #[inline] - fn to_i16(&self) -> Option { impl_to_primitive_uint_to_int!(i16) } - #[inline] - fn to_i32(&self) -> Option { impl_to_primitive_uint_to_int!(i32) } - #[inline] - fn to_i64(&self) -> Option { impl_to_primitive_uint_to_int!(i64) } - - #[inline] - fn to_uint(&self) -> Option { impl_to_primitive_uint_to_uint!($T, uint) } - #[inline] - fn to_u8(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u8) } - #[inline] - fn to_u16(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u16) } - #[inline] - fn to_u32(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u32) } - #[inline] - fn to_u64(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u64) } - - #[inline] - fn to_f32(&self) -> Option { Some(*self as f32) } - #[inline] - fn to_f64(&self) -> Option { Some(*self as f64) } - } - ) -) - -impl_to_primitive_uint!(uint) -impl_to_primitive_uint!(u8) -impl_to_primitive_uint!(u16) -impl_to_primitive_uint!(u32) -impl_to_primitive_uint!(u64) - -macro_rules! impl_to_primitive_float_to_float( - ($SrcT:ty, $DstT:ty) => ( - if Primitive::bits(None::<$SrcT>) <= Primitive::bits(None::<$DstT>) { - Some(*self as $DstT) - } else { - let n = *self as f64; - let max_value: $SrcT = Bounded::max_value(); - if -max_value as f64 <= n && n <= max_value as f64 { - Some(*self as $DstT) - } else { - None - } - } - ) -) - -macro_rules! impl_to_primitive_float( - ($T:ty) => ( - impl ToPrimitive for $T { - #[inline] - fn to_int(&self) -> Option { Some(*self as int) } - #[inline] - fn to_i8(&self) -> Option { Some(*self as i8) } - #[inline] - fn to_i16(&self) -> Option { Some(*self as i16) } - #[inline] - fn to_i32(&self) -> Option { Some(*self as i32) } - #[inline] - fn to_i64(&self) -> Option { Some(*self as i64) } - - #[inline] - fn to_uint(&self) -> Option { Some(*self as uint) } - #[inline] - fn to_u8(&self) -> Option { Some(*self as u8) } - #[inline] - fn to_u16(&self) -> Option { Some(*self as u16) } - #[inline] - fn to_u32(&self) -> Option { Some(*self as u32) } - #[inline] - fn to_u64(&self) -> Option { Some(*self as u64) } - - #[inline] - fn to_f32(&self) -> Option { impl_to_primitive_float_to_float!($T, f32) } - #[inline] - fn to_f64(&self) -> Option { impl_to_primitive_float_to_float!($T, f64) } - } - ) -) - -impl_to_primitive_float!(f32) -impl_to_primitive_float!(f64) - -/// A generic trait for converting a number to a value. -pub trait FromPrimitive { - /// Convert an `int` to return an optional value of this type. If the - /// value cannot be represented by this value, the `None` is returned. - #[inline] - fn from_int(n: int) -> Option { - FromPrimitive::from_i64(n as i64) - } - - /// Convert an `i8` to return an optional value of this type. If the - /// type cannot be represented by this value, the `None` is returned. - #[inline] - fn from_i8(n: i8) -> Option { - FromPrimitive::from_i64(n as i64) - } - - /// Convert an `i16` to return an optional value of this type. If the - /// type cannot be represented by this value, the `None` is returned. - #[inline] - fn from_i16(n: i16) -> Option { - FromPrimitive::from_i64(n as i64) - } - - /// Convert an `i32` to return an optional value of this type. If the - /// type cannot be represented by this value, the `None` is returned. - #[inline] - fn from_i32(n: i32) -> Option { - FromPrimitive::from_i64(n as i64) - } - - /// Convert an `i64` to return an optional value of this type. If the - /// type cannot be represented by this value, the `None` is returned. - fn from_i64(n: i64) -> Option; - - /// Convert an `uint` to return an optional value of this type. If the - /// type cannot be represented by this value, the `None` is returned. - #[inline] - fn from_uint(n: uint) -> Option { - FromPrimitive::from_u64(n as u64) - } - - /// Convert an `u8` to return an optional value of this type. If the - /// type cannot be represented by this value, the `None` is returned. - #[inline] - fn from_u8(n: u8) -> Option { - FromPrimitive::from_u64(n as u64) - } - - /// Convert an `u16` to return an optional value of this type. If the - /// type cannot be represented by this value, the `None` is returned. - #[inline] - fn from_u16(n: u16) -> Option { - FromPrimitive::from_u64(n as u64) - } - - /// Convert an `u32` to return an optional value of this type. If the - /// type cannot be represented by this value, the `None` is returned. - #[inline] - fn from_u32(n: u32) -> Option { - FromPrimitive::from_u64(n as u64) - } - - /// Convert an `u64` to return an optional value of this type. If the - /// type cannot be represented by this value, the `None` is returned. - fn from_u64(n: u64) -> Option; - - /// Convert a `f32` to return an optional value of this type. If the - /// type cannot be represented by this value, the `None` is returned. - #[inline] - fn from_f32(n: f32) -> Option { - FromPrimitive::from_f64(n as f64) - } - - /// Convert a `f64` to return an optional value of this type. If the - /// type cannot be represented by this value, the `None` is returned. - #[inline] - fn from_f64(n: f64) -> Option { - FromPrimitive::from_i64(n as i64) - } -} - -/// A utility function that just calls `FromPrimitive::from_int`. -pub fn from_int(n: int) -> Option { - FromPrimitive::from_int(n) -} - -/// A utility function that just calls `FromPrimitive::from_i8`. -pub fn from_i8(n: i8) -> Option { - FromPrimitive::from_i8(n) -} - -/// A utility function that just calls `FromPrimitive::from_i16`. -pub fn from_i16(n: i16) -> Option { - FromPrimitive::from_i16(n) -} - -/// A utility function that just calls `FromPrimitive::from_i32`. -pub fn from_i32(n: i32) -> Option { - FromPrimitive::from_i32(n) -} - -/// A utility function that just calls `FromPrimitive::from_i64`. -pub fn from_i64(n: i64) -> Option { - FromPrimitive::from_i64(n) -} - -/// A utility function that just calls `FromPrimitive::from_uint`. -pub fn from_uint(n: uint) -> Option { - FromPrimitive::from_uint(n) -} - -/// A utility function that just calls `FromPrimitive::from_u8`. -pub fn from_u8(n: u8) -> Option { - FromPrimitive::from_u8(n) -} - -/// A utility function that just calls `FromPrimitive::from_u16`. -pub fn from_u16(n: u16) -> Option { - FromPrimitive::from_u16(n) -} - -/// A utility function that just calls `FromPrimitive::from_u32`. -pub fn from_u32(n: u32) -> Option { - FromPrimitive::from_u32(n) -} - -/// A utility function that just calls `FromPrimitive::from_u64`. -pub fn from_u64(n: u64) -> Option { - FromPrimitive::from_u64(n) -} - -/// A utility function that just calls `FromPrimitive::from_f32`. -pub fn from_f32(n: f32) -> Option { - FromPrimitive::from_f32(n) -} - -/// A utility function that just calls `FromPrimitive::from_f64`. -pub fn from_f64(n: f64) -> Option { - FromPrimitive::from_f64(n) -} - -macro_rules! impl_from_primitive( - ($T:ty, $to_ty:expr) => ( - impl FromPrimitive for $T { - #[inline] fn from_int(n: int) -> Option<$T> { $to_ty } - #[inline] fn from_i8(n: i8) -> Option<$T> { $to_ty } - #[inline] fn from_i16(n: i16) -> Option<$T> { $to_ty } - #[inline] fn from_i32(n: i32) -> Option<$T> { $to_ty } - #[inline] fn from_i64(n: i64) -> Option<$T> { $to_ty } - - #[inline] fn from_uint(n: uint) -> Option<$T> { $to_ty } - #[inline] fn from_u8(n: u8) -> Option<$T> { $to_ty } - #[inline] fn from_u16(n: u16) -> Option<$T> { $to_ty } - #[inline] fn from_u32(n: u32) -> Option<$T> { $to_ty } - #[inline] fn from_u64(n: u64) -> Option<$T> { $to_ty } - - #[inline] fn from_f32(n: f32) -> Option<$T> { $to_ty } - #[inline] fn from_f64(n: f64) -> Option<$T> { $to_ty } - } - ) -) - -impl_from_primitive!(int, n.to_int()) -impl_from_primitive!(i8, n.to_i8()) -impl_from_primitive!(i16, n.to_i16()) -impl_from_primitive!(i32, n.to_i32()) -impl_from_primitive!(i64, n.to_i64()) -impl_from_primitive!(uint, n.to_uint()) -impl_from_primitive!(u8, n.to_u8()) -impl_from_primitive!(u16, n.to_u16()) -impl_from_primitive!(u32, n.to_u32()) -impl_from_primitive!(u64, n.to_u64()) -impl_from_primitive!(f32, n.to_f32()) -impl_from_primitive!(f64, n.to_f64()) - -/// Cast from one machine scalar to another. -/// -/// # Example -/// -/// ``` -/// let twenty: f32 = num::cast(0x14).unwrap(); -/// assert_eq!(twenty, 20f32); -/// ``` -/// -#[inline] -pub fn cast(n: T) -> Option { - NumCast::from(n) -} - -/// An interface for casting between machine scalars -pub trait NumCast: ToPrimitive { - fn from(n: T) -> Option; -} - -macro_rules! impl_num_cast( - ($T:ty, $conv:ident) => ( - impl NumCast for $T { - #[inline] - fn from(n: N) -> Option<$T> { - // `$conv` could be generated using `concat_idents!`, but that - // macro seems to be broken at the moment - n.$conv() - } - } - ) -) - -impl_num_cast!(u8, to_u8) -impl_num_cast!(u16, to_u16) -impl_num_cast!(u32, to_u32) -impl_num_cast!(u64, to_u64) -impl_num_cast!(uint, to_uint) -impl_num_cast!(i8, to_i8) -impl_num_cast!(i16, to_i16) -impl_num_cast!(i32, to_i32) -impl_num_cast!(i64, to_i64) -impl_num_cast!(int, to_int) -impl_num_cast!(f32, to_f32) -impl_num_cast!(f64, to_f64) - -pub trait ToStrRadix { - fn to_str_radix(&self, radix: uint) -> ~str; -} - -pub trait FromStrRadix { - fn from_str_radix(str: &str, radix: uint) -> Option; -} - -/// A utility function that just calls FromStrRadix::from_str_radix. -pub fn from_str_radix(str: &str, radix: uint) -> Option { - FromStrRadix::from_str_radix(str, radix) -} - -/// Calculates a power to a given radix, optimized for uint `pow` and `radix`. -/// -/// Returns `radix^pow` as `T`. -/// -/// Note: -/// Also returns `1` for `0^0`, despite that technically being an -/// undefined number. The reason for this is twofold: -/// - If code written to use this function cares about that special case, it's -/// probably going to catch it before making the call. -/// - If code written to use this function doesn't care about it, it's -/// probably assuming that `x^0` always equals `1`. -/// -pub fn pow_with_uint+Mul>(radix: uint, pow: uint) -> T { - let _0: T = Zero::zero(); - let _1: T = One::one(); - - if pow == 0u { return _1; } - if radix == 0u { return _0; } - let mut my_pow = pow; - let mut total = _1; - let mut multiplier = cast(radix).unwrap(); - while (my_pow > 0u) { - if my_pow % 2u == 1u { - total = total * multiplier; - } - my_pow = my_pow / 2u; - multiplier = multiplier * multiplier; - } - total -} - -impl Zero for @mut T { - fn zero() -> @mut T { @mut Zero::zero() } - fn is_zero(&self) -> bool { (**self).is_zero() } -} - -impl Zero for @T { - fn zero() -> @T { @Zero::zero() } - fn is_zero(&self) -> bool { (**self).is_zero() } -} - -impl Zero for ~T { - fn zero() -> ~T { ~Zero::zero() } - fn is_zero(&self) -> bool { (**self).is_zero() } -} - -/// Saturating math operations -pub trait Saturating { - /// Saturating addition operator. - /// Returns a+b, saturating at the numeric bounds instead of overflowing. - fn saturating_add(self, v: Self) -> Self; - - /// Saturating subtraction operator. - /// Returns a-b, saturating at the numeric bounds instead of overflowing. - fn saturating_sub(self, v: Self) -> Self; -} - -impl Saturating for T { - #[inline] - fn saturating_add(self, v: T) -> T { - match self.checked_add(&v) { - Some(x) => x, - None => if v >= Zero::zero() { - Bounded::max_value() - } else { - Bounded::min_value() - } - } - } - - #[inline] - fn saturating_sub(self, v: T) -> T { - match self.checked_sub(&v) { - Some(x) => x, - None => if v >= Zero::zero() { - Bounded::min_value() - } else { - Bounded::max_value() - } - } - } -} - -pub trait CheckedAdd: Add { - fn checked_add(&self, v: &Self) -> Option; -} - -pub trait CheckedSub: Sub { - fn checked_sub(&self, v: &Self) -> Option; -} - -pub trait CheckedMul: Mul { - fn checked_mul(&self, v: &Self) -> Option; -} - -pub trait CheckedDiv: Div { - fn checked_div(&self, v: &Self) -> Option; -} - -/// Helper function for testing numeric operations -#[cfg(test)] -pub fn test_num(ten: T, two: T) { - assert_eq!(ten.add(&two), cast(12).unwrap()); - assert_eq!(ten.sub(&two), cast(8).unwrap()); - assert_eq!(ten.mul(&two), cast(20).unwrap()); - assert_eq!(ten.div(&two), cast(5).unwrap()); - assert_eq!(ten.rem(&two), cast(0).unwrap()); - - assert_eq!(ten.add(&two), ten + two); - assert_eq!(ten.sub(&two), ten - two); - assert_eq!(ten.mul(&two), ten * two); - assert_eq!(ten.div(&two), ten / two); - assert_eq!(ten.rem(&two), ten % two); -} - -#[cfg(test)] -mod tests { - use prelude::*; - use super::*; - use i8; - use i16; - use i32; - use i64; - use int; - use u8; - use u16; - use u32; - use u64; - use uint; - - macro_rules! test_cast_20( - ($_20:expr) => ({ - let _20 = $_20; - - assert_eq!(20u, _20.to_uint().unwrap()); - assert_eq!(20u8, _20.to_u8().unwrap()); - assert_eq!(20u16, _20.to_u16().unwrap()); - assert_eq!(20u32, _20.to_u32().unwrap()); - assert_eq!(20u64, _20.to_u64().unwrap()); - assert_eq!(20i, _20.to_int().unwrap()); - assert_eq!(20i8, _20.to_i8().unwrap()); - assert_eq!(20i16, _20.to_i16().unwrap()); - assert_eq!(20i32, _20.to_i32().unwrap()); - assert_eq!(20i64, _20.to_i64().unwrap()); - assert_eq!(20f32, _20.to_f32().unwrap()); - assert_eq!(20f64, _20.to_f64().unwrap()); - - assert_eq!(_20, NumCast::from(20u).unwrap()); - assert_eq!(_20, NumCast::from(20u8).unwrap()); - assert_eq!(_20, NumCast::from(20u16).unwrap()); - assert_eq!(_20, NumCast::from(20u32).unwrap()); - assert_eq!(_20, NumCast::from(20u64).unwrap()); - assert_eq!(_20, NumCast::from(20i).unwrap()); - assert_eq!(_20, NumCast::from(20i8).unwrap()); - assert_eq!(_20, NumCast::from(20i16).unwrap()); - assert_eq!(_20, NumCast::from(20i32).unwrap()); - assert_eq!(_20, NumCast::from(20i64).unwrap()); - assert_eq!(_20, NumCast::from(20f32).unwrap()); - assert_eq!(_20, NumCast::from(20f64).unwrap()); - - assert_eq!(_20, cast(20u).unwrap()); - assert_eq!(_20, cast(20u8).unwrap()); - assert_eq!(_20, cast(20u16).unwrap()); - assert_eq!(_20, cast(20u32).unwrap()); - assert_eq!(_20, cast(20u64).unwrap()); - assert_eq!(_20, cast(20i).unwrap()); - assert_eq!(_20, cast(20i8).unwrap()); - assert_eq!(_20, cast(20i16).unwrap()); - assert_eq!(_20, cast(20i32).unwrap()); - assert_eq!(_20, cast(20i64).unwrap()); - assert_eq!(_20, cast(20f32).unwrap()); - assert_eq!(_20, cast(20f64).unwrap()); - }) - ) - - #[test] fn test_u8_cast() { test_cast_20!(20u8) } - #[test] fn test_u16_cast() { test_cast_20!(20u16) } - #[test] fn test_u32_cast() { test_cast_20!(20u32) } - #[test] fn test_u64_cast() { test_cast_20!(20u64) } - #[test] fn test_uint_cast() { test_cast_20!(20u) } - #[test] fn test_i8_cast() { test_cast_20!(20i8) } - #[test] fn test_i16_cast() { test_cast_20!(20i16) } - #[test] fn test_i32_cast() { test_cast_20!(20i32) } - #[test] fn test_i64_cast() { test_cast_20!(20i64) } - #[test] fn test_int_cast() { test_cast_20!(20i) } - #[test] fn test_f32_cast() { test_cast_20!(20f32) } - #[test] fn test_f64_cast() { test_cast_20!(20f64) } - - #[test] - fn test_cast_range_int_min() { - assert_eq!(int::min_value.to_int(), Some(int::min_value as int)); - assert_eq!(int::min_value.to_i8(), None); - assert_eq!(int::min_value.to_i16(), None); - // int::min_value.to_i32() is word-size specific - assert_eq!(int::min_value.to_i64(), Some(int::min_value as i64)); - assert_eq!(int::min_value.to_uint(), None); - assert_eq!(int::min_value.to_u8(), None); - assert_eq!(int::min_value.to_u16(), None); - assert_eq!(int::min_value.to_u32(), None); - assert_eq!(int::min_value.to_u64(), None); - - #[cfg(target_word_size = "32")] - fn check_word_size() { - assert_eq!(int::min_value.to_i32(), Some(int::min_value as i32)); - } - - #[cfg(target_word_size = "64")] - fn check_word_size() { - assert_eq!(int::min_value.to_i32(), None); - } - - check_word_size(); - } - - #[test] - fn test_cast_range_i8_min() { - assert_eq!(i8::min_value.to_int(), Some(i8::min_value as int)); - assert_eq!(i8::min_value.to_i8(), Some(i8::min_value as i8)); - assert_eq!(i8::min_value.to_i16(), Some(i8::min_value as i16)); - assert_eq!(i8::min_value.to_i32(), Some(i8::min_value as i32)); - assert_eq!(i8::min_value.to_i64(), Some(i8::min_value as i64)); - assert_eq!(i8::min_value.to_uint(), None); - assert_eq!(i8::min_value.to_u8(), None); - assert_eq!(i8::min_value.to_u16(), None); - assert_eq!(i8::min_value.to_u32(), None); - assert_eq!(i8::min_value.to_u64(), None); - } - - #[test] - fn test_cast_range_i16_min() { - assert_eq!(i16::min_value.to_int(), Some(i16::min_value as int)); - assert_eq!(i16::min_value.to_i8(), None); - assert_eq!(i16::min_value.to_i16(), Some(i16::min_value as i16)); - assert_eq!(i16::min_value.to_i32(), Some(i16::min_value as i32)); - assert_eq!(i16::min_value.to_i64(), Some(i16::min_value as i64)); - assert_eq!(i16::min_value.to_uint(), None); - assert_eq!(i16::min_value.to_u8(), None); - assert_eq!(i16::min_value.to_u16(), None); - assert_eq!(i16::min_value.to_u32(), None); - assert_eq!(i16::min_value.to_u64(), None); - } - - #[test] - fn test_cast_range_i32_min() { - assert_eq!(i32::min_value.to_int(), Some(i32::min_value as int)); - assert_eq!(i32::min_value.to_i8(), None); - assert_eq!(i32::min_value.to_i16(), None); - assert_eq!(i32::min_value.to_i32(), Some(i32::min_value as i32)); - assert_eq!(i32::min_value.to_i64(), Some(i32::min_value as i64)); - assert_eq!(i32::min_value.to_uint(), None); - assert_eq!(i32::min_value.to_u8(), None); - assert_eq!(i32::min_value.to_u16(), None); - assert_eq!(i32::min_value.to_u32(), None); - assert_eq!(i32::min_value.to_u64(), None); - } - - #[test] - fn test_cast_range_i64_min() { - // i64::min_value.to_int() is word-size specific - assert_eq!(i64::min_value.to_i8(), None); - assert_eq!(i64::min_value.to_i16(), None); - assert_eq!(i64::min_value.to_i32(), None); - assert_eq!(i64::min_value.to_i64(), Some(i64::min_value as i64)); - assert_eq!(i64::min_value.to_uint(), None); - assert_eq!(i64::min_value.to_u8(), None); - assert_eq!(i64::min_value.to_u16(), None); - assert_eq!(i64::min_value.to_u32(), None); - assert_eq!(i64::min_value.to_u64(), None); - - #[cfg(target_word_size = "32")] - fn check_word_size() { - assert_eq!(i64::min_value.to_int(), None); - } - - #[cfg(target_word_size = "64")] - fn check_word_size() { - assert_eq!(i64::min_value.to_int(), Some(i64::min_value as int)); - } - - check_word_size(); - } - - #[test] - fn test_cast_range_int_max() { - assert_eq!(int::max_value.to_int(), Some(int::max_value as int)); - assert_eq!(int::max_value.to_i8(), None); - assert_eq!(int::max_value.to_i16(), None); - // int::max_value.to_i32() is word-size specific - assert_eq!(int::max_value.to_i64(), Some(int::max_value as i64)); - assert_eq!(int::max_value.to_u8(), None); - assert_eq!(int::max_value.to_u16(), None); - // int::max_value.to_u32() is word-size specific - assert_eq!(int::max_value.to_u64(), Some(int::max_value as u64)); - - #[cfg(target_word_size = "32")] - fn check_word_size() { - assert_eq!(int::max_value.to_i32(), Some(int::max_value as i32)); - assert_eq!(int::max_value.to_u32(), Some(int::max_value as u32)); - } - - #[cfg(target_word_size = "64")] - fn check_word_size() { - assert_eq!(int::max_value.to_i32(), None); - assert_eq!(int::max_value.to_u32(), None); - } - - check_word_size(); - } - - #[test] - fn test_cast_range_i8_max() { - assert_eq!(i8::max_value.to_int(), Some(i8::max_value as int)); - assert_eq!(i8::max_value.to_i8(), Some(i8::max_value as i8)); - assert_eq!(i8::max_value.to_i16(), Some(i8::max_value as i16)); - assert_eq!(i8::max_value.to_i32(), Some(i8::max_value as i32)); - assert_eq!(i8::max_value.to_i64(), Some(i8::max_value as i64)); - assert_eq!(i8::max_value.to_uint(), Some(i8::max_value as uint)); - assert_eq!(i8::max_value.to_u8(), Some(i8::max_value as u8)); - assert_eq!(i8::max_value.to_u16(), Some(i8::max_value as u16)); - assert_eq!(i8::max_value.to_u32(), Some(i8::max_value as u32)); - assert_eq!(i8::max_value.to_u64(), Some(i8::max_value as u64)); - } - - #[test] - fn test_cast_range_i16_max() { - assert_eq!(i16::max_value.to_int(), Some(i16::max_value as int)); - assert_eq!(i16::max_value.to_i8(), None); - assert_eq!(i16::max_value.to_i16(), Some(i16::max_value as i16)); - assert_eq!(i16::max_value.to_i32(), Some(i16::max_value as i32)); - assert_eq!(i16::max_value.to_i64(), Some(i16::max_value as i64)); - assert_eq!(i16::max_value.to_uint(), Some(i16::max_value as uint)); - assert_eq!(i16::max_value.to_u8(), None); - assert_eq!(i16::max_value.to_u16(), Some(i16::max_value as u16)); - assert_eq!(i16::max_value.to_u32(), Some(i16::max_value as u32)); - assert_eq!(i16::max_value.to_u64(), Some(i16::max_value as u64)); - } - - #[test] - fn test_cast_range_i32_max() { - assert_eq!(i32::max_value.to_int(), Some(i32::max_value as int)); - assert_eq!(i32::max_value.to_i8(), None); - assert_eq!(i32::max_value.to_i16(), None); - assert_eq!(i32::max_value.to_i32(), Some(i32::max_value as i32)); - assert_eq!(i32::max_value.to_i64(), Some(i32::max_value as i64)); - assert_eq!(i32::max_value.to_uint(), Some(i32::max_value as uint)); - assert_eq!(i32::max_value.to_u8(), None); - assert_eq!(i32::max_value.to_u16(), None); - assert_eq!(i32::max_value.to_u32(), Some(i32::max_value as u32)); - assert_eq!(i32::max_value.to_u64(), Some(i32::max_value as u64)); - } - - #[test] - fn test_cast_range_i64_max() { - // i64::max_value.to_int() is word-size specific - assert_eq!(i64::max_value.to_i8(), None); - assert_eq!(i64::max_value.to_i16(), None); - assert_eq!(i64::max_value.to_i32(), None); - assert_eq!(i64::max_value.to_i64(), Some(i64::max_value as i64)); - // i64::max_value.to_uint() is word-size specific - assert_eq!(i64::max_value.to_u8(), None); - assert_eq!(i64::max_value.to_u16(), None); - assert_eq!(i64::max_value.to_u32(), None); - assert_eq!(i64::max_value.to_u64(), Some(i64::max_value as u64)); - - #[cfg(target_word_size = "32")] - fn check_word_size() { - assert_eq!(i64::max_value.to_int(), None); - assert_eq!(i64::max_value.to_uint(), None); - } - - #[cfg(target_word_size = "64")] - fn check_word_size() { - assert_eq!(i64::max_value.to_int(), Some(i64::max_value as int)); - assert_eq!(i64::max_value.to_uint(), Some(i64::max_value as uint)); - } - - check_word_size(); - } - - #[test] - fn test_cast_range_uint_min() { - assert_eq!(uint::min_value.to_int(), Some(uint::min_value as int)); - assert_eq!(uint::min_value.to_i8(), Some(uint::min_value as i8)); - assert_eq!(uint::min_value.to_i16(), Some(uint::min_value as i16)); - assert_eq!(uint::min_value.to_i32(), Some(uint::min_value as i32)); - assert_eq!(uint::min_value.to_i64(), Some(uint::min_value as i64)); - assert_eq!(uint::min_value.to_uint(), Some(uint::min_value as uint)); - assert_eq!(uint::min_value.to_u8(), Some(uint::min_value as u8)); - assert_eq!(uint::min_value.to_u16(), Some(uint::min_value as u16)); - assert_eq!(uint::min_value.to_u32(), Some(uint::min_value as u32)); - assert_eq!(uint::min_value.to_u64(), Some(uint::min_value as u64)); - } - - #[test] - fn test_cast_range_u8_min() { - assert_eq!(u8::min_value.to_int(), Some(u8::min_value as int)); - assert_eq!(u8::min_value.to_i8(), Some(u8::min_value as i8)); - assert_eq!(u8::min_value.to_i16(), Some(u8::min_value as i16)); - assert_eq!(u8::min_value.to_i32(), Some(u8::min_value as i32)); - assert_eq!(u8::min_value.to_i64(), Some(u8::min_value as i64)); - assert_eq!(u8::min_value.to_uint(), Some(u8::min_value as uint)); - assert_eq!(u8::min_value.to_u8(), Some(u8::min_value as u8)); - assert_eq!(u8::min_value.to_u16(), Some(u8::min_value as u16)); - assert_eq!(u8::min_value.to_u32(), Some(u8::min_value as u32)); - assert_eq!(u8::min_value.to_u64(), Some(u8::min_value as u64)); - } - - #[test] - fn test_cast_range_u16_min() { - assert_eq!(u16::min_value.to_int(), Some(u16::min_value as int)); - assert_eq!(u16::min_value.to_i8(), Some(u16::min_value as i8)); - assert_eq!(u16::min_value.to_i16(), Some(u16::min_value as i16)); - assert_eq!(u16::min_value.to_i32(), Some(u16::min_value as i32)); - assert_eq!(u16::min_value.to_i64(), Some(u16::min_value as i64)); - assert_eq!(u16::min_value.to_uint(), Some(u16::min_value as uint)); - assert_eq!(u16::min_value.to_u8(), Some(u16::min_value as u8)); - assert_eq!(u16::min_value.to_u16(), Some(u16::min_value as u16)); - assert_eq!(u16::min_value.to_u32(), Some(u16::min_value as u32)); - assert_eq!(u16::min_value.to_u64(), Some(u16::min_value as u64)); - } - - #[test] - fn test_cast_range_u32_min() { - assert_eq!(u32::min_value.to_int(), Some(u32::min_value as int)); - assert_eq!(u32::min_value.to_i8(), Some(u32::min_value as i8)); - assert_eq!(u32::min_value.to_i16(), Some(u32::min_value as i16)); - assert_eq!(u32::min_value.to_i32(), Some(u32::min_value as i32)); - assert_eq!(u32::min_value.to_i64(), Some(u32::min_value as i64)); - assert_eq!(u32::min_value.to_uint(), Some(u32::min_value as uint)); - assert_eq!(u32::min_value.to_u8(), Some(u32::min_value as u8)); - assert_eq!(u32::min_value.to_u16(), Some(u32::min_value as u16)); - assert_eq!(u32::min_value.to_u32(), Some(u32::min_value as u32)); - assert_eq!(u32::min_value.to_u64(), Some(u32::min_value as u64)); - } - - #[test] - fn test_cast_range_u64_min() { - assert_eq!(u64::min_value.to_int(), Some(u64::min_value as int)); - assert_eq!(u64::min_value.to_i8(), Some(u64::min_value as i8)); - assert_eq!(u64::min_value.to_i16(), Some(u64::min_value as i16)); - assert_eq!(u64::min_value.to_i32(), Some(u64::min_value as i32)); - assert_eq!(u64::min_value.to_i64(), Some(u64::min_value as i64)); - assert_eq!(u64::min_value.to_uint(), Some(u64::min_value as uint)); - assert_eq!(u64::min_value.to_u8(), Some(u64::min_value as u8)); - assert_eq!(u64::min_value.to_u16(), Some(u64::min_value as u16)); - assert_eq!(u64::min_value.to_u32(), Some(u64::min_value as u32)); - assert_eq!(u64::min_value.to_u64(), Some(u64::min_value as u64)); - } - - #[test] - fn test_cast_range_uint_max() { - assert_eq!(uint::max_value.to_int(), None); - assert_eq!(uint::max_value.to_i8(), None); - assert_eq!(uint::max_value.to_i16(), None); - assert_eq!(uint::max_value.to_i32(), None); - // uint::max_value.to_i64() is word-size specific - assert_eq!(uint::max_value.to_u8(), None); - assert_eq!(uint::max_value.to_u16(), None); - // uint::max_value.to_u32() is word-size specific - assert_eq!(uint::max_value.to_u64(), Some(uint::max_value as u64)); - - #[cfg(target_word_size = "32")] - fn check_word_size() { - assert_eq!(uint::max_value.to_u32(), Some(uint::max_value as u32)); - assert_eq!(uint::max_value.to_i64(), Some(uint::max_value as i64)); - } - - #[cfg(target_word_size = "64")] - fn check_word_size() { - assert_eq!(uint::max_value.to_u32(), None); - assert_eq!(uint::max_value.to_i64(), None); - } - - check_word_size(); - } - - #[test] - fn test_cast_range_u8_max() { - assert_eq!(u8::max_value.to_int(), Some(u8::max_value as int)); - assert_eq!(u8::max_value.to_i8(), None); - assert_eq!(u8::max_value.to_i16(), Some(u8::max_value as i16)); - assert_eq!(u8::max_value.to_i32(), Some(u8::max_value as i32)); - assert_eq!(u8::max_value.to_i64(), Some(u8::max_value as i64)); - assert_eq!(u8::max_value.to_uint(), Some(u8::max_value as uint)); - assert_eq!(u8::max_value.to_u8(), Some(u8::max_value as u8)); - assert_eq!(u8::max_value.to_u16(), Some(u8::max_value as u16)); - assert_eq!(u8::max_value.to_u32(), Some(u8::max_value as u32)); - assert_eq!(u8::max_value.to_u64(), Some(u8::max_value as u64)); - } - - #[test] - fn test_cast_range_u16_max() { - assert_eq!(u16::max_value.to_int(), Some(u16::max_value as int)); - assert_eq!(u16::max_value.to_i8(), None); - assert_eq!(u16::max_value.to_i16(), None); - assert_eq!(u16::max_value.to_i32(), Some(u16::max_value as i32)); - assert_eq!(u16::max_value.to_i64(), Some(u16::max_value as i64)); - assert_eq!(u16::max_value.to_uint(), Some(u16::max_value as uint)); - assert_eq!(u16::max_value.to_u8(), None); - assert_eq!(u16::max_value.to_u16(), Some(u16::max_value as u16)); - assert_eq!(u16::max_value.to_u32(), Some(u16::max_value as u32)); - assert_eq!(u16::max_value.to_u64(), Some(u16::max_value as u64)); - } - - #[test] - fn test_cast_range_u32_max() { - // u32::max_value.to_int() is word-size specific - assert_eq!(u32::max_value.to_i8(), None); - assert_eq!(u32::max_value.to_i16(), None); - assert_eq!(u32::max_value.to_i32(), None); - assert_eq!(u32::max_value.to_i64(), Some(u32::max_value as i64)); - assert_eq!(u32::max_value.to_uint(), Some(u32::max_value as uint)); - assert_eq!(u32::max_value.to_u8(), None); - assert_eq!(u32::max_value.to_u16(), None); - assert_eq!(u32::max_value.to_u32(), Some(u32::max_value as u32)); - assert_eq!(u32::max_value.to_u64(), Some(u32::max_value as u64)); - - #[cfg(target_word_size = "32")] - fn check_word_size() { - assert_eq!(u32::max_value.to_int(), None); - } - - #[cfg(target_word_size = "64")] - fn check_word_size() { - assert_eq!(u32::max_value.to_int(), Some(u32::max_value as int)); - } - - check_word_size(); - } - - #[test] - fn test_cast_range_u64_max() { - assert_eq!(u64::max_value.to_int(), None); - assert_eq!(u64::max_value.to_i8(), None); - assert_eq!(u64::max_value.to_i16(), None); - assert_eq!(u64::max_value.to_i32(), None); - assert_eq!(u64::max_value.to_i64(), None); - // u64::max_value.to_uint() is word-size specific - assert_eq!(u64::max_value.to_u8(), None); - assert_eq!(u64::max_value.to_u16(), None); - assert_eq!(u64::max_value.to_u32(), None); - assert_eq!(u64::max_value.to_u64(), Some(u64::max_value as u64)); - - #[cfg(target_word_size = "32")] - fn check_word_size() { - assert_eq!(u64::max_value.to_uint(), None); - } - - #[cfg(target_word_size = "64")] - fn check_word_size() { - assert_eq!(u64::max_value.to_uint(), Some(u64::max_value as uint)); - } - - check_word_size(); - } - - #[test] - fn test_saturating_add_uint() { - use uint::max_value; - assert_eq!(3u.saturating_add(5u), 8u); - assert_eq!(3u.saturating_add(max_value-1), max_value); - assert_eq!(max_value.saturating_add(max_value), max_value); - assert_eq!((max_value-2).saturating_add(1), max_value-1); - } - - #[test] - fn test_saturating_sub_uint() { - use uint::max_value; - assert_eq!(5u.saturating_sub(3u), 2u); - assert_eq!(3u.saturating_sub(5u), 0u); - assert_eq!(0u.saturating_sub(1u), 0u); - assert_eq!((max_value-1).saturating_sub(max_value), 0); - } - - #[test] - fn test_saturating_add_int() { - use int::{min_value,max_value}; - assert_eq!(3i.saturating_add(5i), 8i); - assert_eq!(3i.saturating_add(max_value-1), max_value); - assert_eq!(max_value.saturating_add(max_value), max_value); - assert_eq!((max_value-2).saturating_add(1), max_value-1); - assert_eq!(3i.saturating_add(-5i), -2i); - assert_eq!(min_value.saturating_add(-1i), min_value); - assert_eq!((-2i).saturating_add(-max_value), min_value); - } - - #[test] - fn test_saturating_sub_int() { - use int::{min_value,max_value}; - assert_eq!(3i.saturating_sub(5i), -2i); - assert_eq!(min_value.saturating_sub(1i), min_value); - assert_eq!((-2i).saturating_sub(max_value), min_value); - assert_eq!(3i.saturating_sub(-5i), 8i); - assert_eq!(3i.saturating_sub(-(max_value-1)), max_value); - assert_eq!(max_value.saturating_sub(-max_value), max_value); - assert_eq!((max_value-2).saturating_sub(-1), max_value-1); - } - - #[test] - fn test_checked_add() { - let five_less = uint::max_value - 5; - assert_eq!(five_less.checked_add(&0), Some(uint::max_value - 5)); - assert_eq!(five_less.checked_add(&1), Some(uint::max_value - 4)); - assert_eq!(five_less.checked_add(&2), Some(uint::max_value - 3)); - assert_eq!(five_less.checked_add(&3), Some(uint::max_value - 2)); - assert_eq!(five_less.checked_add(&4), Some(uint::max_value - 1)); - assert_eq!(five_less.checked_add(&5), Some(uint::max_value)); - assert_eq!(five_less.checked_add(&6), None); - assert_eq!(five_less.checked_add(&7), None); - } - - #[test] - fn test_checked_sub() { - assert_eq!(5u.checked_sub(&0), Some(5)); - assert_eq!(5u.checked_sub(&1), Some(4)); - assert_eq!(5u.checked_sub(&2), Some(3)); - assert_eq!(5u.checked_sub(&3), Some(2)); - assert_eq!(5u.checked_sub(&4), Some(1)); - assert_eq!(5u.checked_sub(&5), Some(0)); - assert_eq!(5u.checked_sub(&6), None); - assert_eq!(5u.checked_sub(&7), None); - } - - #[test] - fn test_checked_mul() { - let third = uint::max_value / 3; - assert_eq!(third.checked_mul(&0), Some(0)); - assert_eq!(third.checked_mul(&1), Some(third)); - assert_eq!(third.checked_mul(&2), Some(third * 2)); - assert_eq!(third.checked_mul(&3), Some(third * 3)); - assert_eq!(third.checked_mul(&4), None); - } - - - #[deriving(Eq)] - struct Value { x: int } - - impl ToPrimitive for Value { - fn to_i64(&self) -> Option { self.x.to_i64() } - fn to_u64(&self) -> Option { self.x.to_u64() } - } - - impl FromPrimitive for Value { - fn from_i64(n: i64) -> Option { Some(Value { x: n as int }) } - fn from_u64(n: u64) -> Option { Some(Value { x: n as int }) } - } - - #[test] - fn test_to_primitive() { - let value = Value { x: 5 }; - assert_eq!(value.to_int(), Some(5)); - assert_eq!(value.to_i8(), Some(5)); - assert_eq!(value.to_i16(), Some(5)); - assert_eq!(value.to_i32(), Some(5)); - assert_eq!(value.to_i64(), Some(5)); - assert_eq!(value.to_uint(), Some(5)); - assert_eq!(value.to_u8(), Some(5)); - assert_eq!(value.to_u16(), Some(5)); - assert_eq!(value.to_u32(), Some(5)); - assert_eq!(value.to_u64(), Some(5)); - assert_eq!(value.to_f32(), Some(5f32)); - assert_eq!(value.to_f64(), Some(5f64)); - } - - #[test] - fn test_from_primitive() { - assert_eq!(from_int(5), Some(Value { x: 5 })); - assert_eq!(from_i8(5), Some(Value { x: 5 })); - assert_eq!(from_i16(5), Some(Value { x: 5 })); - assert_eq!(from_i32(5), Some(Value { x: 5 })); - assert_eq!(from_i64(5), Some(Value { x: 5 })); - assert_eq!(from_uint(5), Some(Value { x: 5 })); - assert_eq!(from_u8(5), Some(Value { x: 5 })); - assert_eq!(from_u16(5), Some(Value { x: 5 })); - assert_eq!(from_u32(5), Some(Value { x: 5 })); - assert_eq!(from_u64(5), Some(Value { x: 5 })); - assert_eq!(from_f32(5f32), Some(Value { x: 5 })); - assert_eq!(from_f64(5f64), Some(Value { x: 5 })); - } -} diff --git a/src/libstd/std.rs b/src/libstd/std.rs deleted file mode 100644 index 4500bae4c90..00000000000 --- a/src/libstd/std.rs +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright 2012-2013 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! # The Rust standard library -//! -//! The Rust standard library is a group of interrelated modules defining -//! the core language traits, operations on built-in data types, collections, -//! platform abstractions, the task scheduler, runtime support for language -//! features and other common functionality. -//! -//! `std` includes modules corresponding to each of the integer types, -//! each of the floating point types, the `bool` type, tuples, characters, -//! strings (`str`), vectors (`vec`), managed boxes (`managed`), owned -//! boxes (`owned`), and unsafe and borrowed pointers (`ptr`, `borrowed`). -//! Additionally, `std` provides pervasive types (`option` and `result`), -//! task creation and communication primitives (`task`, `comm`), platform -//! abstractions (`os` and `path`), basic I/O abstractions (`io`), common -//! traits (`kinds`, `ops`, `cmp`, `num`, `to_str`), and complete bindings -//! to the C standard library (`libc`). -//! -//! # Standard library injection and the Rust prelude -//! -//! `std` is imported at the topmost level of every crate by default, as -//! if the first line of each crate was -//! -//! extern mod std; -//! -//! This means that the contents of std can be accessed from any context -//! with the `std::` path prefix, as in `use std::vec`, `use std::task::spawn`, -//! etc. -//! -//! Additionally, `std` contains a `prelude` module that reexports many of the -//! most common types, traits and functions. The contents of the prelude are -//! imported into every *module* by default. Implicitly, all modules behave as if -//! they contained the following prologue: -//! -//! use std::prelude::*; - -#[link(name = "std", - vers = "0.9-pre", - uuid = "c70c24a7-5551-4f73-8e37-380b11d80be8", - url = "https://github.com/mozilla/rust/tree/master/src/libstd")]; - -#[comment = "The Rust standard library"]; -#[license = "MIT/ASL2"]; -#[crate_type = "lib"]; - -#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk.png", - html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://static.rust-lang.org/doc/master")]; - -#[feature(macro_rules, globs, asm, managed_boxes)]; - -// Don't link to std. We are std. -#[no_std]; - -#[deny(non_camel_case_types)]; -#[deny(missing_doc)]; - -// When testing libstd, bring in libuv as the I/O backend so tests can print -// things and all of the std::rt::io tests have an I/O interface to run on top -// of -#[cfg(test)] extern mod rustuv(vers = "0.9-pre"); - -// Make extra accessible for benchmarking -#[cfg(test)] extern mod extra(vers = "0.9-pre"); - -// Make std testable by not duplicating lang items. See #2912 -#[cfg(test)] extern mod realstd(name = "std"); -#[cfg(test)] pub use kinds = realstd::kinds; -#[cfg(test)] pub use ops = realstd::ops; -#[cfg(test)] pub use cmp = realstd::cmp; - -// On Linux, link to the runtime with -lrt. -#[cfg(target_os = "linux")] -#[doc(hidden)] -pub mod linkhack { - #[link_args="-lrustrt -lrt"] - #[link_args = "-lpthread"] - extern { - } -} - -/* The Prelude. */ - -pub mod prelude; - - -/* Primitive types */ - -#[path = "num/int_macros.rs"] mod int_macros; -#[path = "num/uint_macros.rs"] mod uint_macros; - -#[path = "num/int.rs"] pub mod int; -#[path = "num/i8.rs"] pub mod i8; -#[path = "num/i16.rs"] pub mod i16; -#[path = "num/i32.rs"] pub mod i32; -#[path = "num/i64.rs"] pub mod i64; - -#[path = "num/uint.rs"] pub mod uint; -#[path = "num/u8.rs"] pub mod u8; -#[path = "num/u16.rs"] pub mod u16; -#[path = "num/u32.rs"] pub mod u32; -#[path = "num/u64.rs"] pub mod u64; - -#[path = "num/f32.rs"] pub mod f32; -#[path = "num/f64.rs"] pub mod f64; - -pub mod unit; -pub mod bool; -pub mod char; -pub mod tuple; - -pub mod vec; -pub mod at_vec; -pub mod str; - -#[path = "str/ascii.rs"] -pub mod ascii; -pub mod send_str; - -pub mod ptr; -pub mod owned; -pub mod managed; -pub mod borrow; -pub mod rc; - - -/* Core language traits */ - -#[cfg(not(test))] pub mod kinds; -#[cfg(not(test))] pub mod ops; -#[cfg(not(test))] pub mod cmp; - - -/* Common traits */ - -pub mod from_str; -#[path = "num/num.rs"] -pub mod num; -pub mod iter; -pub mod to_str; -pub mod to_bytes; -pub mod clone; -pub mod hash; -pub mod container; -pub mod default; -pub mod any; - - -/* Common data structures */ - -pub mod option; -pub mod result; -pub mod either; -pub mod hashmap; -pub mod cell; -pub mod trie; - - -/* Tasks and communication */ - -pub mod task; -pub mod comm; -pub mod select; -pub mod local_data; - - -/* Runtime and platform support */ - -pub mod libc; -pub mod c_str; -pub mod os; -pub mod path; -pub mod rand; -pub mod run; -pub mod cast; -pub mod fmt; -pub mod repr; -pub mod cleanup; -pub mod reflect; -pub mod condition; -pub mod logging; -pub mod util; -pub mod routine; -pub mod mem; - - -/* Unsupported interfaces */ - -// Private APIs -pub mod unstable; - - -/* For internal use, not exported */ - -mod unicode; -#[path = "num/cmath.rs"] -mod cmath; - -// FIXME #7809: This shouldn't be pub, and it should be reexported under 'unstable' -// but name resolution doesn't work without it being pub. -pub mod rt; - -// A curious inner-module that's not exported that contains the binding -// 'std' so that macro-expanded references to std::error and such -// can be resolved within libstd. -#[doc(hidden)] -mod std { - pub use clone; - pub use cmp; - pub use condition; - pub use fmt; - pub use kinds; - pub use local_data; - pub use logging; - pub use logging; - pub use option; - pub use os; - pub use rt; - pub use str; - pub use to_bytes; - pub use to_str; - pub use unstable; -} diff --git a/src/libstd/str/ascii.rs b/src/libstd/str/ascii.rs deleted file mode 100644 index ec2d7566177..00000000000 --- a/src/libstd/str/ascii.rs +++ /dev/null @@ -1,582 +0,0 @@ -// Copyright 2013 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Operations on ASCII strings and characters. - -use to_str::{ToStr,ToStrConsume}; -use str; -use str::StrSlice; -use str::OwnedStr; -use container::Container; -use cast; -use iter::Iterator; -use vec::{CopyableVector, ImmutableVector, MutableVector}; -use to_bytes::IterBytes; -use option::{Some, None}; - -/// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero. -#[deriving(Clone, Eq, Ord, TotalOrd, TotalEq)] -pub struct Ascii { priv chr: u8 } - -impl Ascii { - /// Converts a ascii character into a `u8`. - #[inline] - pub fn to_byte(self) -> u8 { - self.chr - } - - /// Converts a ascii character into a `char`. - #[inline] - pub fn to_char(self) -> char { - self.chr as char - } - - /// Convert to lowercase. - #[inline] - pub fn to_lower(self) -> Ascii { - Ascii{chr: ASCII_LOWER_MAP[self.chr]} - } - - /// Convert to uppercase. - #[inline] - pub fn to_upper(self) -> Ascii { - Ascii{chr: ASCII_UPPER_MAP[self.chr]} - } - - /// Compares two ascii characters of equality, ignoring case. - #[inline] - pub fn eq_ignore_case(self, other: Ascii) -> bool { - ASCII_LOWER_MAP[self.chr] == ASCII_LOWER_MAP[other.chr] - } -} - -impl ToStr for Ascii { - #[inline] - fn to_str(&self) -> ~str { - // self.chr is always a valid utf8 byte, no need for the check - unsafe { str::raw::from_byte(self.chr) } - } -} - -/// Trait for converting into an ascii type. -pub trait AsciiCast { - /// Convert to an ascii type - fn to_ascii(&self) -> T; - - /// Convert to an ascii type, not doing any range asserts - unsafe fn to_ascii_nocheck(&self) -> T; - - /// Check if convertible to ascii - fn is_ascii(&self) -> bool; -} - -impl<'self> AsciiCast<&'self[Ascii]> for &'self [u8] { - #[inline] - fn to_ascii(&self) -> &'self[Ascii] { - assert!(self.is_ascii()); - unsafe {self.to_ascii_nocheck()} - } - - #[inline] - unsafe fn to_ascii_nocheck(&self) -> &'self[Ascii] { - cast::transmute(*self) - } - - #[inline] - fn is_ascii(&self) -> bool { - for b in self.iter() { - if !b.is_ascii() { return false; } - } - true - } -} - -impl<'self> AsciiCast<&'self [Ascii]> for &'self str { - #[inline] - fn to_ascii(&self) -> &'self [Ascii] { - assert!(self.is_ascii()); - unsafe { self.to_ascii_nocheck() } - } - - #[inline] - unsafe fn to_ascii_nocheck(&self) -> &'self [Ascii] { - cast::transmute(*self) - } - - #[inline] - fn is_ascii(&self) -> bool { - self.byte_iter().all(|b| b.is_ascii()) - } -} - -impl AsciiCast for u8 { - #[inline] - fn to_ascii(&self) -> Ascii { - assert!(self.is_ascii()); - unsafe {self.to_ascii_nocheck()} - } - - #[inline] - unsafe fn to_ascii_nocheck(&self) -> Ascii { - Ascii{ chr: *self } - } - - #[inline] - fn is_ascii(&self) -> bool { - *self & 128 == 0u8 - } -} - -impl AsciiCast for char { - #[inline] - fn to_ascii(&self) -> Ascii { - assert!(self.is_ascii()); - unsafe {self.to_ascii_nocheck()} - } - - #[inline] - unsafe fn to_ascii_nocheck(&self) -> Ascii { - Ascii{ chr: *self as u8 } - } - - #[inline] - fn is_ascii(&self) -> bool { - *self as u32 - ('\x7F' as u32 & *self as u32) == 0 - } -} - -/// Trait for copyless casting to an ascii vector. -pub trait OwnedAsciiCast { - /// Take ownership and cast to an ascii vector without trailing zero element. - fn into_ascii(self) -> ~[Ascii]; - - /// Take ownership and cast to an ascii vector without trailing zero element. - /// Does not perform validation checks. - unsafe fn into_ascii_nocheck(self) -> ~[Ascii]; -} - -impl OwnedAsciiCast for ~[u8] { - #[inline] - fn into_ascii(self) -> ~[Ascii] { - assert!(self.is_ascii()); - unsafe {self.into_ascii_nocheck()} - } - - #[inline] - unsafe fn into_ascii_nocheck(self) -> ~[Ascii] { - cast::transmute(self) - } -} - -impl OwnedAsciiCast for ~str { - #[inline] - fn into_ascii(self) -> ~[Ascii] { - assert!(self.is_ascii()); - unsafe {self.into_ascii_nocheck()} - } - - #[inline] - unsafe fn into_ascii_nocheck(self) -> ~[Ascii] { - cast::transmute(self) - } -} - -/// Trait for converting an ascii type to a string. Needed to convert `&[Ascii]` to `~str` -pub trait AsciiStr { - /// Convert to a string. - fn to_str_ascii(&self) -> ~str; - - /// Convert to vector representing a lower cased ascii string. - fn to_lower(&self) -> ~[Ascii]; - - /// Convert to vector representing a upper cased ascii string. - fn to_upper(&self) -> ~[Ascii]; - - /// Compares two Ascii strings ignoring case - fn eq_ignore_case(self, other: &[Ascii]) -> bool; -} - -impl<'self> AsciiStr for &'self [Ascii] { - #[inline] - fn to_str_ascii(&self) -> ~str { - let cpy = self.to_owned(); - unsafe { cast::transmute(cpy) } - } - - #[inline] - fn to_lower(&self) -> ~[Ascii] { - self.map(|a| a.to_lower()) - } - - #[inline] - fn to_upper(&self) -> ~[Ascii] { - self.map(|a| a.to_upper()) - } - - #[inline] - fn eq_ignore_case(self, other: &[Ascii]) -> bool { - do self.iter().zip(other.iter()).all |(&a, &b)| { a.eq_ignore_case(b) } - } -} - -impl ToStrConsume for ~[Ascii] { - #[inline] - fn into_str(self) -> ~str { - unsafe { cast::transmute(self) } - } -} - -impl IterBytes for Ascii { - #[inline] - fn iter_bytes(&self, _lsb0: bool, f: &fn(buf: &[u8]) -> bool) -> bool { - f([self.to_byte()]) - } -} - -/// Trait to convert to a owned byte array by consuming self -pub trait ToBytesConsume { - /// Converts to a owned byte array by consuming self - fn into_bytes(self) -> ~[u8]; -} - -impl ToBytesConsume for ~[Ascii] { - fn into_bytes(self) -> ~[u8] { - unsafe { cast::transmute(self) } - } -} - -/// Extension methods for ASCII-subset only operations on owned strings -pub trait OwnedStrAsciiExt { - /// Convert the string to ASCII upper case: - /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', - /// but non-ASCII letters are unchanged. - fn into_ascii_upper(self) -> ~str; - - /// Convert the string to ASCII lower case: - /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', - /// but non-ASCII letters are unchanged. - fn into_ascii_lower(self) -> ~str; -} - -/// Extension methods for ASCII-subset only operations on string slices -pub trait StrAsciiExt { - /// Makes a copy of the string in ASCII upper case: - /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', - /// but non-ASCII letters are unchanged. - fn to_ascii_upper(&self) -> ~str; - - /// Makes a copy of the string in ASCII lower case: - /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', - /// but non-ASCII letters are unchanged. - fn to_ascii_lower(&self) -> ~str; - - /// Check that two strings are an ASCII case-insensitive match. - /// Same as `to_ascii_lower(a) == to_ascii_lower(b)`, - /// but without allocating and copying temporary strings. - fn eq_ignore_ascii_case(&self, other: &str) -> bool; -} - -impl<'self> StrAsciiExt for &'self str { - #[inline] - fn to_ascii_upper(&self) -> ~str { - unsafe { str_copy_map_bytes(*self, ASCII_UPPER_MAP) } - } - - #[inline] - fn to_ascii_lower(&self) -> ~str { - unsafe { str_copy_map_bytes(*self, ASCII_LOWER_MAP) } - } - - #[inline] - fn eq_ignore_ascii_case(&self, other: &str) -> bool { - self.len() == other.len() && self.as_bytes().iter().zip(other.as_bytes().iter()).all( - |(byte_self, byte_other)| ASCII_LOWER_MAP[*byte_self] == ASCII_LOWER_MAP[*byte_other]) - } -} - -impl OwnedStrAsciiExt for ~str { - #[inline] - fn into_ascii_upper(self) -> ~str { - unsafe { str_map_bytes(self, ASCII_UPPER_MAP) } - } - - #[inline] - fn into_ascii_lower(self) -> ~str { - unsafe { str_map_bytes(self, ASCII_LOWER_MAP) } - } -} - -#[inline] -unsafe fn str_map_bytes(string: ~str, map: &'static [u8]) -> ~str { - let mut bytes = string.into_bytes(); - - for b in bytes.mut_iter() { - *b = map[*b]; - } - - str::raw::from_utf8_owned(bytes) -} - -#[inline] -unsafe fn str_copy_map_bytes(string: &str, map: &'static [u8]) -> ~str { - let bytes = string.byte_iter().map(|b| map[b]).to_owned_vec(); - - str::raw::from_utf8_owned(bytes) -} - -static ASCII_LOWER_MAP: &'static [u8] = &[ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, - 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, - 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, -]; - -static ASCII_UPPER_MAP: &'static [u8] = &[ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, - 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, - 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, -]; - - -#[cfg(test)] -mod tests { - use super::*; - use str::from_char; - use char::from_u32; - - macro_rules! v2ascii ( - ( [$($e:expr),*]) => ( [$(Ascii{chr:$e}),*]); - (~[$($e:expr),*]) => (~[$(Ascii{chr:$e}),*]); - ) - - #[test] - fn test_ascii() { - assert_eq!(65u8.to_ascii().to_byte(), 65u8); - assert_eq!(65u8.to_ascii().to_char(), 'A'); - assert_eq!('A'.to_ascii().to_char(), 'A'); - assert_eq!('A'.to_ascii().to_byte(), 65u8); - - assert_eq!('A'.to_ascii().to_lower().to_char(), 'a'); - assert_eq!('Z'.to_ascii().to_lower().to_char(), 'z'); - assert_eq!('a'.to_ascii().to_upper().to_char(), 'A'); - assert_eq!('z'.to_ascii().to_upper().to_char(), 'Z'); - - assert_eq!('@'.to_ascii().to_lower().to_char(), '@'); - assert_eq!('['.to_ascii().to_lower().to_char(), '['); - assert_eq!('`'.to_ascii().to_upper().to_char(), '`'); - assert_eq!('{'.to_ascii().to_upper().to_char(), '{'); - - assert!("banana".iter().all(|c| c.is_ascii())); - assert!(!"ประเทศไทย中华Việt Nam".iter().all(|c| c.is_ascii())); - } - - #[test] - fn test_ascii_vec() { - assert_eq!((&[40u8, 32u8, 59u8]).to_ascii(), v2ascii!([40, 32, 59])); - assert_eq!("( ;".to_ascii(), v2ascii!([40, 32, 59])); - // FIXME: #5475 borrowchk error, owned vectors do not live long enough - // if chained-from directly - let v = ~[40u8, 32u8, 59u8]; assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59])); - let v = ~"( ;"; assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59])); - - assert_eq!("abCDef&?#".to_ascii().to_lower().to_str_ascii(), ~"abcdef&?#"); - assert_eq!("abCDef&?#".to_ascii().to_upper().to_str_ascii(), ~"ABCDEF&?#"); - - assert_eq!("".to_ascii().to_lower().to_str_ascii(), ~""); - assert_eq!("YMCA".to_ascii().to_lower().to_str_ascii(), ~"ymca"); - assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().to_str_ascii(), ~"ABCDEFXYZ:.;"); - - assert!("aBcDeF&?#".to_ascii().eq_ignore_case("AbCdEf&?#".to_ascii())); - - assert!("".is_ascii()); - assert!("a".is_ascii()); - assert!(!"\u2009".is_ascii()); - - } - - #[test] - fn test_owned_ascii_vec() { - assert_eq!((~"( ;").into_ascii(), v2ascii!(~[40, 32, 59])); - assert_eq!((~[40u8, 32u8, 59u8]).into_ascii(), v2ascii!(~[40, 32, 59])); - } - - #[test] - fn test_ascii_to_str() { assert_eq!(v2ascii!([40, 32, 59]).to_str_ascii(), ~"( ;"); } - - #[test] - fn test_ascii_into_str() { - assert_eq!(v2ascii!(~[40, 32, 59]).into_str(), ~"( ;"); - } - - #[test] - fn test_ascii_to_bytes() { - assert_eq!(v2ascii!(~[40, 32, 59]).into_bytes(), ~[40u8, 32u8, 59u8]); - } - - #[test] #[should_fail] - fn test_ascii_vec_fail_u8_slice() { (&[127u8, 128u8, 255u8]).to_ascii(); } - - #[test] #[should_fail] - fn test_ascii_vec_fail_str_slice() { "zoä华".to_ascii(); } - - #[test] #[should_fail] - fn test_ascii_fail_u8_slice() { 255u8.to_ascii(); } - - #[test] #[should_fail] - fn test_ascii_fail_char_slice() { 'λ'.to_ascii(); } - - #[test] - fn test_to_ascii_upper() { - assert_eq!("url()URL()uRl()ürl".to_ascii_upper(), ~"URL()URL()URL()üRL"); - assert_eq!("hıKß".to_ascii_upper(), ~"HıKß"); - - let mut i = 0; - while i <= 500 { - let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 } - else { i }; - assert_eq!(from_char(from_u32(i).unwrap()).to_ascii_upper(), - from_char(from_u32(upper).unwrap())) - i += 1; - } - } - - #[test] - fn test_to_ascii_lower() { - assert_eq!("url()URL()uRl()Ürl".to_ascii_lower(), ~"url()url()url()Ürl"); - // Dotted capital I, Kelvin sign, Sharp S. - assert_eq!("HİKß".to_ascii_lower(), ~"hİKß"); - - let mut i = 0; - while i <= 500 { - let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } - else { i }; - assert_eq!(from_char(from_u32(i).unwrap()).to_ascii_lower(), - from_char(from_u32(lower).unwrap())) - i += 1; - } - } - - #[test] - fn test_into_ascii_upper() { - assert_eq!((~"url()URL()uRl()ürl").into_ascii_upper(), ~"URL()URL()URL()üRL"); - assert_eq!((~"hıKß").into_ascii_upper(), ~"HıKß"); - - let mut i = 0; - while i <= 500 { - let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 } - else { i }; - assert_eq!(from_char(from_u32(i).unwrap()).into_ascii_upper(), - from_char(from_u32(upper).unwrap())) - i += 1; - } - } - - #[test] - fn test_into_ascii_lower() { - assert_eq!((~"url()URL()uRl()Ürl").into_ascii_lower(), ~"url()url()url()Ürl"); - // Dotted capital I, Kelvin sign, Sharp S. - assert_eq!((~"HİKß").into_ascii_lower(), ~"hİKß"); - - let mut i = 0; - while i <= 500 { - let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } - else { i }; - assert_eq!(from_char(from_u32(i).unwrap()).into_ascii_lower(), - from_char(from_u32(lower).unwrap())) - i += 1; - } - } - - #[test] - fn test_eq_ignore_ascii_case() { - assert!("url()URL()uRl()Ürl".eq_ignore_ascii_case("url()url()url()Ürl")); - assert!(!"Ürl".eq_ignore_ascii_case("ürl")); - // Dotted capital I, Kelvin sign, Sharp S. - assert!("HİKß".eq_ignore_ascii_case("hİKß")); - assert!(!"İ".eq_ignore_ascii_case("i")); - assert!(!"K".eq_ignore_ascii_case("k")); - assert!(!"ß".eq_ignore_ascii_case("s")); - - let mut i = 0; - while i <= 500 { - let c = i; - let lower = if 'A' as u32 <= c && c <= 'Z' as u32 { c + 'a' as u32 - 'A' as u32 } - else { c }; - assert!(from_char(from_u32(i).unwrap()). - eq_ignore_ascii_case(from_char(from_u32(lower).unwrap()))); - i += 1; - } - } - - #[test] - fn test_to_str() { - let s = Ascii{ chr: 't' as u8 }.to_str(); - assert_eq!(s, ~"t"); - } - - -} -- cgit 1.4.1-3-g733a5