1111
1212use crate :: num:: dec2flt:: common:: { ByteSlice , is_8digits} ;
1313
14- /// A decimal floating-point number.
15- #[ derive( Clone ) ]
16- pub struct Decimal {
14+ /// A decimal floating-point number, represented as a sequence of decimal digits .
15+ #[ derive( Clone , Debug , PartialEq ) ]
16+ pub struct DecimalSeq {
1717 /// The number of significant digits in the decimal.
1818 pub num_digits : usize ,
1919 /// The offset of the decimal point in the significant digits.
@@ -24,13 +24,13 @@ pub struct Decimal {
2424 pub digits : [ u8 ; Self :: MAX_DIGITS ] ,
2525}
2626
27- impl Default for Decimal {
27+ impl Default for DecimalSeq {
2828 fn default ( ) -> Self {
2929 Self { num_digits : 0 , decimal_point : 0 , truncated : false , digits : [ 0 ; Self :: MAX_DIGITS ] }
3030 }
3131}
3232
33- impl Decimal {
33+ impl DecimalSeq {
3434 /// The maximum number of digits required to unambiguously round up to a 64-bit float.
3535 ///
3636 /// For an IEEE 754 binary64 float, this required 767 digits. So we store the max digits + 1.
@@ -74,11 +74,11 @@ impl Decimal {
7474 /// Trim trailing zeros from the buffer.
7575 // FIXME(tgross35): this could be `.rev().position()` if perf is okay
7676 pub fn trim ( & mut self ) {
77- // All of the following calls to `Decimal ::trim` can't panic because:
77+ // All of the following calls to `DecimalSeq ::trim` can't panic because:
7878 //
79- // 1. `parse_decimal` sets `num_digits` to a max of `Decimal ::MAX_DIGITS`.
79+ // 1. `parse_decimal` sets `num_digits` to a max of `DecimalSeq ::MAX_DIGITS`.
8080 // 2. `right_shift` sets `num_digits` to `write_index`, which is bounded by `num_digits`.
81- // 3. `left_shift` `num_digits` to a max of `Decimal ::MAX_DIGITS`.
81+ // 3. `left_shift` `num_digits` to a max of `DecimalSeq ::MAX_DIGITS`.
8282 //
8383 // Trim is only called in `right_shift` and `left_shift`.
8484 debug_assert ! ( self . num_digits <= Self :: MAX_DIGITS ) ;
@@ -93,21 +93,26 @@ impl Decimal {
9393 } else if self . decimal_point >= Self :: MAX_DIGITS_WITHOUT_OVERFLOW as i32 {
9494 return 0xFFFF_FFFF_FFFF_FFFF_u64 ;
9595 }
96+
9697 let dp = self . decimal_point as usize ;
9798 let mut n = 0_u64 ;
99+
98100 for i in 0 ..dp {
99101 n *= 10 ;
100102 if i < self . num_digits {
101103 n += self . digits [ i] as u64 ;
102104 }
103105 }
106+
104107 let mut round_up = false ;
108+
105109 if dp < self . num_digits {
106110 round_up = self . digits [ dp] >= 5 ;
107111 if self . digits [ dp] == 5 && dp + 1 == self . num_digits {
108112 round_up = self . truncated || ( ( dp != 0 ) && ( 1 & self . digits [ dp - 1 ] != 0 ) )
109113 }
110114 }
115+
111116 if round_up {
112117 n += 1 ;
113118 }
@@ -123,6 +128,7 @@ impl Decimal {
123128 let mut read_index = self . num_digits ;
124129 let mut write_index = self . num_digits + num_new_digits;
125130 let mut n = 0_u64 ;
131+
126132 while read_index != 0 {
127133 read_index -= 1 ;
128134 write_index -= 1 ;
@@ -136,6 +142,7 @@ impl Decimal {
136142 }
137143 n = quotient;
138144 }
145+
139146 while n > 0 {
140147 write_index -= 1 ;
141148 let quotient = n / 10 ;
@@ -147,10 +154,13 @@ impl Decimal {
147154 }
148155 n = quotient;
149156 }
157+
150158 self . num_digits += num_new_digits;
159+
151160 if self . num_digits > Self :: MAX_DIGITS {
152161 self . num_digits = Self :: MAX_DIGITS ;
153162 }
163+
154164 self . decimal_point += num_new_digits as i32 ;
155165 self . trim ( ) ;
156166 }
@@ -206,8 +216,8 @@ impl Decimal {
206216}
207217
208218/// Parse a big integer representation of the float as a decimal.
209- pub fn parse_decimal ( mut s : & [ u8 ] ) -> Decimal {
210- let mut d = Decimal :: default ( ) ;
219+ pub fn parse_decimal_seq ( mut s : & [ u8 ] ) -> DecimalSeq {
220+ let mut d = DecimalSeq :: default ( ) ;
211221 let start = s;
212222
213223 while let Some ( ( & b'0' , s_next) ) = s. split_first ( ) {
@@ -225,7 +235,7 @@ pub fn parse_decimal(mut s: &[u8]) -> Decimal {
225235 s = s_next;
226236 }
227237 }
228- while s. len ( ) >= 8 && d. num_digits + 8 < Decimal :: MAX_DIGITS {
238+ while s. len ( ) >= 8 && d. num_digits + 8 < DecimalSeq :: MAX_DIGITS {
229239 let v = s. read_u64 ( ) ;
230240 if !is_8digits ( v) {
231241 break ;
@@ -237,6 +247,7 @@ pub fn parse_decimal(mut s: &[u8]) -> Decimal {
237247 s = s. parse_digits ( |digit| d. try_add_digit ( digit) ) ;
238248 d. decimal_point = s. len ( ) as i32 - first. len ( ) as i32 ;
239249 }
250+
240251 if d. num_digits != 0 {
241252 // Ignore the trailing zeros if there are any
242253 let mut n_trailing_zeros = 0 ;
@@ -250,11 +261,12 @@ pub fn parse_decimal(mut s: &[u8]) -> Decimal {
250261 d. decimal_point += n_trailing_zeros as i32 ;
251262 d. num_digits -= n_trailing_zeros;
252263 d. decimal_point += d. num_digits as i32 ;
253- if d. num_digits > Decimal :: MAX_DIGITS {
264+ if d. num_digits > DecimalSeq :: MAX_DIGITS {
254265 d. truncated = true ;
255- d. num_digits = Decimal :: MAX_DIGITS ;
266+ d. num_digits = DecimalSeq :: MAX_DIGITS ;
256267 }
257268 }
269+
258270 if let Some ( ( & ch, s_next) ) = s. split_first ( ) {
259271 if ch == b'e' || ch == b'E' {
260272 s = s_next;
@@ -276,13 +288,15 @@ pub fn parse_decimal(mut s: &[u8]) -> Decimal {
276288 d. decimal_point += if neg_exp { -exp_num } else { exp_num } ;
277289 }
278290 }
279- for i in d. num_digits ..Decimal :: MAX_DIGITS_WITHOUT_OVERFLOW {
291+
292+ for i in d. num_digits ..DecimalSeq :: MAX_DIGITS_WITHOUT_OVERFLOW {
280293 d. digits [ i] = 0 ;
281294 }
295+
282296 d
283297}
284298
285- fn number_of_digits_decimal_left_shift ( d : & Decimal , mut shift : usize ) -> usize {
299+ fn number_of_digits_decimal_left_shift ( d : & DecimalSeq , mut shift : usize ) -> usize {
286300 #[ rustfmt:: skip]
287301 const TABLE : [ u16 ; 65 ] = [
288302 0x0000 , 0x0800 , 0x0801 , 0x0803 , 0x1006 , 0x1009 , 0x100D , 0x1812 , 0x1817 , 0x181D , 0x2024 ,
@@ -347,6 +361,7 @@ fn number_of_digits_decimal_left_shift(d: &Decimal, mut shift: usize) -> usize {
347361 let pow5_a = ( 0x7FF & x_a) as usize ;
348362 let pow5_b = ( 0x7FF & x_b) as usize ;
349363 let pow5 = & TABLE_POW5 [ pow5_a..] ;
364+
350365 for ( i, & p5) in pow5. iter ( ) . enumerate ( ) . take ( pow5_b - pow5_a) {
351366 if i >= d. num_digits {
352367 return num_new_digits - 1 ;
@@ -358,5 +373,6 @@ fn number_of_digits_decimal_left_shift(d: &Decimal, mut shift: usize) -> usize {
358373 return num_new_digits;
359374 }
360375 }
376+
361377 num_new_digits
362378}
0 commit comments