diff --git a/src/libcore/num/flt2dec/bignum.rs b/src/libcore/num/bignum.rs similarity index 97% rename from src/libcore/num/flt2dec/bignum.rs rename to src/libcore/num/bignum.rs index 091e9c889da..baeca6b8b49 100644 --- a/src/libcore/num/flt2dec/bignum.rs +++ b/src/libcore/num/bignum.rs @@ -19,6 +19,12 @@ //! inputs, but we don't do so to avoid the code bloat. Each bignum is still //! tracked for the actual usages, so it normally doesn't matter. +// This module is only for dec2flt and flt2dec, and only public because of libcoretest. +// It is not intended to ever be stabilized. +#![doc(hidden)] +#![unstable(feature = "core_private_bignum", + reason = "internal routines only exposed for testing", + issue = "0")] #![macro_use] use prelude::v1::*; @@ -194,7 +200,7 @@ macro_rules! define_bignum { /// Adds `other` to itself and returns its own mutable reference. pub fn add<'a>(&'a mut self, other: &$name) -> &'a mut $name { use cmp; - use num::flt2dec::bignum::FullOps; + use num::bignum::FullOps; let mut sz = cmp::max(self.size, other.size); let mut carry = false; @@ -212,7 +218,7 @@ macro_rules! define_bignum { } pub fn add_small(&mut self, other: $ty) -> &mut $name { - use num::flt2dec::bignum::FullOps; + use num::bignum::FullOps; let (mut carry, v) = self.base[0].full_add(other, false); self.base[0] = v; @@ -232,7 +238,7 @@ macro_rules! define_bignum { /// Subtracts `other` from itself and returns its own mutable reference. pub fn sub<'a>(&'a mut self, other: &$name) -> &'a mut $name { use cmp; - use num::flt2dec::bignum::FullOps; + use num::bignum::FullOps; let sz = cmp::max(self.size, other.size); let mut noborrow = true; @@ -249,7 +255,7 @@ macro_rules! define_bignum { /// Multiplies itself by a digit-sized `other` and returns its own /// mutable reference. pub fn mul_small(&mut self, other: $ty) -> &mut $name { - use num::flt2dec::bignum::FullOps; + use num::bignum::FullOps; let mut sz = self.size; let mut carry = 0; @@ -310,7 +316,7 @@ macro_rules! define_bignum { /// Multiplies itself by `5^e` and returns its own mutable reference. pub fn mul_pow5(&mut self, mut e: usize) -> &mut $name { use mem; - use num::flt2dec::bignum::SMALL_POW5; + use num::bignum::SMALL_POW5; // There are exactly n trailing zeros on 2^n, and the only relevant digit sizes // are consecutive powers of two, so this is well suited index for the table. @@ -341,7 +347,7 @@ macro_rules! define_bignum { pub fn mul_digits<'a>(&'a mut self, other: &[$ty]) -> &'a mut $name { // the internal routine. works best when aa.len() <= bb.len(). fn mul_inner(ret: &mut [$ty; $n], aa: &[$ty], bb: &[$ty]) -> usize { - use num::flt2dec::bignum::FullOps; + use num::bignum::FullOps; let mut retsz = 0; for (i, &a) in aa.iter().enumerate() { @@ -378,7 +384,7 @@ macro_rules! define_bignum { /// Divides itself by a digit-sized `other` and returns its own /// mutable reference *and* the remainder. pub fn div_rem_small(&mut self, other: $ty) -> (&mut $name, $ty) { - use num::flt2dec::bignum::FullOps; + use num::bignum::FullOps; assert!(other > 0); diff --git a/src/libcore/num/dec2flt/algorithm.rs b/src/libcore/num/dec2flt/algorithm.rs index f166bb9b3eb..1f0f06d7461 100644 --- a/src/libcore/num/dec2flt/algorithm.rs +++ b/src/libcore/num/dec2flt/algorithm.rs @@ -10,13 +10,13 @@ //! The various algorithms from the paper. -use num::flt2dec::strategy::grisu::Fp; use prelude::v1::*; use cmp::min; use cmp::Ordering::{Less, Equal, Greater}; -use super::table; -use super::rawfp::{self, Unpacked, RawFloat, fp_to_float, next_float, prev_float}; -use super::num::{self, Big}; +use num::diy_float::Fp; +use num::dec2flt::table; +use num::dec2flt::rawfp::{self, Unpacked, RawFloat, fp_to_float, next_float, prev_float}; +use num::dec2flt::num::{self, Big}; /// Number of significand bits in Fp const P: u32 = 64; diff --git a/src/libcore/num/dec2flt/mod.rs b/src/libcore/num/dec2flt/mod.rs index 4e6b6f04e9e..55be4cd3191 100644 --- a/src/libcore/num/dec2flt/mod.rs +++ b/src/libcore/num/dec2flt/mod.rs @@ -86,9 +86,6 @@ //! "such that the exponent +/- the number of decimal digits fits into a 64 bit integer". //! Larger exponents are accepted, but we don't do arithmetic with them, they are immediately //! turned into {positive,negative} {zero,infinity}. -//! -//! FIXME: this uses several things from core::num::flt2dec, which is nonsense. Those things -//! should be moved into core::num::. #![doc(hidden)] #![unstable(feature = "dec2flt", diff --git a/src/libcore/num/dec2flt/num.rs b/src/libcore/num/dec2flt/num.rs index dcba73d7c93..81e7856633b 100644 --- a/src/libcore/num/dec2flt/num.rs +++ b/src/libcore/num/dec2flt/num.rs @@ -14,9 +14,8 @@ use prelude::v1::*; use cmp::Ordering::{self, Less, Equal, Greater}; -use num::flt2dec::bignum::Big32x40; -pub type Big = Big32x40; +pub use num::bignum::Big32x40 as Big; /// Test whether truncating all bits less significant than `ones_place` introduces /// a relative error less, equal, or greater than 0.5 ULP. diff --git a/src/libcore/num/dec2flt/rawfp.rs b/src/libcore/num/dec2flt/rawfp.rs index 830d2dad42f..be61653c379 100644 --- a/src/libcore/num/dec2flt/rawfp.rs +++ b/src/libcore/num/dec2flt/rawfp.rs @@ -33,10 +33,10 @@ use cmp::Ordering::{Less, Equal, Greater}; use ops::{Mul, Div, Neg}; use fmt::{Debug, LowerExp}; use mem::transmute; -use num::flt2dec::strategy::grisu::Fp; +use num::diy_float::Fp; use num::FpCategory::{Infinite, Zero, Subnormal, Normal, Nan}; use num::Float; -use super::num::{self, Big}; +use num::dec2flt::num::{self, Big}; #[derive(Copy, Clone, Debug)] pub struct Unpacked { diff --git a/src/libcore/num/diy_float.rs b/src/libcore/num/diy_float.rs new file mode 100644 index 00000000000..7c369ee3b3b --- /dev/null +++ b/src/libcore/num/diy_float.rs @@ -0,0 +1,71 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Extended precision "soft float", for internal use only. + +// This module is only for dec2flt and flt2dec, and only public because of libcoretest. +// It is not intended to ever be stabilized. +#![doc(hidden)] +#![unstable(feature = "core_private_diy_float", + reason = "internal routines only exposed for testing", + issue = "0")] + +/// A custom 64-bit floating point type, representing `f * 2^e`. +#[derive(Copy, Clone, Debug)] +#[doc(hidden)] +pub struct Fp { + /// The integer mantissa. + pub f: u64, + /// The exponent in base 2. + pub e: i16, +} + +impl Fp { + /// Returns a correctly rounded product of itself and `other`. + pub fn mul(&self, other: &Fp) -> Fp { + const MASK: u64 = 0xffffffff; + let a = self.f >> 32; + let b = self.f & MASK; + let c = other.f >> 32; + let d = other.f & MASK; + let ac = a * c; + let bc = b * c; + let ad = a * d; + let bd = b * d; + let tmp = (bd >> 32) + (ad & MASK) + (bc & MASK) + (1 << 31) /* round */; + let f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32); + let e = self.e + other.e + 64; + Fp { f: f, e: e } + } + + /// Normalizes itself so that the resulting mantissa is at least `2^63`. + pub fn normalize(&self) -> Fp { + let mut f = self.f; + let mut e = self.e; + if f >> (64 - 32) == 0 { f <<= 32; e -= 32; } + if f >> (64 - 16) == 0 { f <<= 16; e -= 16; } + if f >> (64 - 8) == 0 { f <<= 8; e -= 8; } + if f >> (64 - 4) == 0 { f <<= 4; e -= 4; } + if f >> (64 - 2) == 0 { f <<= 2; e -= 2; } + if f >> (64 - 1) == 0 { f <<= 1; e -= 1; } + debug_assert!(f >= (1 >> 63)); + Fp { f: f, e: e } + } + + /// Normalizes itself to have the shared exponent. + /// It can only decrease the exponent (and thus increase the mantissa). + pub fn normalize_to(&self, e: i16) -> Fp { + let edelta = self.e - e; + assert!(edelta >= 0); + let edelta = edelta as usize; + assert_eq!(self.f << edelta >> edelta, self.f); + Fp { f: self.f << edelta, e: e } + } +} diff --git a/src/libcore/num/flt2dec/mod.rs b/src/libcore/num/flt2dec/mod.rs index 700523e49a2..7f7c61938cb 100644 --- a/src/libcore/num/flt2dec/mod.rs +++ b/src/libcore/num/flt2dec/mod.rs @@ -136,7 +136,6 @@ use slice::bytes; pub use self::decoder::{decode, DecodableFloat, FullDecoded, Decoded}; pub mod estimator; -pub mod bignum; pub mod decoder; /// Digit-generation algorithms. diff --git a/src/libcore/num/flt2dec/strategy/dragon.rs b/src/libcore/num/flt2dec/strategy/dragon.rs index 40aa2a527db..2d68c3a6d02 100644 --- a/src/libcore/num/flt2dec/strategy/dragon.rs +++ b/src/libcore/num/flt2dec/strategy/dragon.rs @@ -21,8 +21,8 @@ use cmp::Ordering; use num::flt2dec::{Decoded, MAX_SIG_DIGITS, round_up}; use num::flt2dec::estimator::estimate_scaling_factor; -use num::flt2dec::bignum::Digit32 as Digit; -use num::flt2dec::bignum::Big32x40 as Big; +use num::bignum::Digit32 as Digit; +use num::bignum::Big32x40 as Big; static POW10: [Digit; 10] = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000]; diff --git a/src/libcore/num/flt2dec/strategy/grisu.rs b/src/libcore/num/flt2dec/strategy/grisu.rs index b0822ca76c7..5b4b2e46478 100644 --- a/src/libcore/num/flt2dec/strategy/grisu.rs +++ b/src/libcore/num/flt2dec/strategy/grisu.rs @@ -18,60 +18,9 @@ Rust adaptation of Grisu3 algorithm described in [1]. It uses about use prelude::v1::*; +use num::diy_float::Fp; use num::flt2dec::{Decoded, MAX_SIG_DIGITS, round_up}; -/// A custom 64-bit floating point type, representing `f * 2^e`. -#[derive(Copy, Clone, Debug)] -#[doc(hidden)] -pub struct Fp { - /// The integer mantissa. - pub f: u64, - /// The exponent in base 2. - pub e: i16, -} - -impl Fp { - /// Returns a correctly rounded product of itself and `other`. - pub fn mul(&self, other: &Fp) -> Fp { - const MASK: u64 = 0xffffffff; - let a = self.f >> 32; - let b = self.f & MASK; - let c = other.f >> 32; - let d = other.f & MASK; - let ac = a * c; - let bc = b * c; - let ad = a * d; - let bd = b * d; - let tmp = (bd >> 32) + (ad & MASK) + (bc & MASK) + (1 << 31) /* round */; - let f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32); - let e = self.e + other.e + 64; - Fp { f: f, e: e } - } - - /// Normalizes itself so that the resulting mantissa is at least `2^63`. - pub fn normalize(&self) -> Fp { - let mut f = self.f; - let mut e = self.e; - if f >> (64 - 32) == 0 { f <<= 32; e -= 32; } - if f >> (64 - 16) == 0 { f <<= 16; e -= 16; } - if f >> (64 - 8) == 0 { f <<= 8; e -= 8; } - if f >> (64 - 4) == 0 { f <<= 4; e -= 4; } - if f >> (64 - 2) == 0 { f <<= 2; e -= 2; } - if f >> (64 - 1) == 0 { f <<= 1; e -= 1; } - debug_assert!(f >= (1 >> 63)); - Fp { f: f, e: e } - } - - /// Normalizes itself to have the shared exponent. - /// It can only decrease the exponent (and thus increase the mantissa). - pub fn normalize_to(&self, e: i16) -> Fp { - let edelta = self.e - e; - assert!(edelta >= 0); - let edelta = edelta as usize; - assert_eq!(self.f << edelta >> edelta, self.f); - Fp { f: self.f << edelta, e: e } - } -} // see the comments in `format_shortest_opt` for the rationale. #[doc(hidden)] pub const ALPHA: i16 = -60; diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 127f8d3b5a2..6507bb7bf8c 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -43,8 +43,12 @@ use slice::SliceExt; pub struct Wrapping(#[stable(feature = "rust1", since = "1.0.0")] pub T); pub mod wrapping; + +// All these modules are technically private and only exposed for libcoretest: pub mod flt2dec; pub mod dec2flt; +pub mod bignum; +pub mod diy_float; /// Types that have a "zero" value. /// diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs index e87a179f58d..22b285b0343 100644 --- a/src/libcoretest/lib.rs +++ b/src/libcoretest/lib.rs @@ -15,6 +15,8 @@ #![feature(const_fn)] #![feature(core)] #![feature(core_float)] +#![feature(core_private_bignum)] +#![feature(core_private_diy_float)] #![feature(dec2flt)] #![feature(decode_utf16)] #![feature(fixed_size_array)] diff --git a/src/libcoretest/num/flt2dec/bignum.rs b/src/libcoretest/num/bignum.rs similarity index 99% rename from src/libcoretest/num/flt2dec/bignum.rs rename to src/libcoretest/num/bignum.rs index 31065b2898f..58a9dd1b128 100644 --- a/src/libcoretest/num/flt2dec/bignum.rs +++ b/src/libcoretest/num/bignum.rs @@ -9,7 +9,7 @@ // except according to those terms. use std::prelude::v1::*; -use core::num::flt2dec::bignum::tests::Big8x3 as Big; +use core::num::bignum::tests::Big8x3 as Big; #[test] #[should_panic] diff --git a/src/libcoretest/num/dec2flt/rawfp.rs b/src/libcoretest/num/dec2flt/rawfp.rs index a40d360f105..4c0a403e574 100644 --- a/src/libcoretest/num/dec2flt/rawfp.rs +++ b/src/libcoretest/num/dec2flt/rawfp.rs @@ -9,14 +9,14 @@ // except according to those terms. use std::f64; -use core::num::flt2dec::strategy::grisu::Fp; +use core::num::diy_float::Fp; use core::num::dec2flt::rawfp::{fp_to_float, prev_float, next_float, round_normal}; #[test] fn fp_to_float_half_to_even() { fn is_normalized(sig: u64) -> bool { - // intentionally written without {min,max}_sig() as a sanity check - sig >> 52 == 1 && sig >> 53 == 0 + // intentionally written without {min,max}_sig() as a sanity check + sig >> 52 == 1 && sig >> 53 == 0 } fn conv(sig: u64) -> u64 { diff --git a/src/libcoretest/num/flt2dec/mod.rs b/src/libcoretest/num/flt2dec/mod.rs index 8ae33a44202..309bf6d8192 100644 --- a/src/libcoretest/num/flt2dec/mod.rs +++ b/src/libcoretest/num/flt2dec/mod.rs @@ -23,7 +23,6 @@ use core::num::flt2dec::{to_shortest_str, to_shortest_exp_str, pub use test::Bencher; mod estimator; -mod bignum; mod strategy { mod dragon; mod grisu; diff --git a/src/libcoretest/num/flt2dec/strategy/dragon.rs b/src/libcoretest/num/flt2dec/strategy/dragon.rs index f3ddc370d1e..79dcca7671a 100644 --- a/src/libcoretest/num/flt2dec/strategy/dragon.rs +++ b/src/libcoretest/num/flt2dec/strategy/dragon.rs @@ -12,7 +12,7 @@ use std::prelude::v1::*; use std::{i16, f64}; use super::super::*; use core::num::flt2dec::*; -use core::num::flt2dec::bignum::Big32x40 as Big; +use core::num::bignum::Big32x40 as Big; use core::num::flt2dec::strategy::dragon::*; #[test] diff --git a/src/libcoretest/num/mod.rs b/src/libcoretest/num/mod.rs index 9f9d2a4ca16..f57c54faf28 100644 --- a/src/libcoretest/num/mod.rs +++ b/src/libcoretest/num/mod.rs @@ -31,6 +31,7 @@ mod u64; mod flt2dec; mod dec2flt; +mod bignum; /// Helper function for testing numeric operations pub fn test_num(ten: T, two: T) where