@@ -220,6 +220,15 @@ static DECIMAL_PAIRS: DecimalPairs = DecimalPairs(
220220 8081828384858687888990919293949596979899",
221221) ;
222222
223+ // Returns {value / 100, value % 100} correct for values of up to 4 digits.
224+ fn divmod100 ( value : u32 ) -> ( u32 , u32 ) {
225+ debug_assert ! ( value < 10_000 ) ;
226+ const EXP : u32 = 19 ; // 19 is faster or equal to 12 even for 3 digits.
227+ const SIG : u32 = ( 1 << EXP ) / 100 + 1 ;
228+ let div = ( value * SIG ) >> EXP ; // value / 100
229+ ( div, value - div * 100 )
230+ }
231+
223232/// This function converts a slice of ascii characters into a `&str` starting
224233/// from `offset`.
225234///
@@ -266,25 +275,30 @@ macro_rules! impl_Unsigned {
266275 . expect( "branch is not hit for types that cannot fit 1E4 (u8)" ) ;
267276 let quad = remain % scale;
268277 remain /= scale;
269- let pair1 = ( quad / 100 ) as usize ;
270- let pair2 = ( quad % 100 ) as usize ;
278+ let ( pair1, pair2) = divmod100( quad as u32 ) ;
271279 unsafe {
272- buf[ offset + 0 ] . write( * DECIMAL_PAIRS . 0 . get_unchecked( pair1 * 2 + 0 ) ) ;
273- buf[ offset + 1 ] . write( * DECIMAL_PAIRS . 0 . get_unchecked( pair1 * 2 + 1 ) ) ;
274- buf[ offset + 2 ] . write( * DECIMAL_PAIRS . 0 . get_unchecked( pair2 * 2 + 0 ) ) ;
275- buf[ offset + 3 ] . write( * DECIMAL_PAIRS . 0 . get_unchecked( pair2 * 2 + 1 ) ) ;
280+ buf[ offset + 0 ]
281+ . write( * DECIMAL_PAIRS . 0 . get_unchecked( pair1 as usize * 2 + 0 ) ) ;
282+ buf[ offset + 1 ]
283+ . write( * DECIMAL_PAIRS . 0 . get_unchecked( pair1 as usize * 2 + 1 ) ) ;
284+ buf[ offset + 2 ]
285+ . write( * DECIMAL_PAIRS . 0 . get_unchecked( pair2 as usize * 2 + 0 ) ) ;
286+ buf[ offset + 3 ]
287+ . write( * DECIMAL_PAIRS . 0 . get_unchecked( pair2 as usize * 2 + 1 ) ) ;
276288 }
277289 }
278290
279291 // Format per two digits from the lookup table.
280292 if remain > 9 {
281293 offset -= 2 ;
282294
283- let pair = ( remain % 100 ) as usize ;
284- remain /= 100 ;
295+ let ( last , pair) = divmod100 ( remain as u32 ) ;
296+ remain = last as Self ;
285297 unsafe {
286- buf[ offset + 0 ] . write( * DECIMAL_PAIRS . 0 . get_unchecked( pair * 2 + 0 ) ) ;
287- buf[ offset + 1 ] . write( * DECIMAL_PAIRS . 0 . get_unchecked( pair * 2 + 1 ) ) ;
298+ buf[ offset + 0 ]
299+ . write( * DECIMAL_PAIRS . 0 . get_unchecked( pair as usize * 2 + 0 ) ) ;
300+ buf[ offset + 1 ]
301+ . write( * DECIMAL_PAIRS . 0 . get_unchecked( pair as usize * 2 + 1 ) ) ;
288302 }
289303 }
290304
@@ -349,25 +363,24 @@ impl Unsigned for u128 {
349363 // pull two pairs
350364 let quad = remain % 1_00_00 ;
351365 remain /= 1_00_00 ;
352- let pair1 = ( quad / 100 ) as usize ;
353- let pair2 = ( quad % 100 ) as usize ;
366+ let ( pair1, pair2) = divmod100 ( quad as u32 ) ;
354367 unsafe {
355- buf[ offset + 0 ] . write ( * DECIMAL_PAIRS . 0 . get_unchecked ( pair1 * 2 + 0 ) ) ;
356- buf[ offset + 1 ] . write ( * DECIMAL_PAIRS . 0 . get_unchecked ( pair1 * 2 + 1 ) ) ;
357- buf[ offset + 2 ] . write ( * DECIMAL_PAIRS . 0 . get_unchecked ( pair2 * 2 + 0 ) ) ;
358- buf[ offset + 3 ] . write ( * DECIMAL_PAIRS . 0 . get_unchecked ( pair2 * 2 + 1 ) ) ;
368+ buf[ offset + 0 ] . write ( * DECIMAL_PAIRS . 0 . get_unchecked ( pair1 as usize * 2 + 0 ) ) ;
369+ buf[ offset + 1 ] . write ( * DECIMAL_PAIRS . 0 . get_unchecked ( pair1 as usize * 2 + 1 ) ) ;
370+ buf[ offset + 2 ] . write ( * DECIMAL_PAIRS . 0 . get_unchecked ( pair2 as usize * 2 + 0 ) ) ;
371+ buf[ offset + 3 ] . write ( * DECIMAL_PAIRS . 0 . get_unchecked ( pair2 as usize * 2 + 1 ) ) ;
359372 }
360373 }
361374
362375 // Format per two digits from the lookup table.
363376 if remain > 9 {
364377 offset -= 2 ;
365378
366- let pair = ( remain % 100 ) as usize ;
367- remain /= 100 ;
379+ let ( last , pair) = divmod100 ( remain as u32 ) ;
380+ remain = last as u64 ;
368381 unsafe {
369- buf[ offset + 0 ] . write ( * DECIMAL_PAIRS . 0 . get_unchecked ( pair * 2 + 0 ) ) ;
370- buf[ offset + 1 ] . write ( * DECIMAL_PAIRS . 0 . get_unchecked ( pair * 2 + 1 ) ) ;
382+ buf[ offset + 0 ] . write ( * DECIMAL_PAIRS . 0 . get_unchecked ( pair as usize * 2 + 0 ) ) ;
383+ buf[ offset + 1 ] . write ( * DECIMAL_PAIRS . 0 . get_unchecked ( pair as usize * 2 + 1 ) ) ;
371384 }
372385 }
373386
@@ -398,13 +411,16 @@ fn enc_16lsd<const OFFSET: usize>(buf: &mut [MaybeUninit<u8>], n: u64) {
398411 // pull two pairs
399412 let quad = remain % 1_00_00 ;
400413 remain /= 1_00_00 ;
401- let pair1 = ( quad / 100 ) as usize ;
402- let pair2 = ( quad % 100 ) as usize ;
414+ let ( pair1, pair2) = divmod100 ( quad as u32 ) ;
403415 unsafe {
404- buf[ quad_index * 4 + OFFSET + 0 ] . write ( * DECIMAL_PAIRS . 0 . get_unchecked ( pair1 * 2 + 0 ) ) ;
405- buf[ quad_index * 4 + OFFSET + 1 ] . write ( * DECIMAL_PAIRS . 0 . get_unchecked ( pair1 * 2 + 1 ) ) ;
406- buf[ quad_index * 4 + OFFSET + 2 ] . write ( * DECIMAL_PAIRS . 0 . get_unchecked ( pair2 * 2 + 0 ) ) ;
407- buf[ quad_index * 4 + OFFSET + 3 ] . write ( * DECIMAL_PAIRS . 0 . get_unchecked ( pair2 * 2 + 1 ) ) ;
416+ buf[ quad_index * 4 + OFFSET + 0 ]
417+ . write ( * DECIMAL_PAIRS . 0 . get_unchecked ( pair1 as usize * 2 + 0 ) ) ;
418+ buf[ quad_index * 4 + OFFSET + 1 ]
419+ . write ( * DECIMAL_PAIRS . 0 . get_unchecked ( pair1 as usize * 2 + 1 ) ) ;
420+ buf[ quad_index * 4 + OFFSET + 2 ]
421+ . write ( * DECIMAL_PAIRS . 0 . get_unchecked ( pair2 as usize * 2 + 0 ) ) ;
422+ buf[ quad_index * 4 + OFFSET + 3 ]
423+ . write ( * DECIMAL_PAIRS . 0 . get_unchecked ( pair2 as usize * 2 + 1 ) ) ;
408424 }
409425 }
410426}
0 commit comments