mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-28 01:34:21 +00:00
Reorganize core::num internals
Move private bignum module to core::num, because it is not only used in flt2dec. Extract private 80-bit soft-float into new core::num module for the same reason.
This commit is contained in:
parent
cff0411706
commit
cd67ec306f
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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",
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
71
src/libcore/num/diy_float.rs
Normal file
71
src/libcore/num/diy_float.rs
Normal file
@ -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 }
|
||||
}
|
||||
}
|
@ -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.
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
///
|
||||
|
@ -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)]
|
||||
|
@ -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]
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user