std: Remove deprecated/unstable num functionality

This commit removes all the old casting/generic traits from `std::num` that are
no longer in use by the standard library. This additionally removes the old
`strconv` module which has not seen much use in quite a long time. All generic
functionality has been supplanted with traits in the `num` crate and the
`strconv` module is supplanted with the [rust-strconv crate][rust-strconv].

[rust-strconv]: https://github.com/lifthrasiir/rust-strconv

This is a breaking change due to the removal of these deprecated crates, and the
alternative crates are listed above.

[breaking-change]
This commit is contained in:
Alex Crichton 2015-04-17 15:32:42 -07:00
parent e091ba3f3e
commit eeb94886ad
54 changed files with 618 additions and 5594 deletions

View File

@ -1058,14 +1058,6 @@ impl<'a> IntoCow<'a, str> for &'a str {
}
}
#[allow(deprecated)]
impl<'a> Str for Cow<'a, str> {
#[inline]
fn as_slice<'b>(&'b self) -> &'b str {
&**self
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Write for String {
#[inline]

View File

@ -11,15 +11,15 @@
pub use self::ExponentFormat::*;
pub use self::SignificantDigits::*;
use char::{self, CharExt};
use prelude::*;
use char;
use fmt;
use iter::Iterator;
use num::{cast, Float, ToPrimitive};
use num::Float;
use num::FpCategory as Fp;
use ops::FnOnce;
use result::Result::Ok;
use slice::{self, SliceExt};
use str::{self, StrExt};
use ops::{Div, Rem, Mul};
use slice;
use str;
/// A flag that specifies whether to use exponential (scientific) notation.
pub enum ExponentFormat {
@ -42,6 +42,21 @@ pub enum SignificantDigits {
DigExact(usize)
}
#[doc(hidden)]
pub trait MyFloat: Float + PartialEq + PartialOrd + Div<Output=Self> +
Mul<Output=Self> + Rem<Output=Self> + Copy {
fn from_u32(u: u32) -> Self;
fn to_i32(&self) -> i32;
}
macro_rules! doit {
($($t:ident)*) => ($(impl MyFloat for $t {
fn from_u32(u: u32) -> $t { u as $t }
fn to_i32(&self) -> i32 { *self as i32 }
})*)
}
doit! { f32 f64 }
/// Converts a float number to its string representation.
/// This is meant to be a common base implementation for various formatting styles.
/// The number is assumed to be non-negative, callers use `Formatter::pad_integral`
@ -63,7 +78,7 @@ pub enum SignificantDigits {
/// # Panics
///
/// - Panics if `num` is negative.
pub fn float_to_str_bytes_common<T: Float, U, F>(
pub fn float_to_str_bytes_common<T: MyFloat, U, F>(
num: T,
digits: SignificantDigits,
exp_format: ExponentFormat,
@ -72,10 +87,10 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
) -> U where
F: FnOnce(&str) -> U,
{
let _0: T = Float::zero();
let _1: T = Float::one();
let _0: T = T::zero();
let _1: T = T::one();
let radix: u32 = 10;
let radix_f: T = cast(radix).unwrap();
let radix_f = T::from_u32(radix);
assert!(num.is_nan() || num >= _0, "float_to_str_bytes_common: number is negative");
@ -99,7 +114,7 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
let (num, exp) = match exp_format {
ExpDec if num != _0 => {
let exp = num.log10().floor();
(num / radix_f.powf(exp), cast::<T, i32>(exp).unwrap())
(num / radix_f.powf(exp), exp.to_i32())
}
_ => (num, 0)
};
@ -114,7 +129,7 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
deccum = deccum / radix_f;
deccum = deccum.trunc();
let c = char::from_digit(current_digit.to_isize().unwrap() as u32, radix);
let c = char::from_digit(current_digit.to_i32() as u32, radix);
buf[end] = c.unwrap() as u8;
end += 1;
@ -158,7 +173,7 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
let current_digit = deccum.trunc();
let c = char::from_digit(current_digit.to_isize().unwrap() as u32, radix);
let c = char::from_digit(current_digit.to_i32() as u32, radix);
buf[end] = c.unwrap() as u8;
end += 1;

View File

@ -12,21 +12,16 @@
#![stable(feature = "rust1", since = "1.0.0")]
use prelude::*;
use cell::{Cell, RefCell, Ref, RefMut, BorrowState};
use char::CharExt;
use clone::Clone;
use iter::Iterator;
use marker::{Copy, PhantomData, Sized};
use marker::PhantomData;
use mem;
use num::Float;
use option::Option;
use option::Option::{Some, None};
use result::Result::Ok;
use ops::{Deref, FnOnce};
use ops::Deref;
use result;
use slice::SliceExt;
use num::Float;
use slice;
use str::{self, StrExt};
use str;
use self::rt::v1::Alignment;
pub use self::num::radix;
@ -912,7 +907,8 @@ impl<'a, T> Pointer for &'a mut T {
}
// Common code of floating point Debug and Display.
fn float_to_str_common<T: Float, F>(num: &T, precision: Option<usize>, post: F) -> Result
fn float_to_str_common<T: float::MyFloat, F>(num: &T, precision: Option<usize>,
post: F) -> Result
where F : FnOnce(&str) -> Result {
let digits = match precision {
Some(i) => float::DigExact(i),
@ -950,8 +946,6 @@ macro_rules! floating { ($ty:ident) => {
#[stable(feature = "rust1", since = "1.0.0")]
impl LowerExp for $ty {
fn fmt(&self, fmt: &mut Formatter) -> Result {
use num::Float;
let digits = match fmt.precision {
Some(i) => float::DigExact(i),
None => float::DigMax(6),
@ -969,8 +963,6 @@ macro_rules! floating { ($ty:ident) => {
#[stable(feature = "rust1", since = "1.0.0")]
impl UpperExp for $ty {
fn fmt(&self, fmt: &mut Formatter) -> Result {
use num::Float;
let digits = match fmt.precision {
Some(i) => float::DigExact(i),
None => float::DigMax(6),

View File

@ -14,12 +14,28 @@
#![allow(unsigned_negation)]
use prelude::*;
use fmt;
use iter::Iterator;
use num::{Int, cast};
use slice::SliceExt;
use num::Zero;
use ops::{Div, Rem, Sub};
use str;
#[doc(hidden)]
trait Int: Zero + PartialEq + PartialOrd + Div<Output=Self> + Rem<Output=Self> +
Sub<Output=Self> + Copy {
fn from_u8(u: u8) -> Self;
fn to_u8(&self) -> u8;
}
macro_rules! doit {
($($t:ident)*) => ($(impl Int for $t {
fn from_u8(u: u8) -> $t { u as $t }
fn to_u8(&self) -> u8 { *self as u8 }
})*)
}
doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
/// A type that represents a specific radix
#[doc(hidden)]
trait GenericRadix {
@ -33,33 +49,32 @@ trait GenericRadix {
fn digit(&self, x: u8) -> u8;
/// Format an integer using the radix using a formatter.
#[allow(deprecated)] // Int
fn fmt_int<T: Int>(&self, mut x: T, f: &mut fmt::Formatter) -> fmt::Result {
// The radix can be as low as 2, so we need a buffer of at least 64
// characters for a base 2 number.
let zero = Int::zero();
let zero = T::zero();
let is_positive = x >= zero;
let mut buf = [0; 64];
let mut curr = buf.len();
let base = cast(self.base()).unwrap();
let base = T::from_u8(self.base());
if is_positive {
// Accumulate each digit of the number from the least significant
// to the most significant figure.
for byte in buf.iter_mut().rev() {
let n = x % base; // Get the current place value.
x = x / base; // Deaccumulate the number.
*byte = self.digit(cast(n).unwrap()); // Store the digit in the buffer.
let n = x % base; // Get the current place value.
x = x / base; // Deaccumulate the number.
*byte = self.digit(n.to_u8()); // Store the digit in the buffer.
curr -= 1;
if x == zero { break }; // No more digits left to accumulate.
if x == zero { break }; // No more digits left to accumulate.
}
} else {
// Do the same as above, but accounting for two's complement.
for byte in buf.iter_mut().rev() {
let n = zero - (x % base); // Get the current place value.
x = x / base; // Deaccumulate the number.
*byte = self.digit(cast(n).unwrap()); // Store the digit in the buffer.
let n = zero - (x % base); // Get the current place value.
x = x / base; // Deaccumulate the number.
*byte = self.digit(n.to_u8()); // Store the digit in the buffer.
curr -= 1;
if x == zero { break }; // No more digits left to accumulate.
if x == zero { break }; // No more digits left to accumulate.
}
}
let buf = unsafe { str::from_utf8_unchecked(&buf[curr..]) };

View File

@ -64,7 +64,7 @@ use cmp::{Ord, PartialOrd, PartialEq};
use default::Default;
use marker;
use mem;
use num::{Int, Zero, One};
use num::{Zero, One};
use ops::{self, Add, Sub, FnMut, Mul, RangeFrom};
use option::Option::{self, Some, None};
use marker::Sized;
@ -2647,80 +2647,6 @@ impl<A: Step + Zero + Clone> Iterator for StepBy<A, ops::Range<A>> {
}
}
/// An iterator over the range [start, stop] by `step`. It handles overflow by stopping.
#[derive(Clone)]
#[unstable(feature = "core",
reason = "likely to be replaced by range notation and adapters")]
pub struct RangeStepInclusive<A> {
state: A,
stop: A,
step: A,
rev: bool,
done: bool,
}
/// Returns an iterator over the range [start, stop] by `step`.
///
/// It handles overflow by stopping.
///
/// # Examples
///
/// ```
/// # #![feature(core)]
/// use std::iter::range_step_inclusive;
///
/// for i in range_step_inclusive(0, 10, 2) {
/// println!("{}", i);
/// }
/// ```
///
/// This prints:
///
/// ```text
/// 0
/// 2
/// 4
/// 6
/// 8
/// 10
/// ```
#[inline]
#[unstable(feature = "core",
reason = "likely to be replaced by range notation and adapters")]
#[allow(deprecated)]
pub fn range_step_inclusive<A: Int>(start: A, stop: A, step: A) -> RangeStepInclusive<A> {
let rev = step < Int::zero();
RangeStepInclusive {
state: start,
stop: stop,
step: step,
rev: rev,
done: false,
}
}
#[unstable(feature = "core",
reason = "likely to be replaced by range notation and adapters")]
#[allow(deprecated)]
impl<A: Int> Iterator for RangeStepInclusive<A> {
type Item = A;
#[inline]
fn next(&mut self) -> Option<A> {
if !self.done && ((self.rev && self.state >= self.stop) ||
(!self.rev && self.state <= self.stop)) {
let result = self.state;
match self.state.checked_add(self.step) {
Some(x) => self.state = x,
None => self.done = true
}
Some(result)
} else {
None
}
}
}
macro_rules! range_exact_iter_impl {
($($t:ty)*) => ($(
#[stable(feature = "rust1", since = "1.0.0")]

View File

@ -35,7 +35,16 @@ use hash::Hasher;
#[stable(feature = "rust1", since = "1.0.0")]
#[lang="send"]
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
#[allow(deprecated)]
#[cfg(not(stage0))]
pub unsafe trait Send {
// empty.
}
/// Types able to be transferred across thread boundaries.
#[stable(feature = "rust1", since = "1.0.0")]
#[lang="send"]
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
#[cfg(stage0)]
pub unsafe trait Send : MarkerTrait {
// empty.
}
@ -51,7 +60,17 @@ impl !Send for Managed { }
#[lang="sized"]
#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
#[allow(deprecated)]
#[cfg(not(stage0))]
pub trait Sized {
// Empty.
}
/// Types with a constant size known at compile-time.
#[stable(feature = "rust1", since = "1.0.0")]
#[lang="sized"]
#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
#[cfg(stage0)]
pub trait Sized : MarkerTrait {
// Empty.
}
@ -199,13 +218,23 @@ pub trait Copy : Clone {
/// the `sync` crate do ensure that any mutation cannot cause data
/// races. Hence these types are `Sync`.
///
/// Any types with interior mutability must also use the `std::cell::UnsafeCell` wrapper around the
/// value(s) which can be mutated when behind a `&` reference; not doing this is undefined
/// behaviour (for example, `transmute`-ing from `&T` to `&mut T` is illegal).
/// Any types with interior mutability must also use the `std::cell::UnsafeCell`
/// wrapper around the value(s) which can be mutated when behind a `&`
/// reference; not doing this is undefined behaviour (for example,
/// `transmute`-ing from `&T` to `&mut T` is illegal).
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
#[lang="sync"]
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
pub unsafe trait Sync {
// Empty
}
/// dox
#[cfg(stage0)]
#[stable(feature = "rust1", since = "1.0.0")]
#[lang="sync"]
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
#[allow(deprecated)]
pub unsafe trait Sync : MarkerTrait {
// Empty
}
@ -272,42 +301,20 @@ macro_rules! impls{
)
}
/// `MarkerTrait` is deprecated and no longer needed.
/// dox
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "No longer needed")]
#[allow(deprecated)]
#[cfg(stage0)]
pub trait MarkerTrait : PhantomFn<Self,Self> { }
/// `MarkerTrait` is deprecated and no longer needed.
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "No longer needed")]
#[allow(deprecated)]
#[cfg(not(stage0))]
pub trait MarkerTrait { }
#[cfg(stage0)]
impl<T: ?Sized> MarkerTrait for T {}
#[allow(deprecated)]
impl<T:?Sized> MarkerTrait for T { }
/// `PhantomFn` is a deprecated marker trait that is no longer needed.
/// dox
#[lang="phantom_fn"]
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "No longer needed")]
#[cfg(stage0)]
pub trait PhantomFn<A:?Sized,R:?Sized=()> {
}
/// `PhantomFn` is a deprecated marker trait that is no longer needed.
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "No longer needed")]
#[cfg(not(stage0))]
pub trait PhantomFn<A:?Sized,R:?Sized=()> {
}
#[allow(deprecated)]
#[cfg(not(stage0))]
impl<A:?Sized,R:?Sized,T:?Sized> PhantomFn<A,R> for T { }
/// `PhantomData<T>` allows you to describe that a type acts as if it stores a value of type `T`,
/// even though it does not. This allows you to inform the compiler about certain safety properties
/// of your code.
@ -454,8 +461,14 @@ mod impls {
#[rustc_reflect_like]
#[unstable(feature = "core", reason = "requires RFC and more experience")]
#[allow(deprecated)]
pub trait Reflect : MarkerTrait {
}
#[cfg(not(stage0))]
pub trait Reflect {}
/// dox
#[rustc_reflect_like]
#[unstable(feature = "core", reason = "requires RFC and more experience")]
#[cfg(stage0)]
pub trait Reflect: MarkerTrait {}
impl Reflect for .. { }

View File

@ -10,12 +10,17 @@
//! Exposes the NonZero lang item which provides optimization hints.
use marker::{Sized, MarkerTrait};
use marker::Sized;
use ops::Deref;
#[cfg(stage0)] use marker::MarkerTrait;
/// Unsafe trait to indicate what types are usable with the NonZero struct
#[allow(deprecated)]
pub unsafe trait Zeroable : MarkerTrait {}
#[cfg(not(stage0))]
pub unsafe trait Zeroable {}
/// Unsafe trait to indicate what types are usable with the NonZero struct
#[cfg(stage0)]
pub unsafe trait Zeroable: MarkerTrait {}
unsafe impl<T:?Sized> Zeroable for *const T {}
unsafe impl<T:?Sized> Zeroable for *mut T {}

View File

@ -20,7 +20,6 @@ use intrinsics;
use mem;
use num::Float;
use num::FpCategory as Fp;
use option::Option;
#[stable(feature = "rust1", since = "1.0.0")]
pub const RADIX: u32 = 2;
@ -33,19 +32,6 @@ pub const DIGITS: u32 = 6;
#[stable(feature = "rust1", since = "1.0.0")]
pub const EPSILON: f32 = 1.19209290e-07_f32;
/// Smallest finite f32 value
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "use `std::f32::MIN`")]
pub const MIN_VALUE: f32 = -3.40282347e+38_f32;
/// Smallest positive, normalized f32 value
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "use `std::f32::MIN_POSITIVE`")]
pub const MIN_POS_VALUE: f32 = 1.17549435e-38_f32;
/// Largest finite f32 value
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "use `std::f32::MAX`")]
pub const MAX_VALUE: f32 = 3.40282347e+38_f32;
/// Smallest finite f32 value
#[stable(feature = "rust1", since = "1.0.0")]
pub const MIN: f32 = -3.40282347e+38_f32;
@ -118,26 +104,14 @@ pub mod consts {
#[stable(feature = "rust1", since = "1.0.0")]
pub const FRAC_2_SQRT_PI: f32 = 1.12837916709551257389615890312154517_f32;
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "renamed to FRAC_2_SQRT_PI")]
pub const FRAC_2_SQRTPI: f32 = 1.12837916709551257389615890312154517_f32;
/// sqrt(2.0)
#[stable(feature = "rust1", since = "1.0.0")]
pub const SQRT_2: f32 = 1.41421356237309504880168872420969808_f32;
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "renamed to SQRT_2")]
pub const SQRT2: f32 = 1.41421356237309504880168872420969808_f32;
/// 1.0/sqrt(2.0)
#[stable(feature = "rust1", since = "1.0.0")]
pub const FRAC_1_SQRT_2: f32 = 0.707106781186547524400844362104849039_f32;
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "renamed to FRAC_1_SQRT_2")]
pub const FRAC_1_SQRT2: f32 = 0.707106781186547524400844362104849039_f32;
/// Euler's number
#[stable(feature = "rust1", since = "1.0.0")]
pub const E: f32 = 2.71828182845904523536028747135266250_f32;
@ -218,56 +192,6 @@ impl Float for f32 {
}
}
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn mantissa_digits(_: Option<f32>) -> usize { MANTISSA_DIGITS as usize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn digits(_: Option<f32>) -> usize { DIGITS as usize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn epsilon() -> f32 { EPSILON }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn min_exp(_: Option<f32>) -> isize { MIN_EXP as isize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn max_exp(_: Option<f32>) -> isize { MAX_EXP as isize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn min_10_exp(_: Option<f32>) -> isize { MIN_10_EXP as isize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn max_10_exp(_: Option<f32>) -> isize { MAX_10_EXP as isize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn min_value() -> f32 { MIN }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn min_pos_value(_: Option<f32>) -> f32 { MIN_POSITIVE }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn max_value() -> f32 { MAX }
/// Returns the mantissa, exponent and sign as integers.
fn integer_decode(self) -> (u64, i16, i8) {
let bits: u32 = unsafe { mem::transmute(self) };

View File

@ -20,7 +20,6 @@ use intrinsics;
use mem;
use num::Float;
use num::FpCategory as Fp;
use option::Option;
#[stable(feature = "rust1", since = "1.0.0")]
pub const RADIX: u32 = 2;
@ -33,19 +32,6 @@ pub const DIGITS: u32 = 15;
#[stable(feature = "rust1", since = "1.0.0")]
pub const EPSILON: f64 = 2.2204460492503131e-16_f64;
/// Smallest finite f64 value
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "use `std::f64::MIN`")]
pub const MIN_VALUE: f64 = -1.7976931348623157e+308_f64;
/// Smallest positive, normalized f64 value
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "use `std::f64::MIN_POSITIVE`")]
pub const MIN_POS_VALUE: f64 = 2.2250738585072014e-308_f64;
/// Largest finite f64 value
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "use `std::f64::MAX`")]
pub const MAX_VALUE: f64 = 1.7976931348623157e+308_f64;
/// Smallest finite f64 value
#[stable(feature = "rust1", since = "1.0.0")]
pub const MIN: f64 = -1.7976931348623157e+308_f64;
@ -118,26 +104,14 @@ pub mod consts {
#[stable(feature = "rust1", since = "1.0.0")]
pub const FRAC_2_SQRT_PI: f64 = 1.12837916709551257389615890312154517_f64;
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "renamed to FRAC_2_SQRT_PI")]
pub const FRAC_2_SQRTPI: f64 = 1.12837916709551257389615890312154517_f64;
/// sqrt(2.0)
#[stable(feature = "rust1", since = "1.0.0")]
pub const SQRT_2: f64 = 1.41421356237309504880168872420969808_f64;
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "renamed to SQRT_2")]
pub const SQRT2: f64 = 1.41421356237309504880168872420969808_f64;
/// 1.0/sqrt(2.0)
#[stable(feature = "rust1", since = "1.0.0")]
pub const FRAC_1_SQRT_2: f64 = 0.707106781186547524400844362104849039_f64;
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "renamed to FRAC_1_SQRT_2")]
pub const FRAC_1_SQRT2: f64 = 0.707106781186547524400844362104849039_f64;
/// Euler's number
#[stable(feature = "rust1", since = "1.0.0")]
pub const E: f64 = 2.71828182845904523536028747135266250_f64;
@ -218,56 +192,6 @@ impl Float for f64 {
}
}
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn mantissa_digits(_: Option<f64>) -> usize { MANTISSA_DIGITS as usize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn digits(_: Option<f64>) -> usize { DIGITS as usize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn epsilon() -> f64 { EPSILON }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn min_exp(_: Option<f64>) -> isize { MIN_EXP as isize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn max_exp(_: Option<f64>) -> isize { MAX_EXP as isize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn min_10_exp(_: Option<f64>) -> isize { MIN_10_EXP as isize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn max_10_exp(_: Option<f64>) -> isize { MAX_10_EXP as isize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn min_value() -> f64 { MIN }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn min_pos_value(_: Option<f64>) -> f64 { MIN_POSITIVE }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn max_value() -> f64 { MAX }
/// Returns the mantissa, exponent and sign as integers.
fn integer_decode(self) -> (u64, i16, i8) {
let bits: u64 = unsafe { mem::transmute(self) };

File diff suppressed because it is too large Load Diff

View File

@ -15,8 +15,6 @@ use super::Wrapping;
use ops::*;
use intrinsics::{overflowing_add, overflowing_sub, overflowing_mul};
use intrinsics::{i8_add_with_overflow, u8_add_with_overflow};
use intrinsics::{i16_add_with_overflow, u16_add_with_overflow};
use intrinsics::{i32_add_with_overflow, u32_add_with_overflow};
@ -32,14 +30,6 @@ use intrinsics::{i64_mul_with_overflow, u64_mul_with_overflow};
use ::{i8,i16,i32,i64};
#[unstable(feature = "core", reason = "may be removed, renamed, or relocated")]
#[deprecated(since = "1.0.0", reason = "moved to inherent methods")]
pub trait WrappingOps {
fn wrapping_add(self, rhs: Self) -> Self;
fn wrapping_sub(self, rhs: Self) -> Self;
fn wrapping_mul(self, rhs: Self) -> Self;
}
#[unstable(feature = "core", reason = "may be removed, renamed, or relocated")]
pub trait OverflowingOps {
fn overflowing_add(self, rhs: Self) -> (Self, bool);
@ -99,27 +89,6 @@ sh_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
macro_rules! wrapping_impl {
($($t:ty)*) => ($(
impl WrappingOps for $t {
#[inline(always)]
fn wrapping_add(self, rhs: $t) -> $t {
unsafe {
overflowing_add(self, rhs)
}
}
#[inline(always)]
fn wrapping_sub(self, rhs: $t) -> $t {
unsafe {
overflowing_sub(self, rhs)
}
}
#[inline(always)]
fn wrapping_mul(self, rhs: $t) -> $t {
unsafe {
overflowing_mul(self, rhs)
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Add for Wrapping<$t> {
type Output = Wrapping<$t>;

View File

@ -51,7 +51,7 @@ use result::Result::{Ok, Err};
use ptr;
use mem;
use mem::size_of;
use marker::{Send, Sized, Sync, self};
use marker::{Send, Sync, self};
use raw::Repr;
// Avoid conflicts with *both* the Slice trait (buggy) and the `slice::raw` module.
use raw::Slice as RawSlice;

View File

@ -25,7 +25,6 @@ use default::Default;
use fmt;
use iter::ExactSizeIterator;
use iter::{Map, Iterator, DoubleEndedIterator};
use marker::Sized;
use mem;
use ops::{Fn, FnMut, FnOnce};
use option::Option::{self, None, Some};

View File

@ -11,8 +11,6 @@
//! The ChaCha random number generator.
use core::prelude::*;
use core::num::Int;
use core::num::wrapping::WrappingOps;
use {Rng, SeedableRng, Rand};
const KEY_WORDS : usize = 8; // 8 words for the 256-bit key

View File

@ -18,7 +18,7 @@
//! that do not need to record state.
use core::prelude::*;
use core::num::{Float, Int};
use core::num::Float;
use core::marker::PhantomData;
use {Rng, Rand};

View File

@ -13,8 +13,6 @@
// this is surprisingly complicated to be both generic & correct
use core::prelude::PartialOrd;
use core::num::Int;
use core::num::wrapping::WrappingOps;
use Rng;
use distributions::{Sample, IndependentSample};
@ -73,7 +71,7 @@ pub trait SampleRange {
}
macro_rules! integer_impl {
($ty:ty, $unsigned:ty) => {
($ty:ident, $unsigned:ident) => {
impl SampleRange for $ty {
// we play free and fast with unsigned vs signed here
// (when $ty is signed), but that's fine, since the
@ -83,7 +81,7 @@ macro_rules! integer_impl {
fn construct_range(low: $ty, high: $ty) -> Range<$ty> {
let range = (high as $unsigned).wrapping_sub(low as $unsigned);
let unsigned_max: $unsigned = Int::max_value();
let unsigned_max: $unsigned = $unsigned::max_value();
// this is the largest number that fits into $unsigned
// that `range` divides evenly, so, if we've sampled
@ -168,11 +166,11 @@ mod tests {
fn test_integers() {
let mut rng = ::test::rng();
macro_rules! t {
($($ty:ty),*) => {{
($($ty:ident),*) => {{
$(
let v: &[($ty, $ty)] = &[(0, 10),
(10, 127),
(Int::min_value(), Int::max_value())];
($ty::min_value(), $ty::max_value())];
for &(low, high) in v {
let mut sampler: Range<$ty> = Range::new(low, high);
for _ in 0..1000 {

View File

@ -836,7 +836,6 @@ pub mod writer {
use std::io::prelude::*;
use std::io::{self, SeekFrom, Cursor};
use std::slice::bytes;
use std::num::ToPrimitive;
use super::{ EsVec, EsMap, EsEnum, EsSub8, EsSub32, EsVecElt, EsMapKey,
EsU64, EsU32, EsU16, EsU8, EsI64, EsI32, EsI16, EsI8,
@ -1070,10 +1069,10 @@ pub mod writer {
impl<'a> Encoder<'a> {
// used internally to emit things like the vector length and so on
fn _emit_tagged_sub(&mut self, v: usize) -> EncodeResult {
if let Some(v) = v.to_u8() {
self.wr_tagged_raw_u8(EsSub8 as usize, v)
} else if let Some(v) = v.to_u32() {
self.wr_tagged_raw_u32(EsSub32 as usize, v)
if v as u8 as usize == v {
self.wr_tagged_raw_u8(EsSub8 as usize, v as u8)
} else if v as u32 as usize == v {
self.wr_tagged_raw_u32(EsSub32 as usize, v as u32)
} else {
Err(io::Error::new(io::ErrorKind::Other,
&format!("length or variant id too big: {}",
@ -1101,21 +1100,24 @@ pub mod writer {
self.emit_u64(v as u64)
}
fn emit_u64(&mut self, v: u64) -> EncodeResult {
match v.to_u32() {
Some(v) => self.emit_u32(v),
None => self.wr_tagged_raw_u64(EsU64 as usize, v)
if v as u32 as u64 == v {
self.emit_u32(v as u32)
} else {
self.wr_tagged_raw_u64(EsU64 as usize, v)
}
}
fn emit_u32(&mut self, v: u32) -> EncodeResult {
match v.to_u16() {
Some(v) => self.emit_u16(v),
None => self.wr_tagged_raw_u32(EsU32 as usize, v)
if v as u16 as u32 == v {
self.emit_u16(v as u16)
} else {
self.wr_tagged_raw_u32(EsU32 as usize, v)
}
}
fn emit_u16(&mut self, v: u16) -> EncodeResult {
match v.to_u8() {
Some(v) => self.emit_u8(v),
None => self.wr_tagged_raw_u16(EsU16 as usize, v)
if v as u8 as u16 == v {
self.emit_u8(v as u8)
} else {
self.wr_tagged_raw_u16(EsU16 as usize, v)
}
}
fn emit_u8(&mut self, v: u8) -> EncodeResult {
@ -1126,21 +1128,24 @@ pub mod writer {
self.emit_i64(v as i64)
}
fn emit_i64(&mut self, v: i64) -> EncodeResult {
match v.to_i32() {
Some(v) => self.emit_i32(v),
None => self.wr_tagged_raw_i64(EsI64 as usize, v)
if v as i32 as i64 == v {
self.emit_i32(v as i32)
} else {
self.wr_tagged_raw_i64(EsI64 as usize, v)
}
}
fn emit_i32(&mut self, v: i32) -> EncodeResult {
match v.to_i16() {
Some(v) => self.emit_i16(v),
None => self.wr_tagged_raw_i32(EsI32 as usize, v)
if v as i16 as i32 == v {
self.emit_i16(v as i16)
} else {
self.wr_tagged_raw_i32(EsI32 as usize, v)
}
}
fn emit_i16(&mut self, v: i16) -> EncodeResult {
match v.to_i8() {
Some(v) => self.emit_i8(v),
None => self.wr_tagged_raw_i16(EsI16 as usize, v)
if v as i8 as i16 == v {
self.emit_i8(v as i8)
} else {
self.wr_tagged_raw_i16(EsI16 as usize, v)
}
}
fn emit_i8(&mut self, v: i8) -> EncodeResult {

View File

@ -69,6 +69,9 @@ extern crate test;
pub use rustc_llvm as llvm;
#[macro_use]
mod macros;
// NB: This module needs to be declared first so diagnostics are
// registered before they are used.
pub mod diagnostics;
@ -142,6 +145,7 @@ pub mod util {
pub mod ppaux;
pub mod nodemap;
pub mod lev_distance;
pub mod num;
}
pub mod lib {

46
src/librustc/macros.rs Normal file
View File

@ -0,0 +1,46 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
macro_rules! enum_from_u32 {
($(#[$attr:meta])* pub enum $name:ident {
$($variant:ident = $e:expr,)*
}) => {
$(#[$attr])*
pub enum $name {
$($variant = $e),*
}
impl $name {
pub fn from_u32(u: u32) -> Option<$name> {
$(if u == $name::$variant as u32 {
return Some($name::$variant)
})*
None
}
}
};
($(#[$attr:meta])* pub enum $name:ident {
$($variant:ident,)*
}) => {
$(#[$attr])*
pub enum $name {
$($variant,)*
}
impl $name {
pub fn from_u32(u: u32) -> Option<$name> {
$(if u == $name::$variant as u32 {
return Some($name::$variant)
})*
None
}
}
}
}

View File

@ -116,37 +116,39 @@ pub const tag_items_data_item_reexport_def_id: usize = 0x47;
pub const tag_items_data_item_reexport_name: usize = 0x48;
// used to encode crate_ctxt side tables
#[derive(Copy, Clone, PartialEq, FromPrimitive)]
#[repr(usize)]
pub enum astencode_tag { // Reserves 0x50 -- 0x6f
tag_ast = 0x50,
enum_from_u32! {
#[derive(Copy, Clone, PartialEq)]
#[repr(usize)]
pub enum astencode_tag { // Reserves 0x50 -- 0x6f
tag_ast = 0x50,
tag_tree = 0x51,
tag_tree = 0x51,
tag_id_range = 0x52,
tag_id_range = 0x52,
tag_table = 0x53,
// GAP 0x54, 0x55
tag_table_def = 0x56,
tag_table_node_type = 0x57,
tag_table_item_subst = 0x58,
tag_table_freevars = 0x59,
tag_table_tcache = 0x5a,
tag_table_param_defs = 0x5b,
tag_table_mutbl = 0x5c,
tag_table_last_use = 0x5d,
tag_table_spill = 0x5e,
tag_table_method_map = 0x5f,
tag_table_vtable_map = 0x60,
tag_table_adjustments = 0x61,
tag_table_moves_map = 0x62,
tag_table_capture_map = 0x63,
tag_table_closure_tys = 0x64,
tag_table_closure_kinds = 0x65,
tag_table_upvar_capture_map = 0x66,
tag_table_capture_modes = 0x67,
tag_table_object_cast_map = 0x68,
tag_table_const_qualif = 0x69,
tag_table = 0x53,
// GAP 0x54, 0x55
tag_table_def = 0x56,
tag_table_node_type = 0x57,
tag_table_item_subst = 0x58,
tag_table_freevars = 0x59,
tag_table_tcache = 0x5a,
tag_table_param_defs = 0x5b,
tag_table_mutbl = 0x5c,
tag_table_last_use = 0x5d,
tag_table_spill = 0x5e,
tag_table_method_map = 0x5f,
tag_table_vtable_map = 0x60,
tag_table_adjustments = 0x61,
tag_table_moves_map = 0x62,
tag_table_capture_map = 0x63,
tag_table_closure_tys = 0x64,
tag_table_closure_kinds = 0x65,
tag_table_upvar_capture_map = 0x66,
tag_table_capture_modes = 0x67,
tag_table_object_cast_map = 0x68,
tag_table_const_qualif = 0x69,
}
}
pub const tag_item_trait_item_sort: usize = 0x70;

View File

@ -68,11 +68,13 @@ pub enum LinkagePreference {
RequireStatic,
}
#[derive(Copy, Clone, PartialEq, FromPrimitive)]
pub enum NativeLibraryKind {
NativeStatic, // native static library (.a archive)
NativeFramework, // OSX-specific
NativeUnknown, // default way to specify a dynamic library
enum_from_u32! {
#[derive(Copy, Clone, PartialEq)]
pub enum NativeLibraryKind {
NativeStatic, // native static library (.a archive)
NativeFramework, // OSX-specific
NativeUnknown, // default way to specify a dynamic library
}
}
// Where a crate came from on the local filesystem. One of these two options

View File

@ -35,7 +35,6 @@ use std::collections::HashMap;
use std::hash::{self, Hash, SipHasher};
use std::io::prelude::*;
use std::io;
use std::num::FromPrimitive;
use std::rc::Rc;
use std::slice::bytes;
use std::str;
@ -1349,7 +1348,7 @@ pub fn get_native_libraries(cdata: Cmd)
let kind_doc = reader::get_doc(lib_doc, tag_native_libraries_kind);
let name_doc = reader::get_doc(lib_doc, tag_native_libraries_name);
let kind: cstore::NativeLibraryKind =
FromPrimitive::from_u32(reader::doc_as_u32(kind_doc)).unwrap();
cstore::NativeLibraryKind::from_u32(reader::doc_as_u32(kind_doc)).unwrap();
let name = name_doc.as_str().to_string();
result.push((kind, name));
true
@ -1359,7 +1358,7 @@ pub fn get_native_libraries(cdata: Cmd)
pub fn get_plugin_registrar_fn(data: &[u8]) -> Option<ast::NodeId> {
reader::maybe_get_doc(rbml::Doc::new(data), tag_plugin_registrar_fn)
.map(|doc| FromPrimitive::from_u32(reader::doc_as_u32(doc)).unwrap())
.map(|doc| reader::doc_as_u32(doc))
}
pub fn each_exported_macro<F>(data: &[u8], intr: &IdentInterner, mut f: F) where
@ -1407,7 +1406,7 @@ pub fn get_missing_lang_items(cdata: Cmd)
let mut result = Vec::new();
reader::tagged_docs(items, tag_lang_items_missing, |missing_docs| {
let item: lang_items::LangItem =
FromPrimitive::from_u32(reader::doc_as_u32(missing_docs)).unwrap();
lang_items::LangItem::from_u32(reader::doc_as_u32(missing_docs)).unwrap();
result.push(item);
true
});

View File

@ -41,7 +41,6 @@ use syntax;
use std::cell::Cell;
use std::io::SeekFrom;
use std::io::prelude::*;
use std::num::FromPrimitive;
use std::rc::Rc;
use std::fmt::Debug;
@ -1713,7 +1712,8 @@ fn decode_side_tables(dcx: &DecodeContext,
debug!(">> Side table document with tag 0x{:x} \
found for id {} (orig {})",
tag, id, id0);
let decoded_tag: Option<c::astencode_tag> = FromPrimitive::from_usize(tag);
let tag = tag as u32;
let decoded_tag: Option<c::astencode_tag> = c::astencode_tag::from_u32(tag);
match decoded_tag {
None => {
dcx.tcx.sess.bug(

View File

@ -20,6 +20,7 @@ use middle::{astencode, def};
use middle::pat_util::def_to_path;
use middle::ty::{self, Ty};
use middle::astconv_util::ast_ty_to_prim_ty;
use util::num::ToPrimitive;
use syntax::ast::{self, Expr};
use syntax::codemap::Span;
@ -30,7 +31,6 @@ use syntax::{ast_map, ast_util, codemap};
use std::borrow::{Cow, IntoCow};
use std::num::wrapping::OverflowingOps;
use std::num::ToPrimitive;
use std::cmp::Ordering;
use std::collections::hash_map::Entry::Vacant;
use std::{i8, i16, i32, i64};

View File

@ -36,7 +36,6 @@ use syntax::visit::Visitor;
use syntax::visit;
use std::iter::Enumerate;
use std::num::FromPrimitive;
use std::slice;
// The actual lang items defined come at the end of this file in one handy table.
@ -46,9 +45,12 @@ macro_rules! lets_do_this {
$( $variant:ident, $name:expr, $method:ident; )*
) => {
#[derive(Copy, Clone, FromPrimitive, PartialEq, Eq, Hash)]
pub enum LangItem {
$($variant),*
enum_from_u32! {
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub enum LangItem {
$($variant,)*
}
}
pub struct LanguageItems {
@ -71,7 +73,7 @@ impl LanguageItems {
}
pub fn item_name(index: usize) -> &'static str {
let item: Option<LangItem> = FromPrimitive::from_usize(index);
let item: Option<LangItem> = LangItem::from_u32(index as u32);
match item {
$( Some($variant) => $name, )*
None => "???"

View File

@ -63,6 +63,7 @@ use util::ppaux::{Repr, UserString};
use util::common::{memoized, ErrorReported};
use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet};
use util::nodemap::FnvHashMap;
use util::num::ToPrimitive;
use arena::TypedArena;
use std::borrow::{Borrow, Cow};
@ -71,7 +72,6 @@ use std::cmp;
use std::fmt;
use std::hash::{Hash, SipHasher, Hasher};
use std::mem;
use std::num::ToPrimitive;
use std::ops;
use std::rc::Rc;
use std::vec::IntoIter;

98
src/librustc/util/num.rs Normal file
View File

@ -0,0 +1,98 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub trait ToPrimitive {
fn to_i8(&self) -> Option<i8>;
fn to_i16(&self) -> Option<i16>;
fn to_i32(&self) -> Option<i32>;
fn to_i64(&self) -> Option<i64>;
fn to_u8(&self) -> Option<u8>;
fn to_u16(&self) -> Option<u16>;
fn to_u32(&self) -> Option<u32>;
fn to_u64(&self) -> Option<u64>;
}
impl ToPrimitive for i64 {
fn to_i8(&self) -> Option<i8> {
if *self < i8::min_value() as i64 || *self > i8::max_value() as i64 {
None
} else {
Some(*self as i8)
}
}
fn to_i16(&self) -> Option<i16> {
if *self < i16::min_value() as i64 || *self > i16::max_value() as i64 {
None
} else {
Some(*self as i16)
}
}
fn to_i32(&self) -> Option<i32> {
if *self < i32::min_value() as i64 || *self > i32::max_value() as i64 {
None
} else {
Some(*self as i32)
}
}
fn to_i64(&self) -> Option<i64> {
Some(*self)
}
fn to_u8(&self) -> Option<u8> {
if *self < 0 || *self > u8::max_value() as i64 {
None
} else {
Some(*self as u8)
}
}
fn to_u16(&self) -> Option<u16> {
if *self < 0 || *self > u16::max_value() as i64 {
None
} else {
Some(*self as u16)
}
}
fn to_u32(&self) -> Option<u32> {
if *self < 0 || *self > u32::max_value() as i64 {
None
} else {
Some(*self as u32)
}
}
fn to_u64(&self) -> Option<u64> {
if *self < 0 {None} else {Some(*self as u64)}
}
}
impl ToPrimitive for u64 {
fn to_i8(&self) -> Option<i8> {
if *self > i8::max_value() as u64 {None} else {Some(*self as i8)}
}
fn to_i16(&self) -> Option<i16> {
if *self > i16::max_value() as u64 {None} else {Some(*self as i16)}
}
fn to_i32(&self) -> Option<i32> {
if *self > i32::max_value() as u64 {None} else {Some(*self as i32)}
}
fn to_i64(&self) -> Option<i64> {
if *self > i64::max_value() as u64 {None} else {Some(*self as i64)}
}
fn to_u8(&self) -> Option<u8> {
if *self > u8::max_value() as u64 {None} else {Some(*self as u8)}
}
fn to_u16(&self) -> Option<u16> {
if *self > u16::max_value() as u64 {None} else {Some(*self as u16)}
}
fn to_u32(&self) -> Option<u32> {
if *self > u32::max_value() as u64 {None} else {Some(*self as u32)}
}
fn to_u64(&self) -> Option<u64> {
Some(*self)
}
}

View File

@ -12,10 +12,7 @@
//! use. This implementation is not intended for external use or for any use where security is
//! important.
#![allow(deprecated)] // to_be32
use std::iter::repeat;
use std::num::Int;
use std::slice::bytes::{MutableByteVector, copy_memory};
use serialize::hex::ToHex;
@ -61,10 +58,10 @@ impl ToBits for u64 {
/// Adds the specified number of bytes to the bit count. panic!() if this would cause numeric
/// overflow.
fn add_bytes_to_bits<T: Int + ToBits>(bits: T, bytes: T) -> T {
fn add_bytes_to_bits(bits: u64, bytes: u64) -> u64 {
let (new_high_bits, new_low_bits) = bytes.to_bits();
if new_high_bits > T::zero() {
if new_high_bits > 0 {
panic!("numeric overflow occurred.")
}

View File

@ -21,9 +21,6 @@ use libc;
use flate;
use std::ffi::CString;
use std::mem;
#[allow(deprecated)]
use std::num::Int;
pub fn run(sess: &session::Session, llmod: ModuleRef,
tm: TargetMachineRef, reachable: &[String]) {
@ -198,19 +195,15 @@ fn is_versioned_bytecode_format(bc: &[u8]) -> bool {
}
fn extract_bytecode_format_version(bc: &[u8]) -> u32 {
return read_from_le_bytes::<u32>(bc, link::RLIB_BYTECODE_OBJECT_VERSION_OFFSET);
let pos = link::RLIB_BYTECODE_OBJECT_VERSION_OFFSET;
let byte_data = &bc[pos..pos + 4];
let data = unsafe { *(byte_data.as_ptr() as *const u32) };
u32::from_le(data)
}
fn extract_compressed_bytecode_size_v1(bc: &[u8]) -> u64 {
return read_from_le_bytes::<u64>(bc, link::RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET);
}
#[allow(deprecated)]
fn read_from_le_bytes<T: Int>(bytes: &[u8], position_in_bytes: usize) -> T {
let byte_data = &bytes[position_in_bytes..position_in_bytes + mem::size_of::<T>()];
let data = unsafe {
*(byte_data.as_ptr() as *const T)
};
Int::from_le(data)
let pos = link::RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET;
let byte_data = &bc[pos..pos + 8];
let data = unsafe { *(byte_data.as_ptr() as *const u64) };
u64::from_le(data)
}

View File

@ -45,8 +45,6 @@
pub use self::Repr::*;
#[allow(deprecated)]
use std::num::Int;
use std::rc::Rc;
use llvm::{ValueRef, True, IntEQ, IntNE};

View File

@ -21,8 +21,6 @@ use util::ppaux::Repr;
use trans::type_::Type;
#[allow(deprecated)]
use std::num::Int;
use syntax::abi;
use syntax::ast;

View File

@ -204,12 +204,10 @@ use std::io::prelude::*;
use std::io;
use std::mem::swap;
use std::num::FpCategory as Fp;
#[allow(deprecated)]
use std::num::wrapping::WrappingOps;
use std::ops::Index;
use std::str::FromStr;
use std::string;
use std::{char, f64, fmt, num, str};
use std::{char, f64, fmt, str};
use std;
use rustc_unicode::str as unicode_str;
use rustc_unicode::str::Utf16Item;
@ -460,8 +458,8 @@ fn spaces(wr: &mut fmt::Write, mut n: usize) -> EncodeResult {
fn fmt_number_or_null(v: f64) -> string::String {
match v.classify() {
Fp::Nan | Fp::Infinite => string::String::from_str("null"),
_ if v.fract() != 0f64 => f64::to_str_digits(v, 6),
_ => f64::to_str_digits(v, 6) + ".0",
_ if v.fract() != 0f64 => v.to_string(),
_ => v.to_string() + ".0",
}
}
@ -1165,7 +1163,7 @@ impl Json {
pub fn as_i64(&self) -> Option<i64> {
match *self {
Json::I64(n) => Some(n),
Json::U64(n) => num::cast(n),
Json::U64(n) => Some(n as i64),
_ => None
}
}
@ -1174,7 +1172,7 @@ impl Json {
/// Returns None otherwise.
pub fn as_u64(&self) -> Option<u64> {
match *self {
Json::I64(n) => num::cast(n),
Json::I64(n) => Some(n as u64),
Json::U64(n) => Some(n),
_ => None
}
@ -1184,8 +1182,8 @@ impl Json {
/// Returns None otherwise.
pub fn as_f64(&self) -> Option<f64> {
match *self {
Json::I64(n) => num::cast(n),
Json::U64(n) => num::cast(n),
Json::I64(n) => Some(n as f64),
Json::U64(n) => Some(n as f64),
Json::F64(n) => Some(n),
_ => None
}
@ -1556,7 +1554,7 @@ impl<T: Iterator<Item=char>> Parser<T> {
#[allow(deprecated)] // possible resolve bug is mapping these to traits
fn parse_u64(&mut self) -> Result<u64, ParserError> {
let mut accum = 0;
let mut accum = 0u64;
let last_accum = 0; // necessary to detect overflow.
match self.ch_or_null() {
@ -2121,14 +2119,8 @@ macro_rules! read_primitive {
($name:ident, $ty:ty) => {
fn $name(&mut self) -> DecodeResult<$ty> {
match self.pop() {
Json::I64(f) => match num::cast(f) {
Some(f) => Ok(f),
None => Err(ExpectedError("Number".to_string(), format!("{}", f))),
},
Json::U64(f) => match num::cast(f) {
Some(f) => Ok(f),
None => Err(ExpectedError("Number".to_string(), format!("{}", f))),
},
Json::I64(f) => Ok(f as $ty),
Json::U64(f) => Ok(f as $ty),
Json::F64(f) => Err(ExpectedError("Integer".to_string(), format!("{}", f))),
// re: #12967.. a type w/ numeric keys (ie HashMap<usize, V> etc)
// is going to have a string here, as per JSON spec.

View File

@ -17,7 +17,7 @@ use iter::{Iterator, ExactSizeIterator};
use marker::{Copy, Send, Sync, Sized, self};
use mem::{min_align_of, size_of};
use mem;
use num::wrapping::{OverflowingOps, WrappingOps};
use num::wrapping::OverflowingOps;
use ops::{Deref, DerefMut, Drop};
use option::Option;
use option::Option::{Some, None};

View File

@ -172,13 +172,6 @@ impl Error {
Error { repr: Repr::Os(code) }
}
/// Creates a new instance of an `Error` from a particular OS error code.
#[unstable(feature = "io", reason = "deprecated")]
#[deprecated(since = "1.0.0", reason = "renamed to from_raw_os_error")]
pub fn from_os_error(code: i32) -> Error {
Error { repr: Repr::Os(code) }
}
/// Returns the OS error that this error represents (if any).
///
/// If this `Error` was constructed via `last_os_error` then this function

View File

@ -128,6 +128,7 @@
#![feature(std_misc)]
#![feature(slice_patterns)]
#![feature(debug_builders)]
#![feature(zero_one)]
#![cfg_attr(test, feature(test, rustc_private, std_misc))]
// Don't link to std. We are std.

View File

@ -18,8 +18,6 @@
use prelude::v1::*;
use io::{self, Error, ErrorKind};
#[allow(deprecated)] // Int
use num::Int;
use sys_common::net2 as net_imp;
pub use self::ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
@ -55,10 +53,21 @@ pub enum Shutdown {
Both,
}
#[allow(deprecated)] // Int
fn hton<I: Int>(i: I) -> I { i.to_be() }
#[allow(deprecated)] // Int
fn ntoh<I: Int>(i: I) -> I { Int::from_be(i) }
#[doc(hidden)]
trait NetInt {
fn from_be(i: Self) -> Self;
fn to_be(&self) -> Self;
}
macro_rules! doit {
($($t:ident)*) => ($(impl NetInt for $t {
fn from_be(i: Self) -> Self { <$t>::from_be(i) }
fn to_be(&self) -> Self { <$t>::to_be(*self) }
})*)
}
doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
fn hton<I: NetInt>(i: I) -> I { i.to_be() }
fn ntoh<I: NetInt>(i: I) -> I { I::from_be(i) }
fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T>
where F: FnMut(&SocketAddr) -> io::Result<T>

View File

@ -15,20 +15,14 @@
#![allow(unsigned_negation)]
#![doc(primitive = "f32")]
use prelude::v1::*;
use intrinsics;
use libc::c_int;
use num::{Float, FpCategory};
use num::strconv;
use num::strconv::ExponentFormat::{ExpNone, ExpDec};
use num::strconv::SignificantDigits::{DigAll, DigMax, DigExact};
use num::strconv::SignFormat::SignNeg;
use num::FpCategory;
use core::num;
pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON, MIN_VALUE};
pub use core::f32::{MIN_POS_VALUE, MAX_VALUE, MIN_EXP, MAX_EXP, MIN_10_EXP};
pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON};
pub use core::f32::{MIN_EXP, MAX_EXP, MIN_10_EXP};
pub use core::f32::{MAX_10_EXP, NAN, INFINITY, NEG_INFINITY};
pub use core::f32::{MIN, MIN_POSITIVE, MAX};
pub use core::f32::consts;
@ -74,290 +68,6 @@ mod cmath {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
impl Float for f32 {
#[inline]
fn nan() -> f32 { num::Float::nan() }
#[inline]
fn infinity() -> f32 { num::Float::infinity() }
#[inline]
fn neg_infinity() -> f32 { num::Float::neg_infinity() }
#[inline]
fn zero() -> f32 { num::Float::zero() }
#[inline]
fn neg_zero() -> f32 { num::Float::neg_zero() }
#[inline]
fn one() -> f32 { num::Float::one() }
#[allow(deprecated)]
#[inline]
fn mantissa_digits(unused_self: Option<f32>) -> usize {
num::Float::mantissa_digits(unused_self)
}
#[allow(deprecated)]
#[inline]
fn digits(unused_self: Option<f32>) -> usize { num::Float::digits(unused_self) }
#[allow(deprecated)]
#[inline]
fn epsilon() -> f32 { num::Float::epsilon() }
#[allow(deprecated)]
#[inline]
fn min_exp(unused_self: Option<f32>) -> isize { num::Float::min_exp(unused_self) }
#[allow(deprecated)]
#[inline]
fn max_exp(unused_self: Option<f32>) -> isize { num::Float::max_exp(unused_self) }
#[allow(deprecated)]
#[inline]
fn min_10_exp(unused_self: Option<f32>) -> isize { num::Float::min_10_exp(unused_self) }
#[allow(deprecated)]
#[inline]
fn max_10_exp(unused_self: Option<f32>) -> isize { num::Float::max_10_exp(unused_self) }
#[allow(deprecated)]
#[inline]
fn min_value() -> f32 { num::Float::min_value() }
#[allow(deprecated)]
#[inline]
fn min_pos_value(unused_self: Option<f32>) -> f32 { num::Float::min_pos_value(unused_self) }
#[allow(deprecated)]
#[inline]
fn max_value() -> f32 { num::Float::max_value() }
#[inline]
fn is_nan(self) -> bool { num::Float::is_nan(self) }
#[inline]
fn is_infinite(self) -> bool { num::Float::is_infinite(self) }
#[inline]
fn is_finite(self) -> bool { num::Float::is_finite(self) }
#[inline]
fn is_normal(self) -> bool { num::Float::is_normal(self) }
#[inline]
fn classify(self) -> FpCategory { num::Float::classify(self) }
#[inline]
fn integer_decode(self) -> (u64, i16, i8) { num::Float::integer_decode(self) }
#[inline]
fn floor(self) -> f32 { num::Float::floor(self) }
#[inline]
fn ceil(self) -> f32 { num::Float::ceil(self) }
#[inline]
fn round(self) -> f32 { num::Float::round(self) }
#[inline]
fn trunc(self) -> f32 { num::Float::trunc(self) }
#[inline]
fn fract(self) -> f32 { num::Float::fract(self) }
#[inline]
fn abs(self) -> f32 { num::Float::abs(self) }
#[inline]
fn signum(self) -> f32 { num::Float::signum(self) }
#[inline]
fn is_positive(self) -> bool { num::Float::is_positive(self) }
#[inline]
fn is_negative(self) -> bool { num::Float::is_negative(self) }
#[inline]
fn mul_add(self, a: f32, b: f32) -> f32 { num::Float::mul_add(self, a, b) }
#[inline]
fn recip(self) -> f32 { num::Float::recip(self) }
#[inline]
fn powi(self, n: i32) -> f32 { num::Float::powi(self, n) }
#[inline]
fn powf(self, n: f32) -> f32 { num::Float::powf(self, n) }
#[inline]
fn sqrt(self) -> f32 { num::Float::sqrt(self) }
#[inline]
fn rsqrt(self) -> f32 { num::Float::rsqrt(self) }
#[inline]
fn exp(self) -> f32 { num::Float::exp(self) }
#[inline]
fn exp2(self) -> f32 { num::Float::exp2(self) }
#[inline]
fn ln(self) -> f32 { num::Float::ln(self) }
#[inline]
fn log(self, base: f32) -> f32 { num::Float::log(self, base) }
#[inline]
fn log2(self) -> f32 { num::Float::log2(self) }
#[inline]
fn log10(self) -> f32 { num::Float::log10(self) }
#[inline]
fn to_degrees(self) -> f32 { num::Float::to_degrees(self) }
#[inline]
fn to_radians(self) -> f32 { num::Float::to_radians(self) }
/// Constructs a floating point number by multiplying `x` by 2 raised to the
/// power of `exp`
#[inline]
fn ldexp(self, exp: isize) -> f32 {
unsafe { cmath::ldexpf(self, exp as c_int) }
}
/// Breaks the number into a normalized fraction and a base-2 exponent,
/// satisfying:
///
/// - `self = x * pow(2, exp)`
/// - `0.5 <= abs(x) < 1.0`
#[inline]
fn frexp(self) -> (f32, isize) {
unsafe {
let mut exp = 0;
let x = cmath::frexpf(self, &mut exp);
(x, exp as isize)
}
}
/// Returns the next representable floating-point value in the direction of
/// `other`.
#[inline]
fn next_after(self, other: f32) -> f32 {
unsafe { cmath::nextafterf(self, other) }
}
#[inline]
fn max(self, other: f32) -> f32 {
unsafe { cmath::fmaxf(self, other) }
}
#[inline]
fn min(self, other: f32) -> f32 {
unsafe { cmath::fminf(self, other) }
}
#[inline]
fn abs_sub(self, other: f32) -> f32 {
unsafe { cmath::fdimf(self, other) }
}
#[inline]
fn cbrt(self) -> f32 {
unsafe { cmath::cbrtf(self) }
}
#[inline]
fn hypot(self, other: f32) -> f32 {
unsafe { cmath::hypotf(self, other) }
}
#[inline]
fn sin(self) -> f32 {
unsafe { intrinsics::sinf32(self) }
}
#[inline]
fn cos(self) -> f32 {
unsafe { intrinsics::cosf32(self) }
}
#[inline]
fn tan(self) -> f32 {
unsafe { cmath::tanf(self) }
}
#[inline]
fn asin(self) -> f32 {
unsafe { cmath::asinf(self) }
}
#[inline]
fn acos(self) -> f32 {
unsafe { cmath::acosf(self) }
}
#[inline]
fn atan(self) -> f32 {
unsafe { cmath::atanf(self) }
}
#[inline]
fn atan2(self, other: f32) -> f32 {
unsafe { cmath::atan2f(self, other) }
}
/// Simultaneously computes the sine and cosine of the number
#[inline]
fn sin_cos(self) -> (f32, f32) {
(self.sin(), self.cos())
}
/// Returns the exponential of the number, minus `1`, in a way that is
/// accurate even if the number is close to zero
#[inline]
fn exp_m1(self) -> f32 {
unsafe { cmath::expm1f(self) }
}
/// Returns the natural logarithm of the number plus `1` (`ln(1+n)`) more
/// accurately than if the operations were performed separately
#[inline]
fn ln_1p(self) -> f32 {
unsafe { cmath::log1pf(self) }
}
#[inline]
fn sinh(self) -> f32 {
unsafe { cmath::sinhf(self) }
}
#[inline]
fn cosh(self) -> f32 {
unsafe { cmath::coshf(self) }
}
#[inline]
fn tanh(self) -> f32 {
unsafe { cmath::tanhf(self) }
}
/// Inverse hyperbolic sine
///
/// # Returns
///
/// - on success, the inverse hyperbolic sine of `self` will be returned
/// - `self` if `self` is `0.0`, `-0.0`, `INFINITY`, or `NEG_INFINITY`
/// - `NAN` if `self` is `NAN`
#[inline]
fn asinh(self) -> f32 {
match self {
NEG_INFINITY => NEG_INFINITY,
x => (x + ((x * x) + 1.0).sqrt()).ln(),
}
}
/// Inverse hyperbolic cosine
///
/// # Returns
///
/// - on success, the inverse hyperbolic cosine of `self` will be returned
/// - `INFINITY` if `self` is `INFINITY`
/// - `NAN` if `self` is `NAN` or `self < 1.0` (including `NEG_INFINITY`)
#[inline]
fn acosh(self) -> f32 {
match self {
x if x < 1.0 => Float::nan(),
x => (x + ((x * x) - 1.0).sqrt()).ln(),
}
}
/// Inverse hyperbolic tangent
///
/// # Returns
///
/// - on success, the inverse hyperbolic tangent of `self` will be returned
/// - `self` if `self` is `0.0` or `-0.0`
/// - `INFINITY` if `self` is `1.0`
/// - `NEG_INFINITY` if `self` is `-1.0`
/// - `NAN` if the `self` is `NAN` or outside the domain of `-1.0 <= self <= 1.0`
/// (including `INFINITY` and `NEG_INFINITY`)
#[inline]
fn atanh(self) -> f32 {
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
}
}
#[cfg(not(test))]
#[lang = "f32"]
#[stable(feature = "rust1", since = "1.0.0")]
@ -617,11 +327,6 @@ impl f32 {
#[inline]
pub fn is_sign_positive(self) -> bool { num::Float::is_positive(self) }
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "renamed to is_sign_positive")]
#[inline]
pub fn is_positive(self) -> bool { num::Float::is_positive(self) }
/// Returns `true` if `self`'s sign is negative, including `-0.0`
/// and `NEG_INFINITY`.
///
@ -641,11 +346,6 @@ impl f32 {
#[inline]
pub fn is_sign_negative(self) -> bool { num::Float::is_negative(self) }
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "renamed to is_sign_negative")]
#[inline]
pub fn is_negative(self) -> bool { num::Float::is_negative(self) }
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
/// error. This produces a more accurate result with better performance than
/// a separate multiplication operation followed by an add.
@ -729,24 +429,6 @@ impl f32 {
#[inline]
pub fn sqrt(self) -> f32 { num::Float::sqrt(self) }
/// Takes the reciprocal (inverse) square root of a number, `1/sqrt(x)`.
///
/// ```
/// # #![feature(std_misc)]
/// use std::f32;
///
/// let f = 4.0f32;
///
/// let abs_difference = (f.rsqrt() - 0.5).abs();
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
#[deprecated(since = "1.0.0", reason = "use self.sqrt().recip() instead")]
#[inline]
pub fn rsqrt(self) -> f32 { num::Float::rsqrt(self) }
/// Returns `e^(self)`, (the exponential function).
///
/// ```
@ -1339,7 +1021,7 @@ impl f32 {
#[inline]
pub fn acosh(self) -> f32 {
match self {
x if x < 1.0 => Float::nan(),
x if x < 1.0 => num::Float::nan(),
x => (x + ((x * x) - 1.0).sqrt()).ln(),
}
}
@ -1363,114 +1045,6 @@ impl f32 {
}
}
//
// Section: String Conversions
//
/// Converts a float to a string
///
/// # Arguments
///
/// * num - The float value
#[inline]
#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
#[deprecated(since = "1.0.0", reason = "use the ToString trait instead")]
pub fn to_string(num: f32) -> String {
let (r, _) = strconv::float_to_str_common(
num, 10, true, SignNeg, DigAll, ExpNone, false);
r
}
/// Converts a float to a string in hexadecimal format
///
/// # Arguments
///
/// * num - The float value
#[inline]
#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
#[deprecated(since = "1.0.0", reason = "use format! instead")]
pub fn to_str_hex(num: f32) -> String {
let (r, _) = strconv::float_to_str_common(
num, 16, true, SignNeg, DigAll, ExpNone, false);
r
}
/// Converts a float to a string in a given radix, and a flag indicating
/// whether it's a special value
///
/// # Arguments
///
/// * num - The float value
/// * radix - The base to use
#[inline]
#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
#[deprecated(since = "1.0.0", reason = "use format! instead")]
pub fn to_str_radix_special(num: f32, rdx: u32) -> (String, bool) {
strconv::float_to_str_common(num, rdx, true, SignNeg, DigAll, ExpNone, false)
}
/// Converts a float to a string with exactly the number of
/// provided significant digits
///
/// # Arguments
///
/// * num - The float value
/// * digits - The number of significant digits
#[inline]
#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
pub fn to_str_exact(num: f32, dig: usize) -> String {
let (r, _) = strconv::float_to_str_common(
num, 10, true, SignNeg, DigExact(dig), ExpNone, false);
r
}
/// Converts a float to a string with a maximum number of
/// significant digits
///
/// # Arguments
///
/// * num - The float value
/// * digits - The number of significant digits
#[inline]
#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
pub fn to_str_digits(num: f32, dig: usize) -> String {
let (r, _) = strconv::float_to_str_common(
num, 10, true, SignNeg, DigMax(dig), ExpNone, false);
r
}
/// Converts a float to a string using the exponential notation with exactly the number of
/// provided digits after the decimal point in the significand
///
/// # Arguments
///
/// * num - The float value
/// * digits - The number of digits after the decimal point
/// * upper - Use `E` instead of `e` for the exponent sign
#[inline]
#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
pub fn to_str_exp_exact(num: f32, dig: usize, upper: bool) -> String {
let (r, _) = strconv::float_to_str_common(
num, 10, true, SignNeg, DigExact(dig), ExpDec, upper);
r
}
/// Converts a float to a string using the exponential notation with the maximum number of
/// digits after the decimal point in the significand
///
/// # Arguments
///
/// * num - The float value
/// * digits - The number of digits after the decimal point
/// * upper - Use `E` instead of `e` for the exponent sign
#[inline]
#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
pub fn to_str_exp_digits(num: f32, dig: usize, upper: bool) -> String {
let (r, _) = strconv::float_to_str_common(
num, 10, true, SignNeg, DigMax(dig), ExpDec, upper);
r
}
#[cfg(test)]
mod tests {
use f32::*;

View File

@ -14,20 +14,14 @@
#![allow(missing_docs)]
#![doc(primitive = "f64")]
use prelude::v1::*;
use intrinsics;
use libc::c_int;
use num::{Float, FpCategory};
use num::strconv;
use num::strconv::ExponentFormat::{ExpNone, ExpDec};
use num::strconv::SignificantDigits::{DigAll, DigMax, DigExact};
use num::strconv::SignFormat::SignNeg;
use num::FpCategory;
use core::num;
pub use core::f64::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON, MIN_VALUE};
pub use core::f64::{MIN_POS_VALUE, MAX_VALUE, MIN_EXP, MAX_EXP, MIN_10_EXP};
pub use core::f64::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON};
pub use core::f64::{MIN_EXP, MAX_EXP, MIN_10_EXP};
pub use core::f64::{MAX_10_EXP, NAN, INFINITY, NEG_INFINITY};
pub use core::f64::{MIN, MIN_POSITIVE, MAX};
pub use core::f64::consts;
@ -82,291 +76,6 @@ mod cmath {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
impl Float for f64 {
// inlined methods from `num::Float`
#[inline]
fn nan() -> f64 { num::Float::nan() }
#[inline]
fn infinity() -> f64 { num::Float::infinity() }
#[inline]
fn neg_infinity() -> f64 { num::Float::neg_infinity() }
#[inline]
fn zero() -> f64 { num::Float::zero() }
#[inline]
fn neg_zero() -> f64 { num::Float::neg_zero() }
#[inline]
fn one() -> f64 { num::Float::one() }
#[allow(deprecated)]
#[inline]
fn mantissa_digits(unused_self: Option<f64>) -> usize {
num::Float::mantissa_digits(unused_self)
}
#[allow(deprecated)]
#[inline]
fn digits(unused_self: Option<f64>) -> usize { num::Float::digits(unused_self) }
#[allow(deprecated)]
#[inline]
fn epsilon() -> f64 { num::Float::epsilon() }
#[allow(deprecated)]
#[inline]
fn min_exp(unused_self: Option<f64>) -> isize { num::Float::min_exp(unused_self) }
#[allow(deprecated)]
#[inline]
fn max_exp(unused_self: Option<f64>) -> isize { num::Float::max_exp(unused_self) }
#[allow(deprecated)]
#[inline]
fn min_10_exp(unused_self: Option<f64>) -> isize { num::Float::min_10_exp(unused_self) }
#[allow(deprecated)]
#[inline]
fn max_10_exp(unused_self: Option<f64>) -> isize { num::Float::max_10_exp(unused_self) }
#[allow(deprecated)]
#[inline]
fn min_value() -> f64 { num::Float::min_value() }
#[allow(deprecated)]
#[inline]
fn min_pos_value(unused_self: Option<f64>) -> f64 { num::Float::min_pos_value(unused_self) }
#[allow(deprecated)]
#[inline]
fn max_value() -> f64 { num::Float::max_value() }
#[inline]
fn is_nan(self) -> bool { num::Float::is_nan(self) }
#[inline]
fn is_infinite(self) -> bool { num::Float::is_infinite(self) }
#[inline]
fn is_finite(self) -> bool { num::Float::is_finite(self) }
#[inline]
fn is_normal(self) -> bool { num::Float::is_normal(self) }
#[inline]
fn classify(self) -> FpCategory { num::Float::classify(self) }
#[inline]
fn integer_decode(self) -> (u64, i16, i8) { num::Float::integer_decode(self) }
#[inline]
fn floor(self) -> f64 { num::Float::floor(self) }
#[inline]
fn ceil(self) -> f64 { num::Float::ceil(self) }
#[inline]
fn round(self) -> f64 { num::Float::round(self) }
#[inline]
fn trunc(self) -> f64 { num::Float::trunc(self) }
#[inline]
fn fract(self) -> f64 { num::Float::fract(self) }
#[inline]
fn abs(self) -> f64 { num::Float::abs(self) }
#[inline]
fn signum(self) -> f64 { num::Float::signum(self) }
#[inline]
fn is_positive(self) -> bool { num::Float::is_positive(self) }
#[inline]
fn is_negative(self) -> bool { num::Float::is_negative(self) }
#[inline]
fn mul_add(self, a: f64, b: f64) -> f64 { num::Float::mul_add(self, a, b) }
#[inline]
fn recip(self) -> f64 { num::Float::recip(self) }
#[inline]
fn powi(self, n: i32) -> f64 { num::Float::powi(self, n) }
#[inline]
fn powf(self, n: f64) -> f64 { num::Float::powf(self, n) }
#[inline]
fn sqrt(self) -> f64 { num::Float::sqrt(self) }
#[inline]
fn rsqrt(self) -> f64 { num::Float::rsqrt(self) }
#[inline]
fn exp(self) -> f64 { num::Float::exp(self) }
#[inline]
fn exp2(self) -> f64 { num::Float::exp2(self) }
#[inline]
fn ln(self) -> f64 { num::Float::ln(self) }
#[inline]
fn log(self, base: f64) -> f64 { num::Float::log(self, base) }
#[inline]
fn log2(self) -> f64 { num::Float::log2(self) }
#[inline]
fn log10(self) -> f64 { num::Float::log10(self) }
#[inline]
fn to_degrees(self) -> f64 { num::Float::to_degrees(self) }
#[inline]
fn to_radians(self) -> f64 { num::Float::to_radians(self) }
#[inline]
fn ldexp(self, exp: isize) -> f64 {
unsafe { cmath::ldexp(self, exp as c_int) }
}
/// Breaks the number into a normalized fraction and a base-2 exponent,
/// satisfying:
///
/// - `self = x * pow(2, exp)`
/// - `0.5 <= abs(x) < 1.0`
#[inline]
fn frexp(self) -> (f64, isize) {
unsafe {
let mut exp = 0;
let x = cmath::frexp(self, &mut exp);
(x, exp as isize)
}
}
/// Returns the next representable floating-point value in the direction of
/// `other`.
#[inline]
fn next_after(self, other: f64) -> f64 {
unsafe { cmath::nextafter(self, other) }
}
#[inline]
fn max(self, other: f64) -> f64 {
unsafe { cmath::fmax(self, other) }
}
#[inline]
fn min(self, other: f64) -> f64 {
unsafe { cmath::fmin(self, other) }
}
#[inline]
fn abs_sub(self, other: f64) -> f64 {
unsafe { cmath::fdim(self, other) }
}
#[inline]
fn cbrt(self) -> f64 {
unsafe { cmath::cbrt(self) }
}
#[inline]
fn hypot(self, other: f64) -> f64 {
unsafe { cmath::hypot(self, other) }
}
#[inline]
fn sin(self) -> f64 {
unsafe { intrinsics::sinf64(self) }
}
#[inline]
fn cos(self) -> f64 {
unsafe { intrinsics::cosf64(self) }
}
#[inline]
fn tan(self) -> f64 {
unsafe { cmath::tan(self) }
}
#[inline]
fn asin(self) -> f64 {
unsafe { cmath::asin(self) }
}
#[inline]
fn acos(self) -> f64 {
unsafe { cmath::acos(self) }
}
#[inline]
fn atan(self) -> f64 {
unsafe { cmath::atan(self) }
}
#[inline]
fn atan2(self, other: f64) -> f64 {
unsafe { cmath::atan2(self, other) }
}
/// Simultaneously computes the sine and cosine of the number
#[inline]
fn sin_cos(self) -> (f64, f64) {
(self.sin(), self.cos())
}
/// Returns the exponential of the number, minus `1`, in a way that is
/// accurate even if the number is close to zero
#[inline]
fn exp_m1(self) -> f64 {
unsafe { cmath::expm1(self) }
}
/// Returns the natural logarithm of the number plus `1` (`ln(1+n)`) more
/// accurately than if the operations were performed separately
#[inline]
fn ln_1p(self) -> f64 {
unsafe { cmath::log1p(self) }
}
#[inline]
fn sinh(self) -> f64 {
unsafe { cmath::sinh(self) }
}
#[inline]
fn cosh(self) -> f64 {
unsafe { cmath::cosh(self) }
}
#[inline]
fn tanh(self) -> f64 {
unsafe { cmath::tanh(self) }
}
/// Inverse hyperbolic sine
///
/// # Returns
///
/// - on success, the inverse hyperbolic sine of `self` will be returned
/// - `self` if `self` is `0.0`, `-0.0`, `INFINITY`, or `NEG_INFINITY`
/// - `NAN` if `self` is `NAN`
#[inline]
fn asinh(self) -> f64 {
match self {
NEG_INFINITY => NEG_INFINITY,
x => (x + ((x * x) + 1.0).sqrt()).ln(),
}
}
/// Inverse hyperbolic cosine
///
/// # Returns
///
/// - on success, the inverse hyperbolic cosine of `self` will be returned
/// - `INFINITY` if `self` is `INFINITY`
/// - `NAN` if `self` is `NAN` or `self < 1.0` (including `NEG_INFINITY`)
#[inline]
fn acosh(self) -> f64 {
match self {
x if x < 1.0 => Float::nan(),
x => (x + ((x * x) - 1.0).sqrt()).ln(),
}
}
/// Inverse hyperbolic tangent
///
/// # Returns
///
/// - on success, the inverse hyperbolic tangent of `self` will be returned
/// - `self` if `self` is `0.0` or `-0.0`
/// - `INFINITY` if `self` is `1.0`
/// - `NEG_INFINITY` if `self` is `-1.0`
/// - `NAN` if the `self` is `NAN` or outside the domain of `-1.0 <= self <= 1.0`
/// (including `INFINITY` and `NEG_INFINITY`)
#[inline]
fn atanh(self) -> f64 {
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
}
}
#[cfg(not(test))]
#[lang = "f64"]
#[stable(feature = "rust1", since = "1.0.0")]
@ -1304,7 +1013,7 @@ impl f64 {
#[inline]
pub fn acosh(self) -> f64 {
match self {
x if x < 1.0 => Float::nan(),
x if x < 1.0 => num::Float::nan(),
x => (x + ((x * x) - 1.0).sqrt()).ln(),
}
}
@ -1328,114 +1037,6 @@ impl f64 {
}
}
//
// Section: String Conversions
//
/// Converts a float to a string
///
/// # Arguments
///
/// * num - The float value
#[inline]
#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
#[deprecated(since = "1.0.0", reason = "use the ToString trait instead")]
pub fn to_string(num: f64) -> String {
let (r, _) = strconv::float_to_str_common(
num, 10, true, SignNeg, DigAll, ExpNone, false);
r
}
/// Converts a float to a string in hexadecimal format
///
/// # Arguments
///
/// * num - The float value
#[inline]
#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
#[deprecated(since = "1.0.0", reason = "use format! instead")]
pub fn to_str_hex(num: f64) -> String {
let (r, _) = strconv::float_to_str_common(
num, 16, true, SignNeg, DigAll, ExpNone, false);
r
}
/// Converts a float to a string in a given radix, and a flag indicating
/// whether it's a special value
///
/// # Arguments
///
/// * num - The float value
/// * radix - The base to use
#[inline]
#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
#[deprecated(since = "1.0.0", reason = "use format! instead")]
pub fn to_str_radix_special(num: f64, rdx: u32) -> (String, bool) {
strconv::float_to_str_common(num, rdx, true, SignNeg, DigAll, ExpNone, false)
}
/// Converts a float to a string with exactly the number of
/// provided significant digits
///
/// # Arguments
///
/// * num - The float value
/// * digits - The number of significant digits
#[inline]
#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
pub fn to_str_exact(num: f64, dig: usize) -> String {
let (r, _) = strconv::float_to_str_common(
num, 10, true, SignNeg, DigExact(dig), ExpNone, false);
r
}
/// Converts a float to a string with a maximum number of
/// significant digits
///
/// # Arguments
///
/// * num - The float value
/// * digits - The number of significant digits
#[inline]
#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
pub fn to_str_digits(num: f64, dig: usize) -> String {
let (r, _) = strconv::float_to_str_common(
num, 10, true, SignNeg, DigMax(dig), ExpNone, false);
r
}
/// Converts a float to a string using the exponential notation with exactly the number of
/// provided digits after the decimal point in the significand
///
/// # Arguments
///
/// * num - The float value
/// * digits - The number of digits after the decimal point
/// * upper - Use `E` instead of `e` for the exponent sign
#[inline]
#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
pub fn to_str_exp_exact(num: f64, dig: usize, upper: bool) -> String {
let (r, _) = strconv::float_to_str_common(
num, 10, true, SignNeg, DigExact(dig), ExpDec, upper);
r
}
/// Converts a float to a string using the exponential notation with the maximum number of
/// digits after the decimal point in the significand
///
/// # Arguments
///
/// * num - The float value
/// * digits - The number of digits after the decimal point
/// * upper - Use `E` instead of `e` for the exponent sign
#[inline]
#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
pub fn to_str_exp_digits(num: f64, dig: usize, upper: bool) -> String {
let (r, _) = strconv::float_to_str_common(
num, 10, true, SignNeg, DigMax(dig), ExpDec, upper);
r
}
#[cfg(test)]
mod tests {
use f64::*;

File diff suppressed because it is too large Load Diff

View File

@ -1,556 +0,0 @@
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(missing_docs)]
#![allow(deprecated)]
use self::ExponentFormat::*;
use self::SignificantDigits::*;
use self::SignFormat::*;
use char;
use num::{self, Int, Float, ToPrimitive};
use num::FpCategory as Fp;
use ops::FnMut;
use string::String;
use vec::Vec;
/// A flag that specifies whether to use exponential (scientific) notation.
#[derive(Copy, Clone)]
pub enum ExponentFormat {
/// Do not use exponential notation.
ExpNone,
/// Use exponential notation with the exponent having a base of 10 and the
/// exponent sign being `e` or `E`. For example, 1000 would be printed
/// 1e3.
ExpDec,
/// Use exponential notation with the exponent having a base of 2 and the
/// exponent sign being `p` or `P`. For example, 8 would be printed 1p3.
ExpBin,
}
/// The number of digits used for emitting the fractional part of a number, if
/// any.
#[derive(Copy, Clone)]
pub enum SignificantDigits {
/// All calculable digits will be printed.
///
/// Note that bignums or fractions may cause a surprisingly large number
/// of digits to be printed.
DigAll,
/// At most the given number of digits will be printed, truncating any
/// trailing zeroes.
DigMax(usize),
/// Precisely the given number of digits will be printed.
DigExact(usize)
}
/// How to emit the sign of a number.
#[derive(Copy, Clone)]
pub enum SignFormat {
/// No sign will be printed. The exponent sign will also be emitted.
SignNone,
/// `-` will be printed for negative values, but no sign will be emitted
/// for positive numbers.
SignNeg,
/// `+` will be printed for positive values, and `-` will be printed for
/// negative values.
SignAll,
}
/// Converts an integral number to its string representation as a byte vector.
/// This is meant to be a common base implementation for all integral string
/// conversion functions like `to_string()` or `to_str_radix()`.
///
/// # Arguments
///
/// - `num` - The number to convert. Accepts any number that
/// implements the numeric traits.
/// - `radix` - Base to use. Accepts only the values 2-36.
/// - `sign` - How to emit the sign. Options are:
/// - `SignNone`: No sign at all. Basically emits `abs(num)`.
/// - `SignNeg`: Only `-` on negative values.
/// - `SignAll`: Both `+` on positive, and `-` on negative numbers.
/// - `f` - a callback which will be invoked for each ascii character
/// which composes the string representation of this integer
///
/// # Panics
///
/// - Panics if `radix` < 2 or `radix` > 36.
fn int_to_str_bytes_common<T, F>(num: T, radix: usize, sign: SignFormat, mut f: F) where
T: Int,
F: FnMut(u8),
{
assert!(2 <= radix && radix <= 36);
let _0: T = Int::zero();
let neg = num < _0;
let radix_gen: T = num::cast(radix).unwrap();
let mut deccum = num;
// This is just for integral types, the largest of which is a u64. The
// smallest base that we can have is 2, so the most number of digits we're
// ever going to have is 64
let mut buf = [0; 64];
let mut cur = 0;
// Loop at least once to make sure at least a `0` gets emitted.
loop {
// Calculate the absolute value of each digit instead of only
// doing it once for the whole number because a
// representable negative number doesn't necessary have an
// representable additive inverse of the same type
// (See twos complement). But we assume that for the
// numbers [-35 .. 0] we always have [0 .. 35].
let current_digit_signed = deccum % radix_gen;
let current_digit = if current_digit_signed < _0 {
_0 - current_digit_signed
} else {
current_digit_signed
};
buf[cur] = match current_digit.to_u8().unwrap() {
i @ 0...9 => b'0' + i,
i => b'a' + (i - 10),
};
cur += 1;
deccum = deccum / radix_gen;
// No more digits to calculate for the non-fractional part -> break
if deccum == _0 { break; }
}
// Decide what sign to put in front
match sign {
SignNeg | SignAll if neg => { f(b'-'); }
SignAll => { f(b'+'); }
_ => ()
}
// We built the number in reverse order, so un-reverse it here
while cur > 0 {
cur -= 1;
f(buf[cur]);
}
}
/// Converts a number to its string representation as a byte vector.
/// This is meant to be a common base implementation for all numeric string
/// conversion functions like `to_string()` or `to_str_radix()`.
///
/// # Arguments
///
/// - `num` - The number to convert. Accepts any number that
/// implements the numeric traits.
/// - `radix` - Base to use. Accepts only the values 2-36. If the exponential notation
/// is used, then this base is only used for the significand. The exponent
/// itself always printed using a base of 10.
/// - `negative_zero` - Whether to treat the special value `-0` as
/// `-0` or as `+0`.
/// - `sign` - How to emit the sign. See `SignFormat`.
/// - `digits` - The amount of digits to use for emitting the fractional
/// part, if any. See `SignificantDigits`.
/// - `exp_format` - Whether or not to use the exponential (scientific) notation.
/// See `ExponentFormat`.
/// - `exp_capital` - Whether or not to use a capital letter for the exponent sign, if
/// exponential notation is desired.
///
/// # Return value
///
/// A tuple containing the byte vector, and a boolean flag indicating
/// whether it represents a special value like `inf`, `-inf`, `NaN` or not.
/// It returns a tuple because there can be ambiguity between a special value
/// and a number representation at higher bases.
///
/// # Panics
///
/// - Panics if `radix` < 2 or `radix` > 36.
/// - Panics if `radix` > 14 and `exp_format` is `ExpDec` due to conflict
/// between digit and exponent sign `'e'`.
/// - Panics if `radix` > 25 and `exp_format` is `ExpBin` due to conflict
/// between digit and exponent sign `'p'`.
pub fn float_to_str_bytes_common<T: Float>(
num: T, radix: u32, negative_zero: bool,
sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_upper: bool
) -> (Vec<u8>, bool) {
assert!(2 <= radix && radix <= 36);
match exp_format {
ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e'
=> panic!("float_to_str_bytes_common: radix {} incompatible with \
use of 'e' as decimal exponent", radix),
ExpBin if radix >= DIGIT_P_RADIX // binary exponent 'p'
=> panic!("float_to_str_bytes_common: radix {} incompatible with \
use of 'p' as binary exponent", radix),
_ => ()
}
let _0: T = Float::zero();
let _1: T = Float::one();
match num.classify() {
Fp::Nan => { return (b"NaN".to_vec(), true); }
Fp::Infinite if num > _0 => {
return match sign {
SignAll => (b"+inf".to_vec(), true),
_ => (b"inf".to_vec(), true)
};
}
Fp::Infinite if num < _0 => {
return match sign {
SignNone => (b"inf".to_vec(), true),
_ => (b"-inf".to_vec(), true),
};
}
_ => {}
}
let neg = num < _0 || (negative_zero && _1 / num == Float::neg_infinity());
let mut buf = Vec::new();
let radix_gen: T = num::cast(radix as isize).unwrap();
let (num, exp) = match exp_format {
ExpNone => (num, 0),
ExpDec | ExpBin => {
if num == _0 {
(num, 0)
} else {
let (exp, exp_base) = match exp_format {
ExpDec => (num.abs().log10().floor(), num::cast::<f64, T>(10.0f64).unwrap()),
ExpBin => (num.abs().log2().floor(), num::cast::<f64, T>(2.0f64).unwrap()),
ExpNone => unreachable!()
};
(num / exp_base.powf(exp), num::cast::<T, i32>(exp).unwrap())
}
}
};
// First emit the non-fractional part, looping at least once to make
// sure at least a `0` gets emitted.
let mut deccum = num.trunc();
loop {
// Calculate the absolute value of each digit instead of only
// doing it once for the whole number because a
// representable negative number doesn't necessary have an
// representable additive inverse of the same type
// (See twos complement). But we assume that for the
// numbers [-35 .. 0] we always have [0 .. 35].
let current_digit = (deccum % radix_gen).abs();
// Decrease the deccumulator one digit at a time
deccum = deccum / radix_gen;
deccum = deccum.trunc();
buf.push(char::from_digit(current_digit.to_isize().unwrap() as u32, radix)
.unwrap() as u8);
// No more digits to calculate for the non-fractional part -> break
if deccum == _0 { break; }
}
// If limited digits, calculate one digit more for rounding.
let (limit_digits, digit_count, exact) = match digits {
DigAll => (false, 0, false),
DigMax(count) => (true, count+1, false),
DigExact(count) => (true, count+1, true)
};
// Decide what sign to put in front
match sign {
SignNeg | SignAll if neg => {
buf.push(b'-');
}
SignAll => {
buf.push(b'+');
}
_ => ()
}
buf.reverse();
// Remember start of the fractional digits.
// Points one beyond end of buf if none get generated,
// or at the '.' otherwise.
let start_fractional_digits = buf.len();
// Now emit the fractional part, if any
deccum = num.fract();
if deccum != _0 || (limit_digits && exact && digit_count > 0) {
buf.push(b'.');
let mut dig = 0;
// calculate new digits while
// - there is no limit and there are digits left
// - or there is a limit, it's not reached yet and
// - it's exact
// - or it's a maximum, and there are still digits left
while (!limit_digits && deccum != _0)
|| (limit_digits && dig < digit_count && (
exact
|| (!exact && deccum != _0)
)
) {
// Shift first fractional digit into the integer part
deccum = deccum * radix_gen;
// Calculate the absolute value of each digit.
// See note in first loop.
let current_digit = deccum.trunc().abs();
buf.push(char::from_digit(
current_digit.to_isize().unwrap() as u32, radix).unwrap() as u8);
// Decrease the deccumulator one fractional digit at a time
deccum = deccum.fract();
dig += 1;
}
// If digits are limited, and that limit has been reached,
// cut off the one extra digit, and depending on its value
// round the remaining ones.
if limit_digits && dig == digit_count {
let ascii2value = |chr: u8| {
(chr as char).to_digit(radix).unwrap()
};
let value2ascii = |val: u32| {
char::from_digit(val, radix).unwrap() as u8
};
let extra_digit = ascii2value(buf.pop().unwrap());
if extra_digit >= radix / 2 { // -> need to round
let mut i: isize = buf.len() as isize - 1;
loop {
// If reached left end of number, have to
// insert additional digit:
if i < 0
|| buf[i as usize] == b'-'
|| buf[i as usize] == b'+' {
buf.insert((i + 1) as usize, value2ascii(1));
break;
}
// Skip the '.'
if buf[i as usize] == b'.' { i -= 1; continue; }
// Either increment the digit,
// or set to 0 if max and carry the 1.
let current_digit = ascii2value(buf[i as usize]);
if current_digit < (radix - 1) {
buf[i as usize] = value2ascii(current_digit+1);
break;
} else {
buf[i as usize] = value2ascii(0);
i -= 1;
}
}
}
}
}
// if number of digits is not exact, remove all trailing '0's up to
// and including the '.'
if !exact {
let buf_max_i = buf.len() - 1;
// index to truncate from
let mut i = buf_max_i;
// discover trailing zeros of fractional part
while i > start_fractional_digits && buf[i] == b'0' {
i -= 1;
}
// Only attempt to truncate digits if buf has fractional digits
if i >= start_fractional_digits {
// If buf ends with '.', cut that too.
if buf[i] == b'.' { i -= 1 }
// only resize buf if we actually remove digits
if i < buf_max_i {
buf = buf[.. (i + 1)].to_vec();
}
}
} // If exact and trailing '.', just cut that
else {
let max_i = buf.len() - 1;
if buf[max_i] == b'.' {
buf = buf[.. max_i].to_vec();
}
}
match exp_format {
ExpNone => (),
_ => {
buf.push(match exp_format {
ExpDec if exp_upper => 'E',
ExpDec if !exp_upper => 'e',
ExpBin if exp_upper => 'P',
ExpBin if !exp_upper => 'p',
_ => unreachable!()
} as u8);
int_to_str_bytes_common(exp, 10, sign, |c| buf.push(c));
}
}
(buf, false)
}
/// Converts a number to its string representation. This is a wrapper for
/// `to_str_bytes_common()`, for details see there.
#[inline]
pub fn float_to_str_common<T: Float>(
num: T, radix: u32, negative_zero: bool,
sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_capital: bool
) -> (String, bool) {
let (bytes, special) = float_to_str_bytes_common(num, radix,
negative_zero, sign, digits, exp_format, exp_capital);
(String::from_utf8(bytes).unwrap(), special)
}
// Some constants for from_str_bytes_common's input validation,
// they define minimum radix values for which the character is a valid digit.
const DIGIT_P_RADIX: u32 = ('p' as u32) - ('a' as u32) + 11;
const DIGIT_E_RADIX: u32 = ('e' as u32) - ('a' as u32) + 11;
#[cfg(test)]
mod tests {
use core::num::wrapping::WrappingOps;
use string::ToString;
#[test]
fn test_int_to_str_overflow() {
let mut i8_val: i8 = 127;
assert_eq!(i8_val.to_string(), "127");
i8_val = i8_val.wrapping_add(1);
assert_eq!(i8_val.to_string(), "-128");
let mut i16_val: i16 = 32_767;
assert_eq!(i16_val.to_string(), "32767");
i16_val = i16_val.wrapping_add(1);
assert_eq!(i16_val.to_string(), "-32768");
let mut i32_val: i32 = 2_147_483_647;
assert_eq!(i32_val.to_string(), "2147483647");
i32_val = i32_val.wrapping_add(1);
assert_eq!(i32_val.to_string(), "-2147483648");
let mut i64_val: i64 = 9_223_372_036_854_775_807;
assert_eq!(i64_val.to_string(), "9223372036854775807");
i64_val = i64_val.wrapping_add(1);
assert_eq!(i64_val.to_string(), "-9223372036854775808");
}
}
#[cfg(test)]
mod bench {
#![allow(deprecated)] // rand
extern crate test;
mod usize {
use super::test::Bencher;
use rand::{thread_rng, Rng};
use std::fmt;
#[inline]
fn to_string(x: usize, base: u8) {
format!("{}", fmt::radix(x, base));
}
#[bench]
fn to_str_bin(b: &mut Bencher) {
let mut rng = thread_rng();
b.iter(|| { to_string(rng.gen::<usize>(), 2); })
}
#[bench]
fn to_str_oct(b: &mut Bencher) {
let mut rng = thread_rng();
b.iter(|| { to_string(rng.gen::<usize>(), 8); })
}
#[bench]
fn to_str_dec(b: &mut Bencher) {
let mut rng = thread_rng();
b.iter(|| { to_string(rng.gen::<usize>(), 10); })
}
#[bench]
fn to_str_hex(b: &mut Bencher) {
let mut rng = thread_rng();
b.iter(|| { to_string(rng.gen::<usize>(), 16); })
}
#[bench]
fn to_str_base_36(b: &mut Bencher) {
let mut rng = thread_rng();
b.iter(|| { to_string(rng.gen::<usize>(), 36); })
}
}
mod isize {
use super::test::Bencher;
use rand::{thread_rng, Rng};
use std::fmt;
#[inline]
fn to_string(x: isize, base: u8) {
format!("{}", fmt::radix(x, base));
}
#[bench]
fn to_str_bin(b: &mut Bencher) {
let mut rng = thread_rng();
b.iter(|| { to_string(rng.gen::<isize>(), 2); })
}
#[bench]
fn to_str_oct(b: &mut Bencher) {
let mut rng = thread_rng();
b.iter(|| { to_string(rng.gen::<isize>(), 8); })
}
#[bench]
fn to_str_dec(b: &mut Bencher) {
let mut rng = thread_rng();
b.iter(|| { to_string(rng.gen::<isize>(), 10); })
}
#[bench]
fn to_str_hex(b: &mut Bencher) {
let mut rng = thread_rng();
b.iter(|| { to_string(rng.gen::<isize>(), 16); })
}
#[bench]
fn to_str_base_36(b: &mut Bencher) {
let mut rng = thread_rng();
b.iter(|| { to_string(rng.gen::<isize>(), 36); })
}
}
mod f64 {
use super::test::Bencher;
use rand::{thread_rng, Rng};
use f64;
#[bench]
fn float_to_string(b: &mut Bencher) {
let mut rng = thread_rng();
b.iter(|| { f64::to_string(rng.gen()); })
}
}
}

View File

@ -110,7 +110,7 @@ use string::String;
use vec::Vec;
use fmt;
use ffi::{OsStr, OsString, AsOsStr};
use ffi::{OsStr, OsString};
use self::platform::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix};

View File

@ -161,14 +161,6 @@ impl Condvar {
}
}
/// Deprecated: use `wait_timeout_ms` instead.
#[unstable(feature = "std_misc")]
#[deprecated(since = "1.0.0", reason = "use wait_timeout_ms instead")]
pub fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>, dur: Duration)
-> LockResult<(MutexGuard<'a, T>, bool)> {
self.wait_timeout_ms(guard, dur.num_milliseconds() as u32)
}
/// Waits on this condition variable for a notification, timing out after a
/// specified duration.
///

View File

@ -1,971 +0,0 @@
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(deprecated)]
use prelude::v1::*;
use self::SocketStatus::*;
use self::InAddr::*;
use ffi::{CString, CStr};
use old_io::net::addrinfo;
use old_io::net::ip::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr};
use old_io::{IoResult, IoError};
use libc::{self, c_char, c_int};
use mem;
use num::Int;
use ptr::{self, null, null_mut};
use str;
use sys::{self, retry, c, sock_t, last_error, last_net_error, last_gai_error, close_sock,
wrlen, msglen_t, os, wouldblock, set_nonblocking, timer, ms_to_timeval,
decode_error_detailed};
use sync::{Arc, Mutex};
#[cfg(not(target_os = "linux"))]
use sync::MutexGuard;
use sys_common::{self, keep_going, short_write, timeout};
use cmp;
use old_io;
// FIXME: move uses of Arc and deadline tracking to std::io
#[derive(Debug)]
pub enum SocketStatus {
Readable,
Writable,
}
////////////////////////////////////////////////////////////////////////////////
// sockaddr and misc bindings
////////////////////////////////////////////////////////////////////////////////
pub fn htons(u: u16) -> u16 {
u.to_be()
}
pub fn ntohs(u: u16) -> u16 {
Int::from_be(u)
}
pub enum InAddr {
In4Addr(libc::in_addr),
In6Addr(libc::in6_addr),
}
pub fn ip_to_inaddr(ip: IpAddr) -> InAddr {
match ip {
Ipv4Addr(a, b, c, d) => {
let ip = ((a as u32) << 24) |
((b as u32) << 16) |
((c as u32) << 8) |
((d as u32) << 0);
In4Addr(libc::in_addr {
s_addr: Int::from_be(ip)
})
}
Ipv6Addr(a, b, c, d, e, f, g, h) => {
In6Addr(libc::in6_addr {
s6_addr: [
htons(a),
htons(b),
htons(c),
htons(d),
htons(e),
htons(f),
htons(g),
htons(h),
]
})
}
}
}
pub fn addr_to_sockaddr(addr: SocketAddr,
storage: &mut libc::sockaddr_storage)
-> libc::socklen_t {
unsafe {
let len = match ip_to_inaddr(addr.ip) {
In4Addr(inaddr) => {
let storage = storage as *mut _ as *mut libc::sockaddr_in;
(*storage).sin_family = libc::AF_INET as libc::sa_family_t;
(*storage).sin_port = htons(addr.port);
(*storage).sin_addr = inaddr;
mem::size_of::<libc::sockaddr_in>()
}
In6Addr(inaddr) => {
let storage = storage as *mut _ as *mut libc::sockaddr_in6;
(*storage).sin6_family = libc::AF_INET6 as libc::sa_family_t;
(*storage).sin6_port = htons(addr.port);
(*storage).sin6_addr = inaddr;
mem::size_of::<libc::sockaddr_in6>()
}
};
return len as libc::socklen_t;
}
}
pub fn socket(addr: SocketAddr, ty: libc::c_int) -> IoResult<sock_t> {
unsafe {
let fam = match addr.ip {
Ipv4Addr(..) => libc::AF_INET,
Ipv6Addr(..) => libc::AF_INET6,
};
match libc::socket(fam, ty, 0) as i32 {
-1 => Err(last_net_error()),
fd => Ok(fd as sock_t),
}
}
}
pub fn setsockopt<T>(fd: sock_t, opt: libc::c_int, val: libc::c_int,
payload: T) -> IoResult<()> {
unsafe {
let payload = &payload as *const T as *const libc::c_void;
let ret = libc::setsockopt(fd, opt, val,
payload,
mem::size_of::<T>() as libc::socklen_t);
if ret != 0 {
Err(last_net_error())
} else {
Ok(())
}
}
}
pub fn getsockopt<T: Copy>(fd: sock_t, opt: libc::c_int,
val: libc::c_int) -> IoResult<T> {
unsafe {
let mut slot: T = mem::zeroed();
let mut len = mem::size_of::<T>() as libc::socklen_t;
let ret = c::getsockopt(fd, opt, val,
&mut slot as *mut _ as *mut _,
&mut len);
if ret != 0 {
Err(last_net_error())
} else {
assert!(len as usize == mem::size_of::<T>());
Ok(slot)
}
}
}
pub fn sockname(fd: sock_t,
f: unsafe extern "system" fn(sock_t, *mut libc::sockaddr,
*mut libc::socklen_t) -> libc::c_int)
-> IoResult<SocketAddr>
{
let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
let mut len = mem::size_of::<libc::sockaddr_storage>() as libc::socklen_t;
unsafe {
let storage = &mut storage as *mut libc::sockaddr_storage;
let ret = f(fd,
storage as *mut libc::sockaddr,
&mut len as *mut libc::socklen_t);
if ret != 0 {
return Err(last_net_error())
}
}
return sockaddr_to_addr(&storage, len as usize);
}
pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage,
len: usize) -> IoResult<SocketAddr> {
match storage.ss_family as libc::c_int {
libc::AF_INET => {
assert!(len as usize >= mem::size_of::<libc::sockaddr_in>());
let storage: &libc::sockaddr_in = unsafe {
mem::transmute(storage)
};
let ip = (storage.sin_addr.s_addr as u32).to_be();
let a = (ip >> 24) as u8;
let b = (ip >> 16) as u8;
let c = (ip >> 8) as u8;
let d = (ip >> 0) as u8;
Ok(SocketAddr {
ip: Ipv4Addr(a, b, c, d),
port: ntohs(storage.sin_port),
})
}
libc::AF_INET6 => {
assert!(len as usize >= mem::size_of::<libc::sockaddr_in6>());
let storage: &libc::sockaddr_in6 = unsafe {
mem::transmute(storage)
};
let a = ntohs(storage.sin6_addr.s6_addr[0]);
let b = ntohs(storage.sin6_addr.s6_addr[1]);
let c = ntohs(storage.sin6_addr.s6_addr[2]);
let d = ntohs(storage.sin6_addr.s6_addr[3]);
let e = ntohs(storage.sin6_addr.s6_addr[4]);
let f = ntohs(storage.sin6_addr.s6_addr[5]);
let g = ntohs(storage.sin6_addr.s6_addr[6]);
let h = ntohs(storage.sin6_addr.s6_addr[7]);
Ok(SocketAddr {
ip: Ipv6Addr(a, b, c, d, e, f, g, h),
port: ntohs(storage.sin6_port),
})
}
_ => {
Err(IoError {
kind: old_io::InvalidInput,
desc: "invalid argument",
detail: None,
})
}
}
}
////////////////////////////////////////////////////////////////////////////////
// get_host_addresses
////////////////////////////////////////////////////////////////////////////////
extern "system" {
fn getaddrinfo(node: *const c_char, service: *const c_char,
hints: *const libc::addrinfo,
res: *mut *mut libc::addrinfo) -> c_int;
fn freeaddrinfo(res: *mut libc::addrinfo);
}
pub fn get_host_addresses(host: Option<&str>, servname: Option<&str>,
hint: Option<addrinfo::Hint>)
-> Result<Vec<addrinfo::Info>, IoError>
{
sys::init_net();
assert!(host.is_some() || servname.is_some());
let c_host = match host {
Some(x) => Some(try!(CString::new(x))),
None => None,
};
let c_host = c_host.as_ref().map(|x| x.as_ptr()).unwrap_or(null());
let c_serv = match servname {
Some(x) => Some(try!(CString::new(x))),
None => None,
};
let c_serv = c_serv.as_ref().map(|x| x.as_ptr()).unwrap_or(null());
let hint = hint.map(|hint| {
libc::addrinfo {
ai_flags: hint.flags as c_int,
ai_family: hint.family as c_int,
ai_socktype: 0,
ai_protocol: 0,
ai_addrlen: 0,
ai_canonname: null_mut(),
ai_addr: null_mut(),
ai_next: null_mut()
}
});
let hint_ptr = hint.as_ref().map_or(null(), |x| {
x as *const libc::addrinfo
});
let mut res = null_mut();
// Make the call
let s = unsafe {
getaddrinfo(c_host, c_serv, hint_ptr, &mut res)
};
// Error?
if s != 0 {
return Err(last_gai_error(s));
}
// Collect all the results we found
let mut addrs = Vec::new();
let mut rp = res;
while !rp.is_null() {
unsafe {
let addr = try!(sockaddr_to_addr(mem::transmute((*rp).ai_addr),
(*rp).ai_addrlen as usize));
addrs.push(addrinfo::Info {
address: addr,
family: (*rp).ai_family as usize,
socktype: None,
protocol: None,
flags: (*rp).ai_flags as usize
});
rp = (*rp).ai_next as *mut libc::addrinfo;
}
}
unsafe { freeaddrinfo(res); }
Ok(addrs)
}
////////////////////////////////////////////////////////////////////////////////
// get_address_name
////////////////////////////////////////////////////////////////////////////////
extern "system" {
fn getnameinfo(sa: *const libc::sockaddr, salen: libc::socklen_t,
host: *mut c_char, hostlen: libc::size_t,
serv: *mut c_char, servlen: libc::size_t,
flags: c_int) -> c_int;
}
const NI_MAXHOST: usize = 1025;
pub fn get_address_name(addr: IpAddr) -> Result<String, IoError> {
let addr = SocketAddr{ip: addr, port: 0};
let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
let len = addr_to_sockaddr(addr, &mut storage);
let mut hostbuf = [0 as c_char; NI_MAXHOST];
let res = unsafe {
getnameinfo(&storage as *const _ as *const libc::sockaddr, len,
hostbuf.as_mut_ptr(), NI_MAXHOST as libc::size_t,
ptr::null_mut(), 0,
0)
};
if res != 0 {
return Err(last_gai_error(res));
}
unsafe {
let data = CStr::from_ptr(hostbuf.as_ptr());
Ok(str::from_utf8(data.to_bytes()).unwrap().to_string())
}
}
////////////////////////////////////////////////////////////////////////////////
// Timeout helpers
//
// The read/write functions below are the helpers for reading/writing a socket
// with a possible deadline specified. This is generally viewed as a timed out
// I/O operation.
//
// From the application's perspective, timeouts apply to the I/O object, not to
// the underlying file descriptor (it's one timeout per object). This means that
// we can't use the SO_RCVTIMEO and corresponding send timeout option.
//
// The next idea to implement timeouts would be to use nonblocking I/O. An
// invocation of select() would wait (with a timeout) for a socket to be ready.
// Once its ready, we can perform the operation. Note that the operation *must*
// be nonblocking, even though select() says the socket is ready. This is
// because some other thread could have come and stolen our data (handles can be
// cloned).
//
// To implement nonblocking I/O, the first option we have is to use the
// O_NONBLOCK flag. Remember though that this is a global setting, affecting all
// I/O objects, so this was initially viewed as unwise.
//
// It turns out that there's this nifty MSG_DONTWAIT flag which can be passed to
// send/recv, but the niftiness wears off once you realize it only works well on
// Linux [1] [2]. This means that it's pretty easy to get a nonblocking
// operation on Linux (no flag fiddling, no affecting other objects), but not on
// other platforms.
//
// To work around this constraint on other platforms, we end up using the
// original strategy of flipping the O_NONBLOCK flag. As mentioned before, this
// could cause other objects' blocking operations to suddenly become
// nonblocking. To get around this, a "blocking operation" which returns EAGAIN
// falls back to using the same code path as nonblocking operations, but with an
// infinite timeout (select + send/recv). This helps emulate blocking
// reads/writes despite the underlying descriptor being nonblocking, as well as
// optimizing the fast path of just hitting one syscall in the good case.
//
// As a final caveat, this implementation uses a mutex so only one thread is
// doing a nonblocking operation at at time. This is the operation that comes
// after the select() (at which point we think the socket is ready). This is
// done for sanity to ensure that the state of the O_NONBLOCK flag is what we
// expect (wouldn't want someone turning it on when it should be off!). All
// operations performed in the lock are *nonblocking* to avoid holding the mutex
// forever.
//
// So, in summary, Linux uses MSG_DONTWAIT and doesn't need mutexes, everyone
// else uses O_NONBLOCK and mutexes with some trickery to make sure blocking
// reads/writes are still blocking.
//
// Fun, fun!
//
// [1] http://twistedmatrix.com/pipermail/twisted-commits/2012-April/034692.html
// [2] http://stackoverflow.com/questions/19819198/does-send-msg-dontwait
pub fn read<T, L, R>(fd: sock_t, deadline: u64, mut lock: L, mut read: R) -> IoResult<usize> where
L: FnMut() -> T,
R: FnMut(bool) -> libc::c_int,
{
let mut ret = -1;
if deadline == 0 {
ret = retry(|| read(false));
}
if deadline != 0 || (ret == -1 && wouldblock()) {
let deadline = match deadline {
0 => None,
n => Some(n),
};
loop {
// With a timeout, first we wait for the socket to become
// readable using select(), specifying the relevant timeout for
// our previously set deadline.
try!(await(&[fd], deadline, Readable));
// At this point, we're still within the timeout, and we've
// determined that the socket is readable (as returned by
// select). We must still read the socket in *nonblocking* mode
// because some other thread could come steal our data. If we
// fail to read some data, we retry (hence the outer loop) and
// wait for the socket to become readable again.
let _guard = lock();
match retry(|| read(deadline.is_some())) {
-1 if wouldblock() => {}
-1 => return Err(last_net_error()),
n => { ret = n; break }
}
}
}
match ret {
0 => Err(sys_common::eof()),
n if n < 0 => Err(last_net_error()),
n => Ok(n as usize)
}
}
pub fn write<T, L, W>(fd: sock_t,
deadline: u64,
buf: &[u8],
write_everything: bool,
mut lock: L,
mut write: W) -> IoResult<usize> where
L: FnMut() -> T,
W: FnMut(bool, *const u8, usize) -> i64,
{
let mut ret = -1;
let mut written = 0;
if deadline == 0 {
if write_everything {
ret = keep_going(buf, |inner, len| {
written = buf.len() - len;
write(false, inner, len)
});
} else {
ret = retry(|| { write(false, buf.as_ptr(), buf.len()) });
if ret > 0 { written = ret as usize; }
}
}
if deadline != 0 || (ret == -1 && wouldblock()) {
let deadline = match deadline {
0 => None,
n => Some(n),
};
while written < buf.len() && (write_everything || written == 0) {
// As with read(), first wait for the socket to be ready for
// the I/O operation.
match await(&[fd], deadline, Writable) {
Err(ref e) if e.kind == old_io::EndOfFile && written > 0 => {
assert!(deadline.is_some());
return Err(short_write(written, "short write"))
}
Err(e) => return Err(e),
Ok(()) => {}
}
// Also as with read(), we use MSG_DONTWAIT to guard ourselves
// against unforeseen circumstances.
let _guard = lock();
let ptr = buf[written..].as_ptr();
let len = buf.len() - written;
match retry(|| write(deadline.is_some(), ptr, len)) {
-1 if wouldblock() => {}
-1 => return Err(last_net_error()),
n => { written += n as usize; }
}
}
ret = 0;
}
if ret < 0 {
Err(last_net_error())
} else {
Ok(written)
}
}
// See http://developerweb.net/viewtopic.php?id=3196 for where this is
// derived from.
pub fn connect_timeout(fd: sock_t,
addrp: *const libc::sockaddr,
len: libc::socklen_t,
timeout_ms: u64) -> IoResult<()> {
#[cfg(unix)] use libc::EINPROGRESS as INPROGRESS;
#[cfg(windows)] use libc::WSAEINPROGRESS as INPROGRESS;
#[cfg(unix)] use libc::EWOULDBLOCK as WOULDBLOCK;
#[cfg(windows)] use libc::WSAEWOULDBLOCK as WOULDBLOCK;
// Make sure the call to connect() doesn't block
set_nonblocking(fd, true);
let ret = match unsafe { libc::connect(fd, addrp, len) } {
// If the connection is in progress, then we need to wait for it to
// finish (with a timeout). The current strategy for doing this is
// to use select() with a timeout.
-1 if os::errno() as isize == INPROGRESS as isize ||
os::errno() as isize == WOULDBLOCK as isize => {
let mut set: c::fd_set = unsafe { mem::zeroed() };
c::fd_set(&mut set, fd);
match await(fd, &mut set, timeout_ms) {
0 => Err(timeout("connection timed out")),
-1 => Err(last_net_error()),
_ => {
let err: libc::c_int = try!(
getsockopt(fd, libc::SOL_SOCKET, libc::SO_ERROR));
if err == 0 {
Ok(())
} else {
Err(decode_error_detailed(err))
}
}
}
}
-1 => Err(last_net_error()),
_ => Ok(()),
};
// be sure to turn blocking I/O back on
set_nonblocking(fd, false);
return ret;
#[cfg(unix)]
fn await(fd: sock_t, set: &mut c::fd_set, timeout: u64) -> libc::c_int {
let start = timer::now();
retry(|| unsafe {
// Recalculate the timeout each iteration (it is generally
// undefined what the value of the 'tv' is after select
// returns EINTR).
let mut tv = ms_to_timeval(timeout - (timer::now() - start));
c::select(fd + 1, ptr::null_mut(), set as *mut _,
ptr::null_mut(), &mut tv)
})
}
#[cfg(windows)]
fn await(_fd: sock_t, set: &mut c::fd_set, timeout: u64) -> libc::c_int {
let mut tv = ms_to_timeval(timeout);
unsafe { c::select(1, ptr::null_mut(), set, ptr::null_mut(), &mut tv) }
}
}
pub fn await(fds: &[sock_t], deadline: Option<u64>,
status: SocketStatus) -> IoResult<()> {
let mut set: c::fd_set = unsafe { mem::zeroed() };
let mut max = 0;
for &fd in fds {
c::fd_set(&mut set, fd);
max = cmp::max(max, fd + 1);
}
if cfg!(windows) {
max = fds.len() as sock_t;
}
let (read, write) = match status {
Readable => (&mut set as *mut _, ptr::null_mut()),
Writable => (ptr::null_mut(), &mut set as *mut _),
};
let mut tv: libc::timeval = unsafe { mem::zeroed() };
match retry(|| {
let now = timer::now();
let tvp = match deadline {
None => ptr::null_mut(),
Some(deadline) => {
// If we're past the deadline, then pass a 0 timeout to
// select() so we can poll the status
let ms = if deadline < now {0} else {deadline - now};
tv = ms_to_timeval(ms);
&mut tv as *mut _
}
};
let r = unsafe {
c::select(max as libc::c_int, read, write, ptr::null_mut(), tvp)
};
r
}) {
-1 => Err(last_net_error()),
0 => Err(timeout("timed out")),
_ => Ok(()),
}
}
////////////////////////////////////////////////////////////////////////////////
// Basic socket representation
////////////////////////////////////////////////////////////////////////////////
struct Inner {
fd: sock_t,
// Unused on Linux, where this lock is not necessary.
#[allow(dead_code)]
lock: Mutex<()>,
}
impl Inner {
fn new(fd: sock_t) -> Inner {
Inner { fd: fd, lock: Mutex::new(()) }
}
}
impl Drop for Inner {
fn drop(&mut self) { unsafe { close_sock(self.fd); } }
}
#[cfg(not(target_os = "linux"))]
pub struct Guard<'a> {
pub fd: sock_t,
pub guard: MutexGuard<'a, ()>,
}
#[cfg(not(target_os = "linux"))]
#[unsafe_destructor]
impl<'a> Drop for Guard<'a> {
fn drop(&mut self) {
set_nonblocking(self.fd, false);
}
}
////////////////////////////////////////////////////////////////////////////////
// TCP streams
////////////////////////////////////////////////////////////////////////////////
pub struct TcpStream {
inner: Arc<Inner>,
read_deadline: u64,
write_deadline: u64,
}
impl TcpStream {
pub fn connect(addr: SocketAddr, timeout: Option<u64>) -> IoResult<TcpStream> {
sys::init_net();
let fd = try!(socket(addr, libc::SOCK_STREAM));
let ret = TcpStream::new(fd);
let mut storage = unsafe { mem::zeroed() };
let len = addr_to_sockaddr(addr, &mut storage);
let addrp = &storage as *const _ as *const libc::sockaddr;
match timeout {
Some(timeout) => {
try!(connect_timeout(fd, addrp, len, timeout));
Ok(ret)
},
None => {
match retry(|| unsafe { libc::connect(fd, addrp, len) }) {
-1 => Err(last_error()),
_ => Ok(ret),
}
}
}
}
pub fn new(fd: sock_t) -> TcpStream {
TcpStream {
inner: Arc::new(Inner::new(fd)),
read_deadline: 0,
write_deadline: 0,
}
}
pub fn fd(&self) -> sock_t { self.inner.fd }
pub fn set_nodelay(&mut self, nodelay: bool) -> IoResult<()> {
setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_NODELAY,
nodelay as libc::c_int)
}
pub fn set_keepalive(&mut self, seconds: Option<usize>) -> IoResult<()> {
let ret = setsockopt(self.fd(), libc::SOL_SOCKET, libc::SO_KEEPALIVE,
seconds.is_some() as libc::c_int);
match seconds {
Some(n) => ret.and_then(|()| self.set_tcp_keepalive(n)),
None => ret,
}
}
#[cfg(any(target_os = "macos", target_os = "ios"))]
fn set_tcp_keepalive(&mut self, seconds: usize) -> IoResult<()> {
setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_KEEPALIVE,
seconds as libc::c_int)
}
#[cfg(any(target_os = "freebsd",
target_os = "dragonfly"))]
fn set_tcp_keepalive(&mut self, seconds: usize) -> IoResult<()> {
setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_KEEPIDLE,
seconds as libc::c_int)
}
#[cfg(target_os = "openbsd")]
fn set_tcp_keepalive(&mut self, seconds: usize) -> IoResult<()> {
setsockopt(self.fd(), libc::IPPROTO_TCP, libc::SO_KEEPALIVE,
seconds as libc::c_int)
}
#[cfg(not(any(target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly",
target_os = "openbsd")))]
fn set_tcp_keepalive(&mut self, _seconds: usize) -> IoResult<()> {
Ok(())
}
#[cfg(target_os = "linux")]
fn lock_nonblocking(&self) {}
#[cfg(not(target_os = "linux"))]
fn lock_nonblocking<'a>(&'a self) -> Guard<'a> {
let ret = Guard {
fd: self.fd(),
guard: self.inner.lock.lock().unwrap(),
};
set_nonblocking(self.fd(), true);
ret
}
pub fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
let fd = self.fd();
let dolock = || self.lock_nonblocking();
let doread = |nb| unsafe {
let flags = if nb {c::MSG_DONTWAIT} else {0};
libc::recv(fd,
buf.as_mut_ptr() as *mut libc::c_void,
buf.len() as wrlen,
flags) as libc::c_int
};
read(fd, self.read_deadline, dolock, doread)
}
pub fn write(&mut self, buf: &[u8]) -> IoResult<()> {
let fd = self.fd();
let dolock = || self.lock_nonblocking();
let dowrite = |nb: bool, buf: *const u8, len: usize| unsafe {
let flags = if nb {c::MSG_DONTWAIT} else {0};
libc::send(fd,
buf as *const _,
len as wrlen,
flags) as i64
};
write(fd, self.write_deadline, buf, true, dolock, dowrite).map(|_| ())
}
pub fn peer_name(&mut self) -> IoResult<SocketAddr> {
sockname(self.fd(), libc::getpeername)
}
pub fn close_write(&mut self) -> IoResult<()> {
super::mkerr_libc(unsafe { libc::shutdown(self.fd(), libc::SHUT_WR) })
}
pub fn close_read(&mut self) -> IoResult<()> {
super::mkerr_libc(unsafe { libc::shutdown(self.fd(), libc::SHUT_RD) })
}
pub fn set_timeout(&mut self, timeout: Option<u64>) {
let deadline = timeout.map(|a| timer::now() + a).unwrap_or(0);
self.read_deadline = deadline;
self.write_deadline = deadline;
}
pub fn set_read_timeout(&mut self, timeout: Option<u64>) {
self.read_deadline = timeout.map(|a| timer::now() + a).unwrap_or(0);
}
pub fn set_write_timeout(&mut self, timeout: Option<u64>) {
self.write_deadline = timeout.map(|a| timer::now() + a).unwrap_or(0);
}
pub fn socket_name(&mut self) -> IoResult<SocketAddr> {
sockname(self.fd(), libc::getsockname)
}
}
impl Clone for TcpStream {
fn clone(&self) -> TcpStream {
TcpStream {
inner: self.inner.clone(),
read_deadline: 0,
write_deadline: 0,
}
}
}
////////////////////////////////////////////////////////////////////////////////
// UDP
////////////////////////////////////////////////////////////////////////////////
pub struct UdpSocket {
inner: Arc<Inner>,
read_deadline: u64,
write_deadline: u64,
}
impl UdpSocket {
pub fn bind(addr: SocketAddr) -> IoResult<UdpSocket> {
sys::init_net();
let fd = try!(socket(addr, libc::SOCK_DGRAM));
let ret = UdpSocket {
inner: Arc::new(Inner::new(fd)),
read_deadline: 0,
write_deadline: 0,
};
let mut storage = unsafe { mem::zeroed() };
let len = addr_to_sockaddr(addr, &mut storage);
let addrp = &storage as *const _ as *const libc::sockaddr;
match unsafe { libc::bind(fd, addrp, len) } {
-1 => Err(last_error()),
_ => Ok(ret),
}
}
pub fn fd(&self) -> sock_t { self.inner.fd }
pub fn set_broadcast(&mut self, on: bool) -> IoResult<()> {
setsockopt(self.fd(), libc::SOL_SOCKET, libc::SO_BROADCAST,
on as libc::c_int)
}
pub fn set_multicast_loop(&mut self, on: bool) -> IoResult<()> {
setsockopt(self.fd(), libc::IPPROTO_IP, libc::IP_MULTICAST_LOOP,
on as libc::c_int)
}
pub fn set_membership(&mut self, addr: IpAddr, opt: libc::c_int) -> IoResult<()> {
match ip_to_inaddr(addr) {
In4Addr(addr) => {
let mreq = libc::ip_mreq {
imr_multiaddr: addr,
// interface == INADDR_ANY
imr_interface: libc::in_addr { s_addr: 0x0 },
};
setsockopt(self.fd(), libc::IPPROTO_IP, opt, mreq)
}
In6Addr(addr) => {
let mreq = libc::ip6_mreq {
ipv6mr_multiaddr: addr,
ipv6mr_interface: 0,
};
setsockopt(self.fd(), libc::IPPROTO_IPV6, opt, mreq)
}
}
}
#[cfg(target_os = "linux")]
fn lock_nonblocking(&self) {}
#[cfg(not(target_os = "linux"))]
fn lock_nonblocking<'a>(&'a self) -> Guard<'a> {
let ret = Guard {
fd: self.fd(),
guard: self.inner.lock.lock().unwrap(),
};
set_nonblocking(self.fd(), true);
ret
}
pub fn socket_name(&mut self) -> IoResult<SocketAddr> {
sockname(self.fd(), libc::getsockname)
}
pub fn recv_from(&mut self, buf: &mut [u8]) -> IoResult<(usize, SocketAddr)> {
let fd = self.fd();
let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
let storagep = &mut storage as *mut _ as *mut libc::sockaddr;
let mut addrlen: libc::socklen_t =
mem::size_of::<libc::sockaddr_storage>() as libc::socklen_t;
let dolock = || self.lock_nonblocking();
let n = try!(read(fd, self.read_deadline, dolock, |nb| unsafe {
let flags = if nb {c::MSG_DONTWAIT} else {0};
libc::recvfrom(fd,
buf.as_mut_ptr() as *mut libc::c_void,
buf.len() as msglen_t,
flags,
storagep,
&mut addrlen) as libc::c_int
}));
Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize).unwrap()))
}
pub fn send_to(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
let mut storage = unsafe { mem::zeroed() };
let dstlen = addr_to_sockaddr(dst, &mut storage);
let dstp = &storage as *const _ as *const libc::sockaddr;
let fd = self.fd();
let dolock = || self.lock_nonblocking();
let dowrite = |nb, buf: *const u8, len: usize| unsafe {
let flags = if nb {c::MSG_DONTWAIT} else {0};
libc::sendto(fd,
buf as *const libc::c_void,
len as msglen_t,
flags,
dstp,
dstlen) as i64
};
let n = try!(write(fd, self.write_deadline, buf, false, dolock, dowrite));
assert!(n == buf.len(), "UDP packet not completely written.");
Ok(())
}
pub fn join_multicast(&mut self, multi: IpAddr) -> IoResult<()> {
match multi {
Ipv4Addr(..) => {
self.set_membership(multi, libc::IP_ADD_MEMBERSHIP)
}
Ipv6Addr(..) => {
self.set_membership(multi, libc::IPV6_ADD_MEMBERSHIP)
}
}
}
pub fn leave_multicast(&mut self, multi: IpAddr) -> IoResult<()> {
match multi {
Ipv4Addr(..) => {
self.set_membership(multi, libc::IP_DROP_MEMBERSHIP)
}
Ipv6Addr(..) => {
self.set_membership(multi, libc::IPV6_DROP_MEMBERSHIP)
}
}
}
pub fn multicast_time_to_live(&mut self, ttl: isize) -> IoResult<()> {
setsockopt(self.fd(), libc::IPPROTO_IP, libc::IP_MULTICAST_TTL,
ttl as libc::c_int)
}
pub fn time_to_live(&mut self, ttl: isize) -> IoResult<()> {
setsockopt(self.fd(), libc::IPPROTO_IP, libc::IP_TTL, ttl as libc::c_int)
}
pub fn set_timeout(&mut self, timeout: Option<u64>) {
let deadline = timeout.map(|a| timer::now() + a).unwrap_or(0);
self.read_deadline = deadline;
self.write_deadline = deadline;
}
pub fn set_read_timeout(&mut self, timeout: Option<u64>) {
self.read_deadline = timeout.map(|a| timer::now() + a).unwrap_or(0);
}
pub fn set_write_timeout(&mut self, timeout: Option<u64>) {
self.write_deadline = timeout.map(|a| timer::now() + a).unwrap_or(0);
}
}
impl Clone for UdpSocket {
fn clone(&self) -> UdpSocket {
UdpSocket {
inner: self.inner.clone(),
read_deadline: 0,
write_deadline: 0,
}
}
}

View File

@ -37,8 +37,6 @@ use fmt;
use hash::{Hash, Hasher};
use iter::{FromIterator, IntoIterator};
use mem;
#[allow(deprecated)] // Int
use num::Int;
use ops;
use slice;
use str;

View File

@ -17,7 +17,6 @@ use sys::mutex::{self, Mutex};
use sys::time;
use sys::sync as ffi;
use time::Duration;
use num::{Int, NumCast};
pub struct Condvar { inner: UnsafeCell<ffi::pthread_cond_t> }
@ -70,8 +69,8 @@ impl Condvar {
let r = ffi::gettimeofday(&mut sys_now, ptr::null_mut());
debug_assert_eq!(r, 0);
let seconds = NumCast::from(dur.num_seconds());
let timeout = match seconds.and_then(|s| sys_now.tv_sec.checked_add(s)) {
let seconds = dur.num_seconds() as libc::time_t;
let timeout = match sys_now.tv_sec.checked_add(seconds) {
Some(sec) => {
libc::timespec {
tv_sec: sec,
@ -81,7 +80,7 @@ impl Condvar {
}
None => {
libc::timespec {
tv_sec: Int::max_value(),
tv_sec: <libc::time_t>::max_value(),
tv_nsec: 1_000_000_000 - 1,
}
}

View File

@ -15,7 +15,8 @@ use prelude::v1::*;
use io::{self, ErrorKind};
use libc;
use num::{Int, SignedInt};
use num::One;
use ops::Neg;
pub mod backtrace;
pub mod c;
@ -63,23 +64,8 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
}
}
#[inline]
#[allow(deprecated)]
pub fn retry<T, F> (mut f: F) -> T where
T: SignedInt,
F: FnMut() -> T,
{
let one: T = Int::one();
loop {
let n = f();
if n == -one && os::errno() == libc::EINTR as i32 { }
else { return n }
}
}
#[allow(deprecated)]
pub fn cvt<T: SignedInt>(t: T) -> io::Result<T> {
let one: T = Int::one();
pub fn cvt<T: One + PartialEq + Neg<Output=T>>(t: T) -> io::Result<T> {
let one: T = T::one();
if t == -one {
Err(io::Error::last_os_error())
} else {
@ -89,7 +75,7 @@ pub fn cvt<T: SignedInt>(t: T) -> io::Result<T> {
#[allow(deprecated)]
pub fn cvt_r<T, F>(mut f: F) -> io::Result<T>
where T: SignedInt, F: FnMut() -> T
where T: One + PartialEq + Neg<Output=T>, F: FnMut() -> T
{
loop {
match cvt(f()) {

View File

@ -19,7 +19,7 @@ use io::{self, Error, ErrorKind};
use libc::{self, pid_t, c_void, c_int, gid_t, uid_t};
use ptr;
use sys::pipe2::AnonPipe;
use sys::{self, retry, c, cvt};
use sys::{self, c, cvt, cvt_r};
use sys::fs2::{File, OpenOptions};
////////////////////////////////////////////////////////////////////////////////
@ -273,7 +273,7 @@ impl Process {
}
}
};
retry(|| libc::dup2(fd.raw(), dst)) != -1
cvt_r(|| libc::dup2(fd.raw(), dst)).is_ok()
};
if !setup(in_fd, libc::STDIN_FILENO) { fail(&mut output) }
@ -317,19 +317,19 @@ impl Process {
pub fn wait(&self) -> io::Result<ExitStatus> {
let mut status = 0 as c_int;
try!(cvt(retry(|| unsafe { c::waitpid(self.pid, &mut status, 0) })));
try!(cvt_r(|| unsafe { c::waitpid(self.pid, &mut status, 0) }));
Ok(translate_status(status))
}
pub fn try_wait(&self) -> Option<ExitStatus> {
let mut status = 0 as c_int;
match retry(|| unsafe {
match cvt_r(|| unsafe {
c::waitpid(self.pid, &mut status, c::WNOHANG)
}) {
n if n == self.pid => Some(translate_status(status)),
0 => None,
n => panic!("unknown waitpid error `{}`: {}", n,
io::Error::last_os_error()),
Ok(0) => None,
Ok(n) if n == self.pid => Some(translate_status(status)),
Ok(n) => panic!("unkown pid: {}", n),
Err(e) => panic!("unknown waitpid error: {}", e),
}
}
}

View File

@ -497,15 +497,6 @@ pub fn sleep_ms(ms: u32) {
imp::sleep(Duration::milliseconds(ms as i64))
}
/// Deprecated: use `sleep_ms` instead.
#[unstable(feature = "thread_sleep",
reason = "recently added, needs an RFC, and `Duration` itself is \
unstable")]
#[deprecated(since = "1.0.0", reason = "use sleep_ms instead")]
pub fn sleep(dur: Duration) {
imp::sleep(dur)
}
/// Blocks unless or until the current thread's token is made available (may wake spuriously).
///
/// See the module doc for more detail.
@ -546,13 +537,6 @@ pub fn park_timeout_ms(ms: u32) {
*guard = false;
}
/// Deprecated: use `park_timeout_ms`
#[unstable(feature = "std_misc", reason = "recently introduced, depends on Duration")]
#[deprecated(since = "1.0.0", reason = "use park_timeout_ms instead")]
pub fn park_timeout(duration: Duration) {
park_timeout_ms(duration.num_milliseconds() as u32)
}
////////////////////////////////////////////////////////////////////////////////
// Thread
////////////////////////////////////////////////////////////////////////////////

View File

@ -12,13 +12,10 @@
#![unstable(feature = "std_misc")]
use prelude::v1::*;
use {fmt, i64};
use ops::{Add, Sub, Mul, Div, Neg, FnOnce};
use option::Option;
use option::Option::{Some, None};
#[allow(deprecated)] // Int
use num::Int;
use result::Result::Ok;
use ops::{Add, Sub, Mul, Div, Neg};
/// The number of nanoseconds in a microsecond.
const NANOS_PER_MICRO: i32 = 1000;

View File

@ -66,8 +66,6 @@ use parse::lexer;
use ptr::P;
use std::fmt;
#[allow(deprecated)]
use std::num::Int;
use std::rc::Rc;
use serialize::{Encodable, Decodable, Encoder, Decoder};
@ -1142,16 +1140,24 @@ pub enum Sign {
}
impl Sign {
#[allow(deprecated)] // Int
pub fn new<T:Int>(n: T) -> Sign {
if n < Int::zero() {
Minus
} else {
Plus
}
pub fn new<T: IntSign>(n: T) -> Sign {
n.sign()
}
}
pub trait IntSign {
fn sign(&self) -> Sign;
}
macro_rules! doit {
($($t:ident)*) => ($(impl IntSign for $t {
#[allow(unused_comparisons)]
fn sign(&self) -> Sign {
if *self < 0 {Minus} else {Plus}
}
})*)
}
doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
pub enum LitIntType {
SignedIntLit(IntTy, Sign),

View File

@ -20,7 +20,6 @@
pub use self::MacroFormat::*;
use std::cell::RefCell;
use std::num::ToPrimitive;
use std::ops::{Add, Sub};
use std::rc::Rc;
@ -862,7 +861,11 @@ impl CodeMap {
pub fn record_expansion(&self, expn_info: ExpnInfo) -> ExpnId {
let mut expansions = self.expansions.borrow_mut();
expansions.push(expn_info);
ExpnId(expansions.len().to_u32().expect("too many ExpnInfo's!") - 1)
let len = expansions.len();
if len > u32::max_value() as usize {
panic!("too many ExpnInfo's!");
}
ExpnId(len as u32 - 1)
}
pub fn with_expn_info<T, F>(&self, id: ExpnId, f: F) -> T where

View File

@ -22,8 +22,6 @@ use std::cell::{Cell, RefCell};
use std::fs::File;
use std::io::Read;
use std::iter;
#[allow(deprecated)] // Int
use std::num::Int;
use std::path::{Path, PathBuf};
use std::rc::Rc;
use std::str;

View File

@ -75,7 +75,6 @@ use std::fs::File;
use std::io::prelude::*;
use std::io;
use std::iter::repeat;
use std::num::{Float, Int};
use std::path::PathBuf;
use std::sync::mpsc::{channel, Sender};
use std::sync::{Arc, Mutex};
@ -413,7 +412,7 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
#[derive(Clone, PartialEq)]
pub struct BenchSamples {
ns_iter_summ: stats::Summary<f64>,
ns_iter_summ: stats::Summary,
mb_s: usize,
}
@ -1066,7 +1065,7 @@ impl Bencher {
}
// This is a more statistics-driven benchmark algorithm
pub fn auto_bench<F>(&mut self, mut f: F) -> stats::Summary<f64> where F: FnMut(&mut Bencher) {
pub fn auto_bench<F>(&mut self, mut f: F) -> stats::Summary where F: FnMut(&mut Bencher) {
// Initial bench run to get ballpark figure.
let mut n = 1;
self.bench_n(n, |x| f(x));

View File

@ -13,9 +13,8 @@
use std::cmp::Ordering::{self, Less, Greater, Equal};
use std::mem;
use std::num::{Float, FromPrimitive};
fn local_cmp<T:Float>(x: T, y: T) -> Ordering {
fn local_cmp(x: f64, y: f64) -> Ordering {
// arbitrarily decide that NaNs are larger than everything.
if y.is_nan() {
Less
@ -30,12 +29,12 @@ fn local_cmp<T:Float>(x: T, y: T) -> Ordering {
}
}
fn local_sort<T: Float>(v: &mut [T]) {
v.sort_by(|x: &T, y: &T| local_cmp(*x, *y));
fn local_sort(v: &mut [f64]) {
v.sort_by(|x: &f64, y: &f64| local_cmp(*x, *y));
}
/// Trait that provides simple descriptive statistics on a univariate set of numeric samples.
pub trait Stats <T: Float + FromPrimitive> {
pub trait Stats {
/// Sum of the samples.
///
@ -43,24 +42,24 @@ pub trait Stats <T: Float + FromPrimitive> {
/// Depends on IEEE-754 arithmetic guarantees. See proof of correctness at:
/// ["Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric Predicates"]
/// (http://www.cs.cmu.edu/~quake-papers/robust-arithmetic.ps)
fn sum(&self) -> T;
fn sum(&self) -> f64;
/// Minimum value of the samples.
fn min(&self) -> T;
fn min(&self) -> f64;
/// Maximum value of the samples.
fn max(&self) -> T;
fn max(&self) -> f64;
/// Arithmetic mean (average) of the samples: sum divided by sample-count.
///
/// See: https://en.wikipedia.org/wiki/Arithmetic_mean
fn mean(&self) -> T;
fn mean(&self) -> f64;
/// Median of the samples: value separating the lower half of the samples from the higher half.
/// Equal to `self.percentile(50.0)`.
///
/// See: https://en.wikipedia.org/wiki/Median
fn median(&self) -> T;
fn median(&self) -> f64;
/// Variance of the samples: bias-corrected mean of the squares of the differences of each
/// sample from the sample mean. Note that this calculates the _sample variance_ rather than the
@ -69,7 +68,7 @@ pub trait Stats <T: Float + FromPrimitive> {
/// than `n`.
///
/// See: https://en.wikipedia.org/wiki/Variance
fn var(&self) -> T;
fn var(&self) -> f64;
/// Standard deviation: the square root of the sample variance.
///
@ -77,13 +76,13 @@ pub trait Stats <T: Float + FromPrimitive> {
/// `median_abs_dev` for unknown distributions.
///
/// See: https://en.wikipedia.org/wiki/Standard_deviation
fn std_dev(&self) -> T;
fn std_dev(&self) -> f64;
/// Standard deviation as a percent of the mean value. See `std_dev` and `mean`.
///
/// Note: this is not a robust statistic for non-normal distributions. Prefer the
/// `median_abs_dev_pct` for unknown distributions.
fn std_dev_pct(&self) -> T;
fn std_dev_pct(&self) -> f64;
/// Scaled median of the absolute deviations of each sample from the sample median. This is a
/// robust (distribution-agnostic) estimator of sample variability. Use this in preference to
@ -92,10 +91,10 @@ pub trait Stats <T: Float + FromPrimitive> {
/// deviation.
///
/// See: http://en.wikipedia.org/wiki/Median_absolute_deviation
fn median_abs_dev(&self) -> T;
fn median_abs_dev(&self) -> f64;
/// Median absolute deviation as a percent of the median. See `median_abs_dev` and `median`.
fn median_abs_dev_pct(&self) -> T;
fn median_abs_dev_pct(&self) -> f64;
/// Percentile: the value below which `pct` percent of the values in `self` fall. For example,
/// percentile(95.0) will return the value `v` such that 95% of the samples `s` in `self`
@ -104,7 +103,7 @@ pub trait Stats <T: Float + FromPrimitive> {
/// Calculated by linear interpolation between closest ranks.
///
/// See: http://en.wikipedia.org/wiki/Percentile
fn percentile(&self, pct: T) -> T;
fn percentile(&self, pct: f64) -> f64;
/// Quartiles of the sample: three values that divide the sample into four equal groups, each
/// with 1/4 of the data. The middle value is the median. See `median` and `percentile`. This
@ -112,36 +111,36 @@ pub trait Stats <T: Float + FromPrimitive> {
/// is otherwise equivalent.
///
/// See also: https://en.wikipedia.org/wiki/Quartile
fn quartiles(&self) -> (T,T,T);
fn quartiles(&self) -> (f64,f64,f64);
/// Inter-quartile range: the difference between the 25th percentile (1st quartile) and the 75th
/// percentile (3rd quartile). See `quartiles`.
///
/// See also: https://en.wikipedia.org/wiki/Interquartile_range
fn iqr(&self) -> T;
fn iqr(&self) -> f64;
}
/// Extracted collection of all the summary statistics of a sample set.
#[derive(Clone, PartialEq)]
#[allow(missing_docs)]
pub struct Summary<T> {
pub sum: T,
pub min: T,
pub max: T,
pub mean: T,
pub median: T,
pub var: T,
pub std_dev: T,
pub std_dev_pct: T,
pub median_abs_dev: T,
pub median_abs_dev_pct: T,
pub quartiles: (T,T,T),
pub iqr: T,
pub struct Summary {
pub sum: f64,
pub min: f64,
pub max: f64,
pub mean: f64,
pub median: f64,
pub var: f64,
pub std_dev: f64,
pub std_dev_pct: f64,
pub median_abs_dev: f64,
pub median_abs_dev_pct: f64,
pub quartiles: (f64,f64,f64),
pub iqr: f64,
}
impl<T: Float + FromPrimitive> Summary<T> {
impl Summary {
/// Construct a new summary of a sample set.
pub fn new(samples: &[T]) -> Summary<T> {
pub fn new(samples: &[f64]) -> Summary {
Summary {
sum: samples.sum(),
min: samples.min(),
@ -159,9 +158,9 @@ impl<T: Float + FromPrimitive> Summary<T> {
}
}
impl<T: Float + FromPrimitive> Stats<T> for [T] {
impl Stats for [f64] {
// FIXME #11059 handle NaN, inf and overflow
fn sum(&self) -> T {
fn sum(&self) -> f64 {
let mut partials = vec![];
for &x in self {
@ -170,7 +169,7 @@ impl<T: Float + FromPrimitive> Stats<T> for [T] {
// This inner loop applies `hi`/`lo` summation to each
// partial so that the list of partial sums remains exact.
for i in 0..partials.len() {
let mut y: T = partials[i];
let mut y: f64 = partials[i];
if x.abs() < y.abs() {
mem::swap(&mut x, &mut y);
}
@ -178,7 +177,7 @@ impl<T: Float + FromPrimitive> Stats<T> for [T] {
// `lo`. Together `hi+lo` are exactly equal to `x+y`.
let hi = x + y;
let lo = y - (hi - x);
if lo != Float::zero() {
if lo != 0.0 {
partials[j] = lo;
j += 1;
}
@ -191,35 +190,35 @@ impl<T: Float + FromPrimitive> Stats<T> for [T] {
partials.truncate(j+1);
}
}
let zero: T = Float::zero();
let zero: f64 = 0.0;
partials.iter().fold(zero, |p, q| p + *q)
}
fn min(&self) -> T {
fn min(&self) -> f64 {
assert!(!self.is_empty());
self.iter().fold(self[0], |p, q| p.min(*q))
}
fn max(&self) -> T {
fn max(&self) -> f64 {
assert!(!self.is_empty());
self.iter().fold(self[0], |p, q| p.max(*q))
}
fn mean(&self) -> T {
fn mean(&self) -> f64 {
assert!(!self.is_empty());
self.sum() / FromPrimitive::from_usize(self.len()).unwrap()
self.sum() / (self.len() as f64)
}
fn median(&self) -> T {
self.percentile(FromPrimitive::from_usize(50).unwrap())
fn median(&self) -> f64 {
self.percentile(50 as f64)
}
fn var(&self) -> T {
fn var(&self) -> f64 {
if self.len() < 2 {
Float::zero()
0.0
} else {
let mean = self.mean();
let mut v: T = Float::zero();
let mut v: f64 = 0.0;
for s in self {
let x = *s - mean;
v = v + x*x;
@ -227,53 +226,53 @@ impl<T: Float + FromPrimitive> Stats<T> for [T] {
// NB: this is _supposed to be_ len-1, not len. If you
// change it back to len, you will be calculating a
// population variance, not a sample variance.
let denom = FromPrimitive::from_usize(self.len()-1).unwrap();
let denom = (self.len() - 1) as f64;
v/denom
}
}
fn std_dev(&self) -> T {
fn std_dev(&self) -> f64 {
self.var().sqrt()
}
fn std_dev_pct(&self) -> T {
let hundred = FromPrimitive::from_usize(100).unwrap();
fn std_dev_pct(&self) -> f64 {
let hundred = 100 as f64;
(self.std_dev() / self.mean()) * hundred
}
fn median_abs_dev(&self) -> T {
fn median_abs_dev(&self) -> f64 {
let med = self.median();
let abs_devs: Vec<T> = self.iter().map(|&v| (med - v).abs()).collect();
let abs_devs: Vec<f64> = self.iter().map(|&v| (med - v).abs()).collect();
// This constant is derived by smarter statistics brains than me, but it is
// consistent with how R and other packages treat the MAD.
let number = FromPrimitive::from_f64(1.4826).unwrap();
let number = 1.4826;
abs_devs.median() * number
}
fn median_abs_dev_pct(&self) -> T {
let hundred = FromPrimitive::from_usize(100).unwrap();
fn median_abs_dev_pct(&self) -> f64 {
let hundred = 100 as f64;
(self.median_abs_dev() / self.median()) * hundred
}
fn percentile(&self, pct: T) -> T {
fn percentile(&self, pct: f64) -> f64 {
let mut tmp = self.to_vec();
local_sort(&mut tmp);
percentile_of_sorted(&tmp, pct)
}
fn quartiles(&self) -> (T,T,T) {
fn quartiles(&self) -> (f64,f64,f64) {
let mut tmp = self.to_vec();
local_sort(&mut tmp);
let first = FromPrimitive::from_usize(25).unwrap();
let first = 25f64;
let a = percentile_of_sorted(&tmp, first);
let secound = FromPrimitive::from_usize(50).unwrap();
let secound = 50f64;
let b = percentile_of_sorted(&tmp, secound);
let third = FromPrimitive::from_usize(75).unwrap();
let third = 75f64;
let c = percentile_of_sorted(&tmp, third);
(a,b,c)
}
fn iqr(&self) -> T {
fn iqr(&self) -> f64 {
let (a,_,c) = self.quartiles();
c - a
}
@ -282,41 +281,41 @@ impl<T: Float + FromPrimitive> Stats<T> for [T] {
// Helper function: extract a value representing the `pct` percentile of a sorted sample-set, using
// linear interpolation. If samples are not sorted, return nonsensical value.
fn percentile_of_sorted<T: Float + FromPrimitive>(sorted_samples: &[T],
pct: T) -> T {
fn percentile_of_sorted(sorted_samples: &[f64], pct: f64) -> f64 {
assert!(!sorted_samples.is_empty());
if sorted_samples.len() == 1 {
return sorted_samples[0];
}
let zero: T = Float::zero();
let zero: f64 = 0.0;
assert!(zero <= pct);
let hundred = FromPrimitive::from_usize(100).unwrap();
let hundred = 100f64;
assert!(pct <= hundred);
if pct == hundred {
return sorted_samples[sorted_samples.len() - 1];
}
let length = FromPrimitive::from_usize(sorted_samples.len() - 1).unwrap();
let length = (sorted_samples.len() - 1) as f64;
let rank = (pct / hundred) * length;
let lrank = rank.floor();
let d = rank - lrank;
let n = lrank.to_usize().unwrap();
let n = lrank as usize;
let lo = sorted_samples[n];
let hi = sorted_samples[n+1];
lo + (hi - lo) * d
}
/// Winsorize a set of samples, replacing values above the `100-pct` percentile and below the `pct`
/// percentile with those percentiles themselves. This is a way of minimizing the effect of
/// outliers, at the cost of biasing the sample. It differs from trimming in that it does not
/// change the number of samples, just changes the values of those that are outliers.
/// Winsorize a set of samples, replacing values above the `100-pct` percentile
/// and below the `pct` percentile with those percentiles themselves. This is a
/// way of minimizing the effect of outliers, at the cost of biasing the sample.
/// It differs from trimming in that it does not change the number of samples,
/// just changes the values of those that are outliers.
///
/// See: http://en.wikipedia.org/wiki/Winsorising
pub fn winsorize<T: Float + FromPrimitive>(samples: &mut [T], pct: T) {
pub fn winsorize(samples: &mut [f64], pct: f64) {
let mut tmp = samples.to_vec();
local_sort(&mut tmp);
let lo = percentile_of_sorted(&tmp, pct);
let hundred: T = FromPrimitive::from_usize(100).unwrap();
let hundred = 100 as f64;
let hi = percentile_of_sorted(&tmp, hundred-pct);
for samp in samples {
if *samp > hi {