Format libcore with rustfmt

This commit applies rustfmt with default settings to files in
src/libcore *that are not involved in any currently open PR* to minimize
merge conflicts. The list of files involved in open PRs was determined
by querying GitHub's GraphQL API with this script:
https://gist.github.com/dtolnay/aa9c34993dc051a4f344d1b10e4487e8

With the list of files from the script in `outstanding_files`, the
relevant commands were:

    $ find src/libcore -name '*.rs' | xargs rustfmt --edition=2018
    $ rg libcore outstanding_files | xargs git checkout --

Repeating this process several months apart should get us coverage of
most of the rest of libcore.
This commit is contained in:
David Tolnay
2019-11-24 01:43:32 -08:00
parent 809e180a76
commit 95e00bfed8
52 changed files with 1801 additions and 1295 deletions

View File

@@ -12,13 +12,15 @@
// This module is only for dec2flt and flt2dec, and only public because of coretests.
// It is not intended to ever be stabilized.
#![doc(hidden)]
#![unstable(feature = "core_private_bignum",
reason = "internal routines only exposed for testing",
issue = "0")]
#![unstable(
feature = "core_private_bignum",
reason = "internal routines only exposed for testing",
issue = "0"
)]
#![macro_use]
use crate::mem;
use crate::intrinsics;
use crate::mem;
/// Arithmetic operations required by bignums.
pub trait FullOps: Sized {
@@ -36,10 +38,8 @@ pub trait FullOps: Sized {
/// Returns `(quo, rem)` such that `borrow * 2^W + self = quo * other + rem`
/// and `0 <= rem < other`, where `W` is the number of bits in `Self`.
fn full_div_rem(self,
other: Self,
borrow: Self)
-> (Self /* quotient */, Self /* remainder */);
fn full_div_rem(self, other: Self, borrow: Self)
-> (Self /* quotient */, Self /* remainder */);
}
macro_rules! impl_full_ops {
@@ -98,7 +98,7 @@ impl_full_ops! {
const SMALL_POW5: [(u64, usize); 3] = [(125, 3), (15625, 6), (1_220_703_125, 13)];
macro_rules! define_bignum {
($name:ident: type=$ty:ty, n=$n:expr) => (
($name:ident: type=$ty:ty, n=$n:expr) => {
/// Stack-allocated arbitrary-precision (up to certain limit) integer.
///
/// This is backed by a fixed-size array of given type ("digit").
@@ -115,7 +115,7 @@ macro_rules! define_bignum {
size: usize,
/// Digits. `[a, b, c, ...]` represents `a + b*2^W + c*2^(2W) + ...`
/// where `W` is the number of bits in the digit type.
base: [$ty; $n]
base: [$ty; $n],
}
impl $name {
@@ -180,7 +180,7 @@ macro_rules! define_bignum {
}
// This could be optimized with leading_zeros() and bit shifts, but that's
// probably not worth the hassle.
let digitbits = mem::size_of::<$ty>()* 8;
let digitbits = mem::size_of::<$ty>() * 8;
let mut i = nonzero.len() * digitbits - 1;
while self.get_bit(i) == 0 {
i -= 1;
@@ -272,12 +272,12 @@ macro_rules! define_bignum {
let bits = bits % digitbits;
assert!(digits < $n);
debug_assert!(self.base[$n-digits..].iter().all(|&v| v == 0));
debug_assert!(bits == 0 || (self.base[$n-digits-1] >> (digitbits - bits)) == 0);
debug_assert!(self.base[$n - digits..].iter().all(|&v| v == 0));
debug_assert!(bits == 0 || (self.base[$n - digits - 1] >> (digitbits - bits)) == 0);
// shift by `digits * digitbits` bits
for i in (0..self.size).rev() {
self.base[i+digits] = self.base[i];
self.base[i + digits] = self.base[i];
}
for i in 0..digits {
self.base[i] = 0;
@@ -287,14 +287,14 @@ macro_rules! define_bignum {
let mut sz = self.size + digits;
if bits > 0 {
let last = sz;
let overflow = self.base[last-1] >> (digitbits - bits);
let overflow = self.base[last - 1] >> (digitbits - bits);
if overflow > 0 {
self.base[last] = overflow;
sz += 1;
}
for i in (digits+1..last).rev() {
self.base[i] = (self.base[i] << bits) |
(self.base[i-1] >> (digitbits - bits));
for i in (digits + 1..last).rev() {
self.base[i] =
(self.base[i] << bits) | (self.base[i - 1] >> (digitbits - bits));
}
self.base[digits] <<= bits;
// self.base[..digits] is zero, no need to shift
@@ -331,7 +331,6 @@ macro_rules! define_bignum {
self
}
/// Multiplies itself by a number described by `other[0] + other[1] * 2^W +
/// other[2] * 2^(2W) + ...` (where `W` is the number of bits in the digit type)
/// and returns its own mutable reference.
@@ -342,7 +341,9 @@ macro_rules! define_bignum {
let mut retsz = 0;
for (i, &a) in aa.iter().enumerate() {
if a == 0 { continue; }
if a == 0 {
continue;
}
let mut sz = bb.len();
let mut carry = 0;
for (j, &b) in bb.iter().enumerate() {
@@ -430,11 +431,12 @@ macro_rules! define_bignum {
}
impl crate::cmp::PartialEq for $name {
fn eq(&self, other: &$name) -> bool { self.base[..] == other.base[..] }
fn eq(&self, other: &$name) -> bool {
self.base[..] == other.base[..]
}
}
impl crate::cmp::Eq for $name {
}
impl crate::cmp::Eq for $name {}
impl crate::cmp::PartialOrd for $name {
fn partial_cmp(&self, other: &$name) -> crate::option::Option<crate::cmp::Ordering> {
@@ -462,17 +464,17 @@ macro_rules! define_bignum {
fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {
use crate::mem;
let sz = if self.size < 1 {1} else {self.size};
let sz = if self.size < 1 { 1 } else { self.size };
let digitlen = mem::size_of::<$ty>() * 2;
write!(f, "{:#x}", self.base[sz-1])?;
for &v in self.base[..sz-1].iter().rev() {
write!(f, "{:#x}", self.base[sz - 1])?;
for &v in self.base[..sz - 1].iter().rev() {
write!(f, "_{:01$x}", v, digitlen)?;
}
crate::result::Result::Ok(())
}
}
)
};
}
/// The digit type for `Big32x40`.

View File

@@ -1,11 +1,11 @@
//! The various algorithms from the paper.
use crate::cmp::min;
use crate::cmp::Ordering::{Less, Equal, Greater};
use crate::num::diy_float::Fp;
use crate::num::dec2flt::table;
use crate::num::dec2flt::rawfp::{self, Unpacked, RawFloat, fp_to_float, next_float, prev_float};
use crate::cmp::Ordering::{Equal, Greater, Less};
use crate::num::dec2flt::num::{self, Big};
use crate::num::dec2flt::rawfp::{self, fp_to_float, next_float, prev_float, RawFloat, Unpacked};
use crate::num::dec2flt::table;
use crate::num::diy_float::Fp;
/// Number of significand bits in Fp
const P: u32 = 64;
@@ -23,9 +23,9 @@ fn power_of_ten(e: i16) -> Fp {
// In most architectures, floating point operations have an explicit bit size, therefore the
// precision of the computation is determined on a per-operation basis.
#[cfg(any(not(target_arch="x86"), target_feature="sse2"))]
#[cfg(any(not(target_arch = "x86"), target_feature = "sse2"))]
mod fpu_precision {
pub fn set_precision<T>() { }
pub fn set_precision<T>() {}
}
// On x86, the x87 FPU is used for float operations if the SSE/SSE2 extensions are not available.
@@ -33,7 +33,7 @@ mod fpu_precision {
// round to 80 bits causing double rounding to happen when values are eventually represented as
// 32/64 bit float values. To overcome this, the FPU control word can be set so that the
// computations are performed in the desired precision.
#[cfg(all(target_arch="x86", not(target_feature="sse2")))]
#[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
mod fpu_precision {
use crate::mem::size_of;

View File

@@ -78,23 +78,25 @@
//! turned into {positive,negative} {zero,infinity}.
#![doc(hidden)]
#![unstable(feature = "dec2flt",
reason = "internal routines only exposed for testing",
issue = "0")]
#![unstable(
feature = "dec2flt",
reason = "internal routines only exposed for testing",
issue = "0"
)]
use crate::fmt;
use crate::str::FromStr;
use self::parse::{parse_decimal, Decimal, Sign, ParseResult};
use self::num::digits_to_big;
use self::parse::{parse_decimal, Decimal, ParseResult, Sign};
use self::rawfp::RawFloat;
mod algorithm;
mod table;
mod num;
mod table;
// These two have their own tests.
pub mod rawfp;
pub mod parse;
pub mod rawfp;
macro_rules! from_str_float_impl {
($t:ty) => {
@@ -155,7 +157,7 @@ macro_rules! from_str_float_impl {
dec2flt(src)
}
}
}
};
}
from_str_float_impl!(f32);
from_str_float_impl!(f64);
@@ -171,7 +173,7 @@ from_str_float_impl!(f64);
#[derive(Debug, Clone, PartialEq, Eq)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct ParseFloatError {
kind: FloatErrorKind
kind: FloatErrorKind,
}
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -181,10 +183,12 @@ enum FloatErrorKind {
}
impl ParseFloatError {
#[unstable(feature = "int_error_internals",
reason = "available through Error trait and this method should \
not be exposed publicly",
issue = "0")]
#[unstable(
feature = "int_error_internals",
reason = "available through Error trait and this method should \
not be exposed publicly",
issue = "0"
)]
#[doc(hidden)]
pub fn __description(&self) -> &str {
match self.kind {
@@ -222,7 +226,7 @@ fn extract_sign(s: &str) -> (Sign, &str) {
/// Converts a decimal string into a floating point number.
fn dec2flt<T: RawFloat>(s: &str) -> Result<T, ParseFloatError> {
if s.is_empty() {
return Err(pfe_empty())
return Err(pfe_empty());
}
let (sign, s) = extract_sign(s);
let flt = match parse_decimal(s) {
@@ -232,8 +236,10 @@ fn dec2flt<T: RawFloat>(s: &str) -> Result<T, ParseFloatError> {
ParseResult::Invalid => match s {
"inf" => T::INFINITY,
"NaN" => T::NAN,
_ => { return Err(pfe_invalid()); }
}
_ => {
return Err(pfe_invalid());
}
},
};
match sign {

View File

@@ -2,7 +2,7 @@
// FIXME This module's name is a bit unfortunate, since other modules also import `core::num`.
use crate::cmp::Ordering::{self, Less, Equal, Greater};
use crate::cmp::Ordering::{self, Equal, Greater, Less};
pub use crate::num::bignum::Big32x40 as Big;
@@ -36,7 +36,10 @@ pub fn compare_with_half_ulp(f: &Big, ones_place: usize) -> Ordering {
/// 1. using `FromStr` on `&[u8]` requires `from_utf8_unchecked`, which is bad, and
/// 2. piecing together the results of `integral.parse()` and `fractional.parse()` is
/// more complicated than this entire function.
pub fn from_str_unchecked<'a, T>(bytes: T) -> u64 where T : IntoIterator<Item=&'a u8> {
pub fn from_str_unchecked<'a, T>(bytes: T) -> u64
where
T: IntoIterator<Item = &'a u8>,
{
let mut result = 0;
for &c in bytes {
result = result * 10 + (c - b'0') as u64;
@@ -61,14 +64,9 @@ pub fn digits_to_big(integral: &[u8], fractional: &[u8]) -> Big {
pub fn to_u64(x: &Big) -> u64 {
assert!(x.bit_length() < 64);
let d = x.digits();
if d.len() < 2 {
d[0] as u64
} else {
(d[1] as u64) << 32 | d[0] as u64
}
if d.len() < 2 { d[0] as u64 } else { (d[1] as u64) << 32 | d[0] as u64 }
}
/// Extracts a range of bits.
/// Index 0 is the least significant bit and the range is half-open as usual.

View File

@@ -10,8 +10,8 @@
//! modules rely on to not panic (or overflow) in turn.
//! To make matters worse, all that happens in a single pass over the input.
//! So, be careful when modifying anything, and double-check with the other modules.
use self::ParseResult::{Invalid, ShortcutToInf, ShortcutToZero, Valid};
use super::num;
use self::ParseResult::{Valid, ShortcutToInf, ShortcutToZero, Invalid};
#[derive(Debug)]
pub enum Sign {

View File

@@ -17,15 +17,15 @@
//! Many functions in this module only handle normal numbers. The dec2flt routines conservatively
//! take the universally-correct slow path (Algorithm M) for very small and very large numbers.
//! That algorithm needs only next_float() which does handle subnormals and zeros.
use crate::cmp::Ordering::{Less, Equal, Greater};
use crate::cmp::Ordering::{Equal, Greater, Less};
use crate::convert::{TryFrom, TryInto};
use crate::ops::{Add, Mul, Div, Neg};
use crate::fmt::{Debug, LowerExp};
use crate::num::diy_float::Fp;
use crate::num::FpCategory::{Infinite, Zero, Subnormal, Normal, Nan};
use crate::num::FpCategory;
use crate::num::dec2flt::num::{self, Big};
use crate::num::dec2flt::table;
use crate::num::diy_float::Fp;
use crate::num::FpCategory;
use crate::num::FpCategory::{Infinite, Nan, Normal, Subnormal, Zero};
use crate::ops::{Add, Div, Mul, Neg};
#[derive(Copy, Clone, Debug)]
pub struct Unpacked {
@@ -44,13 +44,8 @@ impl Unpacked {
/// See the parent module's doc comment for why this is necessary.
///
/// Should **never ever** be implemented for other types or be used outside the dec2flt module.
pub trait RawFloat
: Copy
+ Debug
+ LowerExp
+ Mul<Output=Self>
+ Div<Output=Self>
+ Neg<Output=Self>
pub trait RawFloat:
Copy + Debug + LowerExp + Mul<Output = Self> + Div<Output = Self> + Neg<Output = Self>
{
const INFINITY: Self;
const NAN: Self;
@@ -144,7 +139,7 @@ macro_rules! other_constants {
const INFINITY: Self = $crate::$type::INFINITY;
const NAN: Self = $crate::$type::NAN;
const ZERO: Self = 0.0;
}
};
}
impl RawFloat for f32 {
@@ -163,11 +158,8 @@ impl RawFloat for f32 {
let bits = self.to_bits();
let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 };
let mut exponent: i16 = ((bits >> 23) & 0xff) as i16;
let mantissa = if exponent == 0 {
(bits & 0x7fffff) << 1
} else {
(bits & 0x7fffff) | 0x800000
};
let mantissa =
if exponent == 0 { (bits & 0x7fffff) << 1 } else { (bits & 0x7fffff) | 0x800000 };
// Exponent bias + mantissa shift
exponent -= 127 + 23;
(mantissa as u64, exponent, sign)
@@ -188,12 +180,17 @@ impl RawFloat for f32 {
table::F32_SHORT_POWERS[e]
}
fn classify(self) -> FpCategory { self.classify() }
fn to_bits(self) -> Self::Bits { self.to_bits() }
fn from_bits(v: Self::Bits) -> Self { Self::from_bits(v) }
fn classify(self) -> FpCategory {
self.classify()
}
fn to_bits(self) -> Self::Bits {
self.to_bits()
}
fn from_bits(v: Self::Bits) -> Self {
Self::from_bits(v)
}
}
impl RawFloat for f64 {
type Bits = u64;
@@ -235,9 +232,15 @@ impl RawFloat for f64 {
table::F64_SHORT_POWERS[e]
}
fn classify(self) -> FpCategory { self.classify() }
fn to_bits(self) -> Self::Bits { self.to_bits() }
fn from_bits(v: Self::Bits) -> Self { Self::from_bits(v) }
fn classify(self) -> FpCategory {
self.classify()
}
fn to_bits(self) -> Self::Bits {
self.to_bits()
}
fn from_bits(v: Self::Bits) -> Self {
Self::from_bits(v)
}
}
/// Converts an `Fp` to the closest machine float type.
@@ -248,7 +251,7 @@ pub fn fp_to_float<T: RawFloat>(x: Fp) -> T {
let e = x.e + 63;
if e > T::MAX_EXP {
panic!("fp_to_float: exponent {} too large", e)
} else if e > T::MIN_EXP {
} else if e > T::MIN_EXP {
encode_normal(round_normal::<T>(x))
} else {
panic!("fp_to_float: exponent {} too small", e)
@@ -278,14 +281,15 @@ pub fn round_normal<T: RawFloat>(x: Fp) -> Unpacked {
/// Inverse of `RawFloat::unpack()` for normalized numbers.
/// Panics if the significand or exponent are not valid for normalized numbers.
pub fn encode_normal<T: RawFloat>(x: Unpacked) -> T {
debug_assert!(T::MIN_SIG <= x.sig && x.sig <= T::MAX_SIG,
"encode_normal: significand not normalized");
debug_assert!(
T::MIN_SIG <= x.sig && x.sig <= T::MAX_SIG,
"encode_normal: significand not normalized"
);
// Remove the hidden bit
let sig_enc = x.sig & !(1 << T::EXPLICIT_SIG_BITS);
// Adjust the exponent for exponent bias and mantissa shift
let k_enc = x.k + T::MAX_EXP + T::EXPLICIT_SIG_BITS as i16;
debug_assert!(k_enc != 0 && k_enc < T::MAX_ENCODED_EXP,
"encode_normal: exponent out of range");
debug_assert!(k_enc != 0 && k_enc < T::MAX_ENCODED_EXP, "encode_normal: exponent out of range");
// Leave sign bit at 0 ("+"), our numbers are all positive
let bits = (k_enc as u64) << T::EXPLICIT_SIG_BITS | sig_enc;
T::from_bits(bits.try_into().unwrap_or_else(|_| unreachable!()))
@@ -315,7 +319,7 @@ pub fn big_to_fp(f: &Big) -> Fp {
Equal | Greater => match leading.checked_add(1) {
Some(f) => Fp { f, e }.normalize(),
None => Fp { f: 1 << 63, e: e + 1 },
}
},
}
}
@@ -354,8 +358,6 @@ pub fn next_float<T: RawFloat>(x: T) -> T {
// want, and the mantissa bits become zero. Because of the hidden bit convention, this
// too is exactly what we want!
// Finally, f64::MAX + 1 = 7eff...f + 1 = 7ff0...0 = f64::INFINITY.
Zero | Subnormal | Normal => {
T::from_bits(x.to_bits() + T::Bits::from(1u8))
}
Zero | Subnormal | Normal => T::from_bits(x.to_bits() + T::Bits::from(1u8)),
}
}

View File

@@ -3,9 +3,11 @@
// This module is only for dec2flt and flt2dec, and only public because of coretests.
// 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")]
#![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)]
@@ -74,9 +76,6 @@ impl Fp {
assert!(edelta >= 0);
let edelta = edelta as usize;
assert_eq!(self.f << edelta >> edelta, self.f);
Fp {
f: self.f << edelta,
e,
}
Fp { f: self.f << edelta, e }
}
}

View File

@@ -1,8 +1,8 @@
//! Decodes a floating-point value into individual parts and error ranges.
use crate::{f32, f64};
use crate::num::FpCategory;
use crate::num::dec2flt::rawfp::RawFloat;
use crate::num::FpCategory;
use crate::{f32, f64};
/// Decoded unsigned finite value, such that:
///
@@ -47,11 +47,15 @@ pub trait DecodableFloat: RawFloat + Copy {
}
impl DecodableFloat for f32 {
fn min_pos_norm_value() -> Self { f32::MIN_POSITIVE }
fn min_pos_norm_value() -> Self {
f32::MIN_POSITIVE
}
}
impl DecodableFloat for f64 {
fn min_pos_norm_value() -> Self { f64::MIN_POSITIVE }
fn min_pos_norm_value() -> Self {
f64::MIN_POSITIVE
}
}
/// Returns a sign (true when negative) and `FullDecoded` value
@@ -67,20 +71,29 @@ pub fn decode<T: DecodableFloat>(v: T) -> (/*negative?*/ bool, FullDecoded) {
// neighbors: (mant - 2, exp) -- (mant, exp) -- (mant + 2, exp)
// Float::integer_decode always preserves the exponent,
// so the mantissa is scaled for subnormals.
FullDecoded::Finite(Decoded { mant, minus: 1, plus: 1,
exp, inclusive: even })
FullDecoded::Finite(Decoded { mant, minus: 1, plus: 1, exp, inclusive: even })
}
FpCategory::Normal => {
let minnorm = <T as DecodableFloat>::min_pos_norm_value().integer_decode();
if mant == minnorm.0 {
// neighbors: (maxmant, exp - 1) -- (minnormmant, exp) -- (minnormmant + 1, exp)
// where maxmant = minnormmant * 2 - 1
FullDecoded::Finite(Decoded { mant: mant << 2, minus: 1, plus: 2,
exp: exp - 2, inclusive: even })
FullDecoded::Finite(Decoded {
mant: mant << 2,
minus: 1,
plus: 2,
exp: exp - 2,
inclusive: even,
})
} else {
// neighbors: (mant - 1, exp) -- (mant, exp) -- (mant + 1, exp)
FullDecoded::Finite(Decoded { mant: mant << 1, minus: 1, plus: 1,
exp: exp - 1, inclusive: even })
FullDecoded::Finite(Decoded {
mant: mant << 1,
minus: 1,
plus: 1,
exp: exp - 1,
inclusive: even,
})
}
}
};

View File

@@ -116,15 +116,17 @@ functions.
// while this is extensively documented, this is in principle private which is
// only made public for testing. do not expose us.
#![doc(hidden)]
#![unstable(feature = "flt2dec",
reason = "internal routines only exposed for testing",
issue = "0")]
#![unstable(
feature = "flt2dec",
reason = "internal routines only exposed for testing",
issue = "0"
)]
pub use self::decoder::{decode, DecodableFloat, Decoded, FullDecoded};
use crate::i16;
pub use self::decoder::{decode, DecodableFloat, FullDecoded, Decoded};
pub mod estimator;
pub mod decoder;
pub mod estimator;
/// Digit-generation algorithms.
pub mod strategy {
@@ -144,17 +146,24 @@ pub const MAX_SIG_DIGITS: usize = 17;
#[doc(hidden)]
pub fn round_up(d: &mut [u8], n: usize) -> Option<u8> {
match d[..n].iter().rposition(|&c| c != b'9') {
Some(i) => { // d[i+1..n] is all nines
Some(i) => {
// d[i+1..n] is all nines
d[i] += 1;
for j in i+1..n { d[j] = b'0'; }
for j in i + 1..n {
d[j] = b'0';
}
None
}
None if n > 0 => { // 999..999 rounds to 1000..000 with an increased exponent
None if n > 0 => {
// 999..999 rounds to 1000..000 with an increased exponent
d[0] = b'1';
for j in 1..n { d[j] = b'0'; }
for j in 1..n {
d[j] = b'0';
}
Some(b'0')
}
None => { // an empty buffer rounds up (a bit strange but reasonable)
None => {
// an empty buffer rounds up (a bit strange but reasonable)
Some(b'1')
}
}
@@ -176,8 +185,19 @@ impl<'a> Part<'a> {
pub fn len(&self) -> usize {
match *self {
Part::Zero(nzeroes) => nzeroes,
Part::Num(v) => if v < 1_000 { if v < 10 { 1 } else if v < 100 { 2 } else { 3 } }
else { if v < 10_000 { 4 } else { 5 } },
Part::Num(v) => {
if v < 1_000 {
if v < 10 {
1
} else if v < 100 {
2
} else {
3
}
} else {
if v < 10_000 { 4 } else { 5 }
}
}
Part::Copy(buf) => buf.len(),
}
}
@@ -190,7 +210,9 @@ impl<'a> Part<'a> {
if out.len() >= len {
match *self {
Part::Zero(nzeroes) => {
for c in &mut out[..nzeroes] { *c = b'0'; }
for c in &mut out[..nzeroes] {
*c = b'0';
}
}
Part::Num(mut v) => {
for c in out[..len].iter_mut().rev() {
@@ -234,7 +256,9 @@ impl<'a> Formatted<'a> {
/// Returns the number of written bytes, or `None` if the buffer is not enough.
/// (It may still leave partially written bytes in the buffer; do not rely on that.)
pub fn write(&self, out: &mut [u8]) -> Option<usize> {
if out.len() < self.sign.len() { return None; }
if out.len() < self.sign.len() {
return None;
}
out[..self.sign.len()].copy_from_slice(self.sign);
let mut written = self.sign.len();
@@ -254,8 +278,12 @@ impl<'a> Formatted<'a> {
/// it will be ignored and full digits will be printed. It is only used to print
/// additional zeroes after rendered digits. Thus `frac_digits` of 0 means that
/// it will only print given digits and nothing else.
fn digits_to_dec_str<'a>(buf: &'a [u8], exp: i16, frac_digits: usize,
parts: &'a mut [Part<'a>]) -> &'a [Part<'a>] {
fn digits_to_dec_str<'a>(
buf: &'a [u8],
exp: i16,
frac_digits: usize,
parts: &'a mut [Part<'a>],
) -> &'a [Part<'a>] {
assert!(!buf.is_empty());
assert!(buf[0] > b'0');
assert!(parts.len() >= 4);
@@ -322,8 +350,13 @@ fn digits_to_dec_str<'a>(buf: &'a [u8], exp: i16, frac_digits: usize,
/// it will be ignored and full digits will be printed. It is only used to print
/// additional zeroes after rendered digits. Thus, `min_digits == 0` means that
/// it will only print the given digits and nothing else.
fn digits_to_exp_str<'a>(buf: &'a [u8], exp: i16, min_ndigits: usize, upper: bool,
parts: &'a mut [Part<'a>]) -> &'a [Part<'a>] {
fn digits_to_exp_str<'a>(
buf: &'a [u8],
exp: i16,
min_ndigits: usize,
upper: bool,
parts: &'a mut [Part<'a>],
) -> &'a [Part<'a>] {
assert!(!buf.is_empty());
assert!(buf[0] > b'0');
assert!(parts.len() >= 6);
@@ -359,11 +392,11 @@ fn digits_to_exp_str<'a>(buf: &'a [u8], exp: i16, min_ndigits: usize, upper: boo
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Sign {
/// Prints `-` only for the negative non-zero values.
Minus, // -inf -1 0 0 1 inf nan
Minus, // -inf -1 0 0 1 inf nan
/// Prints `-` only for any negative values (including the negative zero).
MinusRaw, // -inf -1 -0 0 1 inf nan
MinusRaw, // -inf -1 -0 0 1 inf nan
/// Prints `-` for the negative non-zero values, or `+` otherwise.
MinusPlus, // -inf -1 +0 +0 +1 +inf nan
MinusPlus, // -inf -1 +0 +0 +1 +inf nan
/// Prints `-` for any negative values (including the negative zero), or `+` otherwise.
MinusPlusRaw, // -inf -1 -0 +0 +1 +inf nan
}
@@ -374,11 +407,35 @@ fn determine_sign(sign: Sign, decoded: &FullDecoded, negative: bool) -> &'static
match (*decoded, sign) {
(FullDecoded::Nan, _) => b"",
(FullDecoded::Zero, Sign::Minus) => b"",
(FullDecoded::Zero, Sign::MinusRaw) => if negative { b"-" } else { b"" },
(FullDecoded::Zero, Sign::MinusRaw) => {
if negative {
b"-"
} else {
b""
}
}
(FullDecoded::Zero, Sign::MinusPlus) => b"+",
(FullDecoded::Zero, Sign::MinusPlusRaw) => if negative { b"-" } else { b"+" },
(_, Sign::Minus) | (_, Sign::MinusRaw) => if negative { b"-" } else { b"" },
(_, Sign::MinusPlus) | (_, Sign::MinusPlusRaw) => if negative { b"-" } else { b"+" },
(FullDecoded::Zero, Sign::MinusPlusRaw) => {
if negative {
b"-"
} else {
b"+"
}
}
(_, Sign::Minus) | (_, Sign::MinusRaw) => {
if negative {
b"-"
} else {
b""
}
}
(_, Sign::MinusPlus) | (_, Sign::MinusPlusRaw) => {
if negative {
b"-"
} else {
b"+"
}
}
}
}
@@ -400,10 +457,19 @@ fn determine_sign(sign: Sign, decoded: &FullDecoded, negative: bool) -> &'static
/// The byte buffer should be at least `MAX_SIG_DIGITS` bytes long.
/// There should be at least 4 parts available, due to the worst case like
/// `[+][0.][0000][2][0000]` with `frac_digits = 10`.
pub fn to_shortest_str<'a, T, F>(mut format_shortest: F, v: T,
sign: Sign, frac_digits: usize, _upper: bool,
buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a>
where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
pub fn to_shortest_str<'a, T, F>(
mut format_shortest: F,
v: T,
sign: Sign,
frac_digits: usize,
_upper: bool,
buf: &'a mut [u8],
parts: &'a mut [Part<'a>],
) -> Formatted<'a>
where
T: DecodableFloat,
F: FnMut(&Decoded, &mut [u8]) -> (usize, i16),
{
assert!(parts.len() >= 4);
assert!(buf.len() >= MAX_SIG_DIGITS);
@@ -419,7 +485,8 @@ pub fn to_shortest_str<'a, T, F>(mut format_shortest: F, v: T,
Formatted { sign, parts: &parts[..1] }
}
FullDecoded::Zero => {
if frac_digits > 0 { // [0.][0000]
if frac_digits > 0 {
// [0.][0000]
parts[0] = Part::Copy(b"0.");
parts[1] = Part::Zero(frac_digits);
Formatted { sign, parts: &parts[..2] }
@@ -430,8 +497,7 @@ pub fn to_shortest_str<'a, T, F>(mut format_shortest: F, v: T,
}
FullDecoded::Finite(ref decoded) => {
let (len, exp) = format_shortest(decoded, buf);
Formatted { sign,
parts: digits_to_dec_str(&buf[..len], exp, frac_digits, parts) }
Formatted { sign, parts: digits_to_dec_str(&buf[..len], exp, frac_digits, parts) }
}
}
}
@@ -455,10 +521,19 @@ pub fn to_shortest_str<'a, T, F>(mut format_shortest: F, v: T,
/// The byte buffer should be at least `MAX_SIG_DIGITS` bytes long.
/// There should be at least 6 parts available, due to the worst case like
/// `[+][1][.][2345][e][-][6]`.
pub fn to_shortest_exp_str<'a, T, F>(mut format_shortest: F, v: T,
sign: Sign, dec_bounds: (i16, i16), upper: bool,
buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a>
where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
pub fn to_shortest_exp_str<'a, T, F>(
mut format_shortest: F,
v: T,
sign: Sign,
dec_bounds: (i16, i16),
upper: bool,
buf: &'a mut [u8],
parts: &'a mut [Part<'a>],
) -> Formatted<'a>
where
T: DecodableFloat,
F: FnMut(&Decoded, &mut [u8]) -> (usize, i16),
{
assert!(parts.len() >= 6);
assert!(buf.len() >= MAX_SIG_DIGITS);
assert!(dec_bounds.0 <= dec_bounds.1);
@@ -534,10 +609,19 @@ fn estimate_max_buf_len(exp: i16) -> usize {
/// (The tipping point for `f64` is about 800, so 1000 bytes should be enough.)
/// There should be at least 6 parts available, due to the worst case like
/// `[+][1][.][2345][e][-][6]`.
pub fn to_exact_exp_str<'a, T, F>(mut format_exact: F, v: T,
sign: Sign, ndigits: usize, upper: bool,
buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a>
where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
pub fn to_exact_exp_str<'a, T, F>(
mut format_exact: F,
v: T,
sign: Sign,
ndigits: usize,
upper: bool,
buf: &'a mut [u8],
parts: &'a mut [Part<'a>],
) -> Formatted<'a>
where
T: DecodableFloat,
F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16),
{
assert!(parts.len() >= 6);
assert!(ndigits > 0);
@@ -553,7 +637,8 @@ pub fn to_exact_exp_str<'a, T, F>(mut format_exact: F, v: T,
Formatted { sign, parts: &parts[..1] }
}
FullDecoded::Zero => {
if ndigits > 1 { // [0.][0000][e0]
if ndigits > 1 {
// [0.][0000][e0]
parts[0] = Part::Copy(b"0.");
parts[1] = Part::Zero(ndigits - 1);
parts[2] = Part::Copy(if upper { b"E0" } else { b"e0" });
@@ -569,8 +654,7 @@ pub fn to_exact_exp_str<'a, T, F>(mut format_exact: F, v: T,
let trunc = if ndigits < maxlen { ndigits } else { maxlen };
let (len, exp) = format_exact(decoded, &mut buf[..trunc], i16::MIN);
Formatted { sign,
parts: digits_to_exp_str(&buf[..len], exp, ndigits, upper, parts) }
Formatted { sign, parts: digits_to_exp_str(&buf[..len], exp, ndigits, upper, parts) }
}
}
}
@@ -590,10 +674,19 @@ pub fn to_exact_exp_str<'a, T, F>(mut format_exact: F, v: T,
/// (The tipping point for `f64` is about 800, and 1000 bytes should be enough.)
/// There should be at least 4 parts available, due to the worst case like
/// `[+][0.][0000][2][0000]` with `frac_digits = 10`.
pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, v: T,
sign: Sign, frac_digits: usize, _upper: bool,
buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a>
where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
pub fn to_exact_fixed_str<'a, T, F>(
mut format_exact: F,
v: T,
sign: Sign,
frac_digits: usize,
_upper: bool,
buf: &'a mut [u8],
parts: &'a mut [Part<'a>],
) -> Formatted<'a>
where
T: DecodableFloat,
F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16),
{
assert!(parts.len() >= 4);
let (negative, full_decoded) = decode(v);
@@ -608,7 +701,8 @@ pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, v: T,
Formatted { sign, parts: &parts[..1] }
}
FullDecoded::Zero => {
if frac_digits > 0 { // [0.][0000]
if frac_digits > 0 {
// [0.][0000]
parts[0] = Part::Copy(b"0.");
parts[1] = Part::Zero(frac_digits);
Formatted { sign, parts: &parts[..2] }
@@ -631,7 +725,8 @@ pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, v: T,
// `exp` was. this does not include the case that the restriction has been met
// only after the final rounding-up; it's a regular case with `exp = limit + 1`.
debug_assert_eq!(len, 0);
if frac_digits > 0 { // [0.][0000]
if frac_digits > 0 {
// [0.][0000]
parts[0] = Part::Copy(b"0.");
parts[1] = Part::Zero(frac_digits);
Formatted { sign, parts: &parts[..2] }
@@ -640,8 +735,7 @@ pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, v: T,
Formatted { sign, parts: &parts[..1] }
}
} else {
Formatted { sign,
parts: digits_to_dec_str(&buf[..len], exp, frac_digits, parts) }
Formatted { sign, parts: digits_to_dec_str(&buf[..len], exp, frac_digits, parts) }
}
}
}

View File

@@ -6,38 +6,54 @@
use crate::cmp::Ordering;
use crate::num::flt2dec::{Decoded, MAX_SIG_DIGITS, round_up};
use crate::num::flt2dec::estimator::estimate_scaling_factor;
use crate::num::bignum::Digit32 as Digit;
use crate::num::bignum::Big32x40 as Big;
use crate::num::bignum::Digit32 as Digit;
use crate::num::flt2dec::estimator::estimate_scaling_factor;
use crate::num::flt2dec::{round_up, Decoded, MAX_SIG_DIGITS};
static POW10: [Digit; 10] = [1, 10, 100, 1000, 10000, 100000,
1000000, 10000000, 100000000, 1000000000];
static TWOPOW10: [Digit; 10] = [2, 20, 200, 2000, 20000, 200000,
2000000, 20000000, 200000000, 2000000000];
static POW10: [Digit; 10] =
[1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000];
static TWOPOW10: [Digit; 10] =
[2, 20, 200, 2000, 20000, 200000, 2000000, 20000000, 200000000, 2000000000];
// precalculated arrays of `Digit`s for 10^(2^n)
static POW10TO16: [Digit; 2] = [0x6fc10000, 0x2386f2];
static POW10TO32: [Digit; 4] = [0, 0x85acef81, 0x2d6d415b, 0x4ee];
static POW10TO64: [Digit; 7] = [0, 0, 0xbf6a1f01, 0x6e38ed64, 0xdaa797ed, 0xe93ff9f4, 0x184f03];
static POW10TO128: [Digit; 14] =
[0, 0, 0, 0, 0x2e953e01, 0x3df9909, 0xf1538fd, 0x2374e42f, 0xd3cff5ec, 0xc404dc08,
0xbccdb0da, 0xa6337f19, 0xe91f2603, 0x24e];
static POW10TO256: [Digit; 27] =
[0, 0, 0, 0, 0, 0, 0, 0, 0x982e7c01, 0xbed3875b, 0xd8d99f72, 0x12152f87, 0x6bde50c6,
0xcf4a6e70, 0xd595d80f, 0x26b2716e, 0xadc666b0, 0x1d153624, 0x3c42d35a, 0x63ff540e,
0xcc5573c0, 0x65f9ef17, 0x55bc28f2, 0x80dcc7f7, 0xf46eeddc, 0x5fdcefce, 0x553f7];
static POW10TO128: [Digit; 14] = [
0, 0, 0, 0, 0x2e953e01, 0x3df9909, 0xf1538fd, 0x2374e42f, 0xd3cff5ec, 0xc404dc08, 0xbccdb0da,
0xa6337f19, 0xe91f2603, 0x24e,
];
static POW10TO256: [Digit; 27] = [
0, 0, 0, 0, 0, 0, 0, 0, 0x982e7c01, 0xbed3875b, 0xd8d99f72, 0x12152f87, 0x6bde50c6, 0xcf4a6e70,
0xd595d80f, 0x26b2716e, 0xadc666b0, 0x1d153624, 0x3c42d35a, 0x63ff540e, 0xcc5573c0, 0x65f9ef17,
0x55bc28f2, 0x80dcc7f7, 0xf46eeddc, 0x5fdcefce, 0x553f7,
];
#[doc(hidden)]
pub fn mul_pow10(x: &mut Big, n: usize) -> &mut Big {
debug_assert!(n < 512);
if n & 7 != 0 { x.mul_small(POW10[n & 7]); }
if n & 8 != 0 { x.mul_small(POW10[8]); }
if n & 16 != 0 { x.mul_digits(&POW10TO16); }
if n & 32 != 0 { x.mul_digits(&POW10TO32); }
if n & 64 != 0 { x.mul_digits(&POW10TO64); }
if n & 128 != 0 { x.mul_digits(&POW10TO128); }
if n & 256 != 0 { x.mul_digits(&POW10TO256); }
if n & 7 != 0 {
x.mul_small(POW10[n & 7]);
}
if n & 8 != 0 {
x.mul_small(POW10[8]);
}
if n & 16 != 0 {
x.mul_digits(&POW10TO16);
}
if n & 32 != 0 {
x.mul_digits(&POW10TO32);
}
if n & 64 != 0 {
x.mul_digits(&POW10TO64);
}
if n & 128 != 0 {
x.mul_digits(&POW10TO128);
}
if n & 256 != 0 {
x.mul_digits(&POW10TO256);
}
x
}
@@ -52,13 +68,30 @@ fn div_2pow10(x: &mut Big, mut n: usize) -> &mut Big {
}
// only usable when `x < 16 * scale`; `scaleN` should be `scale.mul_small(N)`
fn div_rem_upto_16<'a>(x: &'a mut Big, scale: &Big,
scale2: &Big, scale4: &Big, scale8: &Big) -> (u8, &'a mut Big) {
fn div_rem_upto_16<'a>(
x: &'a mut Big,
scale: &Big,
scale2: &Big,
scale4: &Big,
scale8: &Big,
) -> (u8, &'a mut Big) {
let mut d = 0;
if *x >= *scale8 { x.sub(scale8); d += 8; }
if *x >= *scale4 { x.sub(scale4); d += 4; }
if *x >= *scale2 { x.sub(scale2); d += 2; }
if *x >= *scale { x.sub(scale); d += 1; }
if *x >= *scale8 {
x.sub(scale8);
d += 8;
}
if *x >= *scale4 {
x.sub(scale4);
d += 4;
}
if *x >= *scale2 {
x.sub(scale2);
d += 2;
}
if *x >= *scale {
x.sub(scale);
d += 1;
}
debug_assert!(*x < *scale);
(d, x)
}
@@ -85,7 +118,7 @@ pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/*#digits*/ usize, /*exp
assert!(buf.len() >= MAX_SIG_DIGITS);
// `a.cmp(&b) < rounding` is `if d.inclusive {a <= b} else {a < b}`
let rounding = if d.inclusive {Ordering::Greater} else {Ordering::Equal};
let rounding = if d.inclusive { Ordering::Greater } else { Ordering::Equal };
// estimate `k_0` from original inputs satisfying `10^(k_0-1) < high <= 10^(k_0+1)`.
// the tight bound `k` satisfying `10^(k-1) < high <= 10^k` is calculated later.
@@ -132,9 +165,12 @@ pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/*#digits*/ usize, /*exp
}
// cache `(2, 4, 8) * scale` for digit generation.
let mut scale2 = scale.clone(); scale2.mul_pow2(1);
let mut scale4 = scale.clone(); scale4.mul_pow2(2);
let mut scale8 = scale.clone(); scale8.mul_pow2(3);
let mut scale2 = scale.clone();
scale2.mul_pow2(1);
let mut scale4 = scale.clone();
scale4.mul_pow2(2);
let mut scale8 = scale.clone();
scale8.mul_pow2(3);
let mut down;
let mut up;
@@ -186,7 +222,9 @@ pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/*#digits*/ usize, /*exp
// - keep generating otherwise.
down = mant.cmp(&minus) < rounding;
up = scale.cmp(mant.clone().add(&plus)) < rounding;
if down || up { break; } // we have the shortest representation, proceed to the rounding
if down || up {
break;
} // we have the shortest representation, proceed to the rounding
// restore the invariants.
// this makes the algorithm always terminating: `minus` and `plus` always increases,
@@ -269,22 +307,40 @@ pub fn format_exact(d: &Decoded, buf: &mut [u8], limit: i16) -> (/*#digits*/ usi
if len > 0 {
// cache `(2, 4, 8) * scale` for digit generation.
// (this can be expensive, so do not calculate them when the buffer is empty.)
let mut scale2 = scale.clone(); scale2.mul_pow2(1);
let mut scale4 = scale.clone(); scale4.mul_pow2(2);
let mut scale8 = scale.clone(); scale8.mul_pow2(3);
let mut scale2 = scale.clone();
scale2.mul_pow2(1);
let mut scale4 = scale.clone();
scale4.mul_pow2(2);
let mut scale8 = scale.clone();
scale8.mul_pow2(3);
for i in 0..len {
if mant.is_zero() { // following digits are all zeroes, we stop here
if mant.is_zero() {
// following digits are all zeroes, we stop here
// do *not* try to perform rounding! rather, fill remaining digits.
for c in &mut buf[i..len] { *c = b'0'; }
for c in &mut buf[i..len] {
*c = b'0';
}
return (len, k);
}
let mut d = 0;
if mant >= scale8 { mant.sub(&scale8); d += 8; }
if mant >= scale4 { mant.sub(&scale4); d += 4; }
if mant >= scale2 { mant.sub(&scale2); d += 2; }
if mant >= scale { mant.sub(&scale); d += 1; }
if mant >= scale8 {
mant.sub(&scale8);
d += 8;
}
if mant >= scale4 {
mant.sub(&scale4);
d += 4;
}
if mant >= scale2 {
mant.sub(&scale2);
d += 2;
}
if mant >= scale {
mant.sub(&scale);
d += 1;
}
debug_assert!(mant < scale);
debug_assert!(d < 10);
buf[i] = b'0' + d;
@@ -296,8 +352,9 @@ pub fn format_exact(d: &Decoded, buf: &mut [u8], limit: i16) -> (/*#digits*/ usi
// if the following digits are exactly 5000..., check the prior digit and try to
// round to even (i.e., avoid rounding up when the prior digit is even).
let order = mant.cmp(scale.mul_small(5));
if order == Ordering::Greater || (order == Ordering::Equal &&
(len == 0 || buf[len-1] & 1 == 1)) {
if order == Ordering::Greater
|| (order == Ordering::Equal && (len == 0 || buf[len - 1] & 1 == 1))
{
// if rounding up changes the length, the exponent should also change.
// but we've been requested a fixed number of digits, so do not alter the buffer...
if let Some(c) = round_up(buf, len) {

View File

@@ -6,12 +6,13 @@
//! accurately with integers. SIGPLAN Not. 45, 6 (June 2010), 233-243.
use crate::num::diy_float::Fp;
use crate::num::flt2dec::{Decoded, MAX_SIG_DIGITS, round_up};
use crate::num::flt2dec::{round_up, Decoded, MAX_SIG_DIGITS};
// see the comments in `format_shortest_opt` for the rationale.
#[doc(hidden)] pub const ALPHA: i16 = -60;
#[doc(hidden)] pub const GAMMA: i16 = -32;
#[doc(hidden)]
pub const ALPHA: i16 = -60;
#[doc(hidden)]
pub const GAMMA: i16 = -32;
/*
# the following Python code generates this table:
@@ -24,92 +25,95 @@ for i in xrange(-308, 333, 8):
*/
#[doc(hidden)]
pub static CACHED_POW10: [(u64, i16, i16); 81] = [ // (f, e, k)
pub static CACHED_POW10: [(u64, i16, i16); 81] = [
// (f, e, k)
(0xe61acf033d1a45df, -1087, -308),
(0xab70fe17c79ac6ca, -1060, -300),
(0xff77b1fcbebcdc4f, -1034, -292),
(0xbe5691ef416bd60c, -1007, -284),
(0x8dd01fad907ffc3c, -980, -276),
(0xd3515c2831559a83, -954, -268),
(0x9d71ac8fada6c9b5, -927, -260),
(0xea9c227723ee8bcb, -901, -252),
(0xaecc49914078536d, -874, -244),
(0x823c12795db6ce57, -847, -236),
(0xc21094364dfb5637, -821, -228),
(0x9096ea6f3848984f, -794, -220),
(0xd77485cb25823ac7, -768, -212),
(0xa086cfcd97bf97f4, -741, -204),
(0xef340a98172aace5, -715, -196),
(0xb23867fb2a35b28e, -688, -188),
(0x84c8d4dfd2c63f3b, -661, -180),
(0xc5dd44271ad3cdba, -635, -172),
(0x936b9fcebb25c996, -608, -164),
(0xdbac6c247d62a584, -582, -156),
(0xa3ab66580d5fdaf6, -555, -148),
(0xf3e2f893dec3f126, -529, -140),
(0xb5b5ada8aaff80b8, -502, -132),
(0x87625f056c7c4a8b, -475, -124),
(0xc9bcff6034c13053, -449, -116),
(0x964e858c91ba2655, -422, -108),
(0xdff9772470297ebd, -396, -100),
(0xa6dfbd9fb8e5b88f, -369, -92),
(0xf8a95fcf88747d94, -343, -84),
(0xb94470938fa89bcf, -316, -76),
(0x8a08f0f8bf0f156b, -289, -68),
(0xcdb02555653131b6, -263, -60),
(0x993fe2c6d07b7fac, -236, -52),
(0xe45c10c42a2b3b06, -210, -44),
(0xaa242499697392d3, -183, -36),
(0xfd87b5f28300ca0e, -157, -28),
(0xbce5086492111aeb, -130, -20),
(0x8cbccc096f5088cc, -103, -12),
(0xd1b71758e219652c, -77, -4),
(0x9c40000000000000, -50, 4),
(0xe8d4a51000000000, -24, 12),
(0xad78ebc5ac620000, 3, 20),
(0x813f3978f8940984, 30, 28),
(0xc097ce7bc90715b3, 56, 36),
(0x8f7e32ce7bea5c70, 83, 44),
(0xd5d238a4abe98068, 109, 52),
(0x9f4f2726179a2245, 136, 60),
(0xed63a231d4c4fb27, 162, 68),
(0xb0de65388cc8ada8, 189, 76),
(0x83c7088e1aab65db, 216, 84),
(0xc45d1df942711d9a, 242, 92),
(0x924d692ca61be758, 269, 100),
(0xda01ee641a708dea, 295, 108),
(0xa26da3999aef774a, 322, 116),
(0xf209787bb47d6b85, 348, 124),
(0xb454e4a179dd1877, 375, 132),
(0x865b86925b9bc5c2, 402, 140),
(0xc83553c5c8965d3d, 428, 148),
(0x952ab45cfa97a0b3, 455, 156),
(0xde469fbd99a05fe3, 481, 164),
(0xa59bc234db398c25, 508, 172),
(0xf6c69a72a3989f5c, 534, 180),
(0xb7dcbf5354e9bece, 561, 188),
(0x88fcf317f22241e2, 588, 196),
(0xcc20ce9bd35c78a5, 614, 204),
(0x98165af37b2153df, 641, 212),
(0xe2a0b5dc971f303a, 667, 220),
(0xa8d9d1535ce3b396, 694, 228),
(0xfb9b7cd9a4a7443c, 720, 236),
(0xbb764c4ca7a44410, 747, 244),
(0x8bab8eefb6409c1a, 774, 252),
(0xd01fef10a657842c, 800, 260),
(0x9b10a4e5e9913129, 827, 268),
(0xe7109bfba19c0c9d, 853, 276),
(0xac2820d9623bf429, 880, 284),
(0x80444b5e7aa7cf85, 907, 292),
(0xbf21e44003acdd2d, 933, 300),
(0x8e679c2f5e44ff8f, 960, 308),
(0xd433179d9c8cb841, 986, 316),
(0x9e19db92b4e31ba9, 1013, 324),
(0xeb96bf6ebadf77d9, 1039, 332),
(0x8dd01fad907ffc3c, -980, -276),
(0xd3515c2831559a83, -954, -268),
(0x9d71ac8fada6c9b5, -927, -260),
(0xea9c227723ee8bcb, -901, -252),
(0xaecc49914078536d, -874, -244),
(0x823c12795db6ce57, -847, -236),
(0xc21094364dfb5637, -821, -228),
(0x9096ea6f3848984f, -794, -220),
(0xd77485cb25823ac7, -768, -212),
(0xa086cfcd97bf97f4, -741, -204),
(0xef340a98172aace5, -715, -196),
(0xb23867fb2a35b28e, -688, -188),
(0x84c8d4dfd2c63f3b, -661, -180),
(0xc5dd44271ad3cdba, -635, -172),
(0x936b9fcebb25c996, -608, -164),
(0xdbac6c247d62a584, -582, -156),
(0xa3ab66580d5fdaf6, -555, -148),
(0xf3e2f893dec3f126, -529, -140),
(0xb5b5ada8aaff80b8, -502, -132),
(0x87625f056c7c4a8b, -475, -124),
(0xc9bcff6034c13053, -449, -116),
(0x964e858c91ba2655, -422, -108),
(0xdff9772470297ebd, -396, -100),
(0xa6dfbd9fb8e5b88f, -369, -92),
(0xf8a95fcf88747d94, -343, -84),
(0xb94470938fa89bcf, -316, -76),
(0x8a08f0f8bf0f156b, -289, -68),
(0xcdb02555653131b6, -263, -60),
(0x993fe2c6d07b7fac, -236, -52),
(0xe45c10c42a2b3b06, -210, -44),
(0xaa242499697392d3, -183, -36),
(0xfd87b5f28300ca0e, -157, -28),
(0xbce5086492111aeb, -130, -20),
(0x8cbccc096f5088cc, -103, -12),
(0xd1b71758e219652c, -77, -4),
(0x9c40000000000000, -50, 4),
(0xe8d4a51000000000, -24, 12),
(0xad78ebc5ac620000, 3, 20),
(0x813f3978f8940984, 30, 28),
(0xc097ce7bc90715b3, 56, 36),
(0x8f7e32ce7bea5c70, 83, 44),
(0xd5d238a4abe98068, 109, 52),
(0x9f4f2726179a2245, 136, 60),
(0xed63a231d4c4fb27, 162, 68),
(0xb0de65388cc8ada8, 189, 76),
(0x83c7088e1aab65db, 216, 84),
(0xc45d1df942711d9a, 242, 92),
(0x924d692ca61be758, 269, 100),
(0xda01ee641a708dea, 295, 108),
(0xa26da3999aef774a, 322, 116),
(0xf209787bb47d6b85, 348, 124),
(0xb454e4a179dd1877, 375, 132),
(0x865b86925b9bc5c2, 402, 140),
(0xc83553c5c8965d3d, 428, 148),
(0x952ab45cfa97a0b3, 455, 156),
(0xde469fbd99a05fe3, 481, 164),
(0xa59bc234db398c25, 508, 172),
(0xf6c69a72a3989f5c, 534, 180),
(0xb7dcbf5354e9bece, 561, 188),
(0x88fcf317f22241e2, 588, 196),
(0xcc20ce9bd35c78a5, 614, 204),
(0x98165af37b2153df, 641, 212),
(0xe2a0b5dc971f303a, 667, 220),
(0xa8d9d1535ce3b396, 694, 228),
(0xfb9b7cd9a4a7443c, 720, 236),
(0xbb764c4ca7a44410, 747, 244),
(0x8bab8eefb6409c1a, 774, 252),
(0xd01fef10a657842c, 800, 260),
(0x9b10a4e5e9913129, 827, 268),
(0xe7109bfba19c0c9d, 853, 276),
(0xac2820d9623bf429, 880, 284),
(0x80444b5e7aa7cf85, 907, 292),
(0xbf21e44003acdd2d, 933, 300),
(0x8e679c2f5e44ff8f, 960, 308),
(0xd433179d9c8cb841, 986, 316),
(0x9e19db92b4e31ba9, 1013, 324),
(0xeb96bf6ebadf77d9, 1039, 332),
];
#[doc(hidden)] pub const CACHED_POW10_FIRST_E: i16 = -1087;
#[doc(hidden)] pub const CACHED_POW10_LAST_E: i16 = 1039;
#[doc(hidden)]
pub const CACHED_POW10_FIRST_E: i16 = -1087;
#[doc(hidden)]
pub const CACHED_POW10_LAST_E: i16 = 1039;
#[doc(hidden)]
pub fn cached_power(alpha: i16, gamma: i16) -> (i16, Fp) {
@@ -128,30 +132,39 @@ pub fn max_pow10_no_more_than(x: u32) -> (u8, u32) {
debug_assert!(x > 0);
const X9: u32 = 10_0000_0000;
const X8: u32 = 1_0000_0000;
const X7: u32 = 1000_0000;
const X6: u32 = 100_0000;
const X5: u32 = 10_0000;
const X4: u32 = 1_0000;
const X3: u32 = 1000;
const X2: u32 = 100;
const X1: u32 = 10;
const X8: u32 = 1_0000_0000;
const X7: u32 = 1000_0000;
const X6: u32 = 100_0000;
const X5: u32 = 10_0000;
const X4: u32 = 1_0000;
const X3: u32 = 1000;
const X2: u32 = 100;
const X1: u32 = 10;
if x < X4 {
if x < X2 { if x < X1 {(0, 1)} else {(1, X1)} }
else { if x < X3 {(2, X2)} else {(3, X3)} }
if x < X2 {
if x < X1 { (0, 1) } else { (1, X1) }
} else {
if x < X3 { (2, X2) } else { (3, X3) }
}
} else {
if x < X6 { if x < X5 {(4, X4)} else {(5, X5)} }
else if x < X8 { if x < X7 {(6, X6)} else {(7, X7)} }
else { if x < X9 {(8, X8)} else {(9, X9)} }
if x < X6 {
if x < X5 { (4, X4) } else { (5, X5) }
} else if x < X8 {
if x < X7 { (6, X6) } else { (7, X7) }
} else {
if x < X9 { (8, X8) } else { (9, X9) }
}
}
}
/// The shortest mode implementation for Grisu.
///
/// It returns `None` when it would return an inexact representation otherwise.
pub fn format_shortest_opt(d: &Decoded,
buf: &mut [u8]) -> Option<(/*#digits*/ usize, /*exp*/ i16)> {
pub fn format_shortest_opt(
d: &Decoded,
buf: &mut [u8],
) -> Option<(/*#digits*/ usize, /*exp*/ i16)> {
assert!(d.mant > 0);
assert!(d.minus > 0);
assert!(d.plus > 0);
@@ -208,8 +221,8 @@ pub fn format_shortest_opt(d: &Decoded,
// we start with the correct repr within the unsafe region, and try to find the closest repr
// to `v` which is also within the safe region. if we can't, we give up.
let plus1 = plus.f + 1;
// let plus0 = plus.f - 1; // only for explanation
// let minus0 = minus.f + 1; // only for explanation
// let plus0 = plus.f - 1; // only for explanation
// let minus0 = minus.f + 1; // only for explanation
let minus1 = minus.f - 1;
let e = -plus.e as usize; // shared exponent
@@ -235,14 +248,15 @@ pub fn format_shortest_opt(d: &Decoded,
// (e.g., `x` = 32000, `y` = 32777; `kappa` = 2 since `y mod 10^3 = 777 < y - x = 777`.)
// the algorithm relies on the later verification phase to exclude `y`.
let delta1 = plus1 - minus1;
// let delta1int = (delta1 >> e) as usize; // only for explanation
// let delta1int = (delta1 >> e) as usize; // only for explanation
let delta1frac = delta1 & ((1 << e) - 1);
// render integral parts, while checking for the accuracy at each step.
let mut kappa = max_kappa as i16;
let mut ten_kappa = max_ten_kappa; // 10^kappa
let mut remainder = plus1int; // digits yet to be rendered
loop { // we always have at least one digit to render, as `plus1 >= 10^kappa`
loop {
// we always have at least one digit to render, as `plus1 >= 10^kappa`
// invariants:
// - `delta1int <= remainder < 10^(kappa+1)`
// - `plus1int = d[0..n-1] * 10^(kappa+1) + remainder`
@@ -281,7 +295,8 @@ pub fn format_shortest_opt(d: &Decoded,
let mut remainder = plus1frac;
let mut threshold = delta1frac;
let mut ulp = 1;
loop { // the next digit should be significant as we've tested that before breaking out
loop {
// the next digit should be significant as we've tested that before breaking out
// invariants, where `m = max_kappa + 1` (# of digits in the integral part):
// - `remainder < 2^e`
// - `plus1frac * 10^(n-m) = d[m..n-1] * 2^e + remainder`
@@ -300,8 +315,15 @@ pub fn format_shortest_opt(d: &Decoded,
if r < threshold {
let ten_kappa = 1 << e; // implicit divisor
return round_and_weed(&mut buf[..i], exp, r, threshold,
(plus1 - v.f) * ulp, ten_kappa, ulp);
return round_and_weed(
&mut buf[..i],
exp,
r,
threshold,
(plus1 - v.f) * ulp,
ten_kappa,
ulp,
);
}
// restore invariants
@@ -325,8 +347,15 @@ pub fn format_shortest_opt(d: &Decoded,
// - `plus1v = (plus1 - v) * k` (and also, `threshold > plus1v` from prior invariants)
// - `ten_kappa = 10^kappa * k`
// - `ulp = 2^-e * k`
fn round_and_weed(buf: &mut [u8], exp: i16, remainder: u64, threshold: u64, plus1v: u64,
ten_kappa: u64, ulp: u64) -> Option<(usize, i16)> {
fn round_and_weed(
buf: &mut [u8],
exp: i16,
remainder: u64,
threshold: u64,
plus1v: u64,
ten_kappa: u64,
ulp: u64,
) -> Option<(usize, i16)> {
assert!(!buf.is_empty());
// produce two approximations to `v` (actually `plus1 - v`) within 1.5 ulps.
@@ -381,10 +410,11 @@ pub fn format_shortest_opt(d: &Decoded,
//
// consequently, we should stop when `TC1 || TC2 || (TC3a && TC3b)`. the following is
// equal to its inverse, `!TC1 && !TC2 && (!TC3a || !TC3b)`.
while plus1w < plus1v_up &&
threshold - plus1w >= ten_kappa &&
(plus1w + ten_kappa < plus1v_up ||
plus1v_up - plus1w >= plus1w + ten_kappa - plus1v_up) {
while plus1w < plus1v_up
&& threshold - plus1w >= ten_kappa
&& (plus1w + ten_kappa < plus1v_up
|| plus1v_up - plus1w >= plus1w + ten_kappa - plus1v_up)
{
*last -= 1;
debug_assert!(*last > b'0'); // the shortest repr cannot end with `0`
plus1w += ten_kappa;
@@ -395,10 +425,11 @@ pub fn format_shortest_opt(d: &Decoded,
//
// this is simply same to the terminating conditions for `v + 1 ulp`, with all `plus1v_up`
// replaced by `plus1v_down` instead. overflow analysis equally holds.
if plus1w < plus1v_down &&
threshold - plus1w >= ten_kappa &&
(plus1w + ten_kappa < plus1v_down ||
plus1v_down - plus1w >= plus1w + ten_kappa - plus1v_down) {
if plus1w < plus1v_down
&& threshold - plus1w >= ten_kappa
&& (plus1w + ten_kappa < plus1v_down
|| plus1v_down - plus1w >= plus1w + ten_kappa - plus1v_down)
{
return None;
}
@@ -428,8 +459,11 @@ pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/*#digits*/ usize, /*exp
/// The exact and fixed mode implementation for Grisu.
///
/// It returns `None` when it would return an inexact representation otherwise.
pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16)
-> Option<(/*#digits*/ usize, /*exp*/ i16)> {
pub fn format_exact_opt(
d: &Decoded,
buf: &mut [u8],
limit: i16,
) -> Option<(/*#digits*/ usize, /*exp*/ i16)> {
assert!(d.mant > 0);
assert!(d.mant < (1 << 61)); // we need at least three bits of additional precision
assert!(!buf.is_empty());
@@ -489,7 +523,8 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16)
let mut kappa = max_kappa as i16;
let mut ten_kappa = max_ten_kappa; // 10^kappa
let mut remainder = vint; // digits yet to be rendered
loop { // we always have at least one digit to render
loop {
// we always have at least one digit to render
// invariants:
// - `remainder < 10^(kappa+1)`
// - `vint = d[0..n-1] * 10^(kappa+1) + remainder`
@@ -575,8 +610,15 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16)
// - `remainder = (v % 10^kappa) * k`
// - `ten_kappa = 10^kappa * k`
// - `ulp = 2^-e * k`
fn possibly_round(buf: &mut [u8], mut len: usize, mut exp: i16, limit: i16,
remainder: u64, ten_kappa: u64, ulp: u64) -> Option<(usize, i16)> {
fn possibly_round(
buf: &mut [u8],
mut len: usize,
mut exp: i16,
limit: i16,
remainder: u64,
ten_kappa: u64,
ulp: u64,
) -> Option<(usize, i16)> {
debug_assert!(remainder < ten_kappa);
// 10^kappa
@@ -593,7 +635,9 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16)
//
// error is too large that there are at least three possible representations
// between `v - 1 ulp` and `v + 1 ulp`. we cannot determine which one is correct.
if ulp >= ten_kappa { return None; }
if ulp >= ten_kappa {
return None;
}
// 10^kappa
// :<------->:
@@ -607,7 +651,9 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16)
// in fact, 1/2 ulp is enough to introduce two possible representations.
// (remember that we need a unique representation for both `v - 1 ulp` and `v + 1 ulp`.)
// this won't overflow, as `ulp < ten_kappa` from the first check.
if ten_kappa - ulp <= ulp { return None; }
if ten_kappa - ulp <= ulp {
return None;
}
// remainder
// :<->| :

View File

@@ -4,7 +4,7 @@ use crate::ops::*;
#[allow(unused_macros)]
macro_rules! sh_impl_signed {
($t:ident, $f:ident) => (
($t:ident, $f:ident) => {
#[stable(feature = "rust1", since = "1.0.0")]
impl Shl<$f> for Wrapping<$t> {
type Output = Wrapping<$t>;
@@ -19,7 +19,7 @@ macro_rules! sh_impl_signed {
}
}
forward_ref_binop! { impl Shl, shl for Wrapping<$t>, $f,
#[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
#[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
#[stable(feature = "op_assign_traits", since = "1.8.0")]
impl ShlAssign<$f> for Wrapping<$t> {
@@ -44,7 +44,7 @@ macro_rules! sh_impl_signed {
}
}
forward_ref_binop! { impl Shr, shr for Wrapping<$t>, $f,
#[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
#[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
#[stable(feature = "op_assign_traits", since = "1.8.0")]
impl ShrAssign<$f> for Wrapping<$t> {
@@ -54,11 +54,11 @@ macro_rules! sh_impl_signed {
}
}
forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f }
)
};
}
macro_rules! sh_impl_unsigned {
($t:ident, $f:ident) => (
($t:ident, $f:ident) => {
#[stable(feature = "rust1", since = "1.0.0")]
impl Shl<$f> for Wrapping<$t> {
type Output = Wrapping<$t>;
@@ -69,7 +69,7 @@ macro_rules! sh_impl_unsigned {
}
}
forward_ref_binop! { impl Shl, shl for Wrapping<$t>, $f,
#[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
#[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
#[stable(feature = "op_assign_traits", since = "1.8.0")]
impl ShlAssign<$f> for Wrapping<$t> {
@@ -90,7 +90,7 @@ macro_rules! sh_impl_unsigned {
}
}
forward_ref_binop! { impl Shr, shr for Wrapping<$t>, $f,
#[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
#[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
#[stable(feature = "op_assign_traits", since = "1.8.0")]
impl ShrAssign<$f> for Wrapping<$t> {
@@ -100,7 +100,7 @@ macro_rules! sh_impl_unsigned {
}
}
forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f }
)
};
}
// FIXME (#23545): uncomment the remaining impls