Skip to content

Reorganize core::num internals #28539

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 21, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions src/libcore/num/flt2dec/bignum.rs → src/libcore/num/bignum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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);

Expand Down
8 changes: 4 additions & 4 deletions src/libcore/num/dec2flt/algorithm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 0 additions & 3 deletions src/libcore/num/dec2flt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<something else>.

#![doc(hidden)]
#![unstable(feature = "dec2flt",
Expand Down
3 changes: 1 addition & 2 deletions src/libcore/num/dec2flt/num.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions src/libcore/num/dec2flt/rawfp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
71 changes: 71 additions & 0 deletions src/libcore/num/diy_float.rs
Original file line number Diff line number Diff line change
@@ -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 <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.

//! 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 }
}
}
1 change: 0 additions & 1 deletion src/libcore/num/flt2dec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions src/libcore/num/flt2dec/strategy/dragon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
53 changes: 1 addition & 52 deletions src/libcore/num/flt2dec/strategy/grisu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions src/libcore/num/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,12 @@ use slice::SliceExt;
pub struct Wrapping<T>(#[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.
///
Expand Down
2 changes: 2 additions & 0 deletions src/libcoretest/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
6 changes: 3 additions & 3 deletions src/libcoretest/num/dec2flt/rawfp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
1 change: 0 additions & 1 deletion src/libcoretest/num/flt2dec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/libcoretest/num/flt2dec/strategy/dragon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
1 change: 1 addition & 0 deletions src/libcoretest/num/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ mod u64;

mod flt2dec;
mod dec2flt;
mod bignum;

/// Helper function for testing numeric operations
pub fn test_num<T>(ten: T, two: T) where
Expand Down