1- //! Arbitrary-precision decimal class for fallback algorithms.
1+ //! Arbitrary-precision decimal type used by fallback algorithms.
22//!
33//! This is only used if the fast-path (native floats) and
44//! the Eisel-Lemire algorithm are unable to unambiguously
1111
1212use crate :: num:: dec2flt:: common:: { ByteSlice , is_8digits} ;
1313
14+ /// A decimal floating-point number.
1415#[ derive( Clone ) ]
1516pub struct Decimal {
1617 /// The number of significant digits in the decimal.
@@ -30,18 +31,17 @@ impl Default for Decimal {
3031}
3132
3233impl Decimal {
33- /// The maximum number of digits required to unambiguously round a float.
34+ /// The maximum number of digits required to unambiguously round up to a 64-bit float.
3435 ///
35- /// For a double-precision IEEE 754 float, this required 767 digits,
36- /// so we store the max digits + 1.
36+ /// For an IEEE 754 binary64 float, this required 767 digits. So we store the max digits + 1.
3737 ///
3838 /// We can exactly represent a float in radix `b` from radix 2 if
3939 /// `b` is divisible by 2. This function calculates the exact number of
4040 /// digits required to exactly represent that float.
4141 ///
4242 /// According to the "Handbook of Floating Point Arithmetic",
43- /// for IEEE754, with emin being the min exponent, p2 being the
44- /// precision, and b being the radix, the number of digits follows as:
43+ /// for IEEE754, with ` emin` being the min exponent, `p2` being the
44+ /// precision, and `b` being the radix, the number of digits follows as:
4545 ///
4646 /// `−emin + p2 + ⌊(emin + 1) log(2, b) − log(1 − 2^(−p2), b)⌋`
4747 ///
@@ -56,11 +56,14 @@ impl Decimal {
5656 /// In Python:
5757 /// `-emin + p2 + math.floor((emin+ 1)*math.log(2, b)-math.log(1-2**(-p2), b))`
5858 pub const MAX_DIGITS : usize = 768 ;
59- /// The max digits that can be exactly represented in a 64-bit integer.
59+ /// The max decimal digits that can be exactly represented in a 64-bit integer.
6060 pub const MAX_DIGITS_WITHOUT_OVERFLOW : usize = 19 ;
6161 pub const DECIMAL_POINT_RANGE : i32 = 2047 ;
6262
63- /// Append a digit to the buffer.
63+ /// Append a digit to the buffer if it fits.
64+ // FIXME(tgross35): it may be better for this to return an option
65+ // FIXME(tgross35): incrementing the digit counter even if we don't push anything
66+ // seems incorrect.
6467 pub fn try_add_digit ( & mut self , digit : u8 ) {
6568 if self . num_digits < Self :: MAX_DIGITS {
6669 self . digits [ self . num_digits ] = digit;
@@ -69,6 +72,7 @@ impl Decimal {
6972 }
7073
7174 /// Trim trailing zeros from the buffer.
75+ // FIXME(tgross35): this could be `.rev().position()` if perf is okay
7276 pub fn trim ( & mut self ) {
7377 // All of the following calls to `Decimal::trim` can't panic because:
7478 //
@@ -86,7 +90,7 @@ impl Decimal {
8690 pub fn round ( & self ) -> u64 {
8791 if self . num_digits == 0 || self . decimal_point < 0 {
8892 return 0 ;
89- } else if self . decimal_point > 18 {
93+ } else if self . decimal_point >= Self :: MAX_DIGITS_WITHOUT_OVERFLOW as i32 {
9094 return 0xFFFF_FFFF_FFFF_FFFF_u64 ;
9195 }
9296 let dp = self . decimal_point as usize ;
0 commit comments