@@ -336,41 +336,102 @@ macro_rules! define_bignum {
336336 ( self , borrow)
337337 }
338338
339- /// Divide self by another bignum, overwriting `q` with the quotient and `r` with the
340- /// remainder.
339+ /// Knuth’s Algorithm D implementation
341340 pub fn div_rem( & self , d: & $name, q: & mut $name, r: & mut $name) {
342- // Stupid slow base-2 long division taken from
343- // https://en.wikipedia.org/wiki/Division_algorithm
344- // FIXME use a greater base ($ty) for the long division.
345341 assert!( !d. is_zero( ) ) ;
346342 let digitbits = <$ty>:: BITS as usize ;
343+
347344 for digit in & mut q. base[ ..] {
348345 * digit = 0 ;
349346 }
350347 for digit in & mut r. base[ ..] {
351348 * digit = 0 ;
352349 }
353- r. size = d. size;
354- q. size = 1 ;
355- let mut q_is_zero = true ;
356- let end = self . bit_length( ) ;
357- for i in ( 0 ..end) . rev( ) {
358- r. mul_pow2( 1 ) ;
359- r. base[ 0 ] |= self . get_bit( i) as $ty;
360- if & * r >= d {
361- r. sub( d) ;
362- // Set bit `i` of q to 1.
363- let digit_idx = i / digitbits;
364- let bit_idx = i % digitbits;
365- if q_is_zero {
366- q. size = digit_idx + 1 ;
367- q_is_zero = false ;
350+
351+ if d. size == 1 {
352+ let mut tmp = self . clone( ) ;
353+ let ( _q, rem) = tmp. div_rem_small( d. base[ 0 ] ) ;
354+ * q = tmp;
355+ r. base[ 0 ] = rem;
356+ r. size = 1 ;
357+ return ;
358+ }
359+
360+ if self . is_zero( ) {
361+ q. size = 1 ;
362+ r. size = 1 ;
363+ return ;
364+ }
365+
366+ q. size = self . size;
367+ r. size = 1 ;
368+ r. base[ 0 ] = 0 ;
369+
370+ for i in ( 0 ..self . size) . rev( ) {
371+ r. mul_pow2( digitbits) ;
372+
373+ r. base[ 0 ] = self . base[ i] ;
374+
375+ while r. size > 1 && r. base[ r. size - 1 ] == 0 {
376+ r. size -= 1 ;
377+ }
378+
379+ if & * r < d {
380+ q. base[ i] = 0 ;
381+ continue ;
382+ }
383+
384+ let r_top = r. base[ r. size - 1 ] as u128 ;
385+ let r_next = if r. size >= 2 { r. base[ r. size - 2 ] as u128 } else { 0u128 } ;
386+ let v = ( r_top << digitbits) | r_next;
387+ let u = d. base[ d. size - 1 ] as u128 ;
388+
389+ // initial estimate
390+ let mut qhat = ( v / u) as $ty;
391+ let base_limit = if digitbits == 64 {
392+ // avoid (1u128<<64) overflow: handle separately
393+ u128 :: MAX as u128
394+ } else {
395+ ( 1u128 << digitbits) - 1
396+ } ;
397+ if ( qhat as u128 ) > base_limit {
398+ qhat = base_limit as $ty;
399+ }
400+
401+ let mut prod = d. clone( ) ;
402+ if qhat != 0 {
403+ prod. mul_small( qhat) ;
404+ } else {
405+ prod. size = 1 ;
406+ prod. base[ 0 ] = 0 ;
407+ }
408+
409+ while & prod > & * r {
410+ qhat = qhat - 1 ;
411+ // we know prod >= d because qhat was at least 1 when prod > r >= d
412+ prod. sub( d) ;
413+ }
414+
415+ // Set quotient digit
416+ q. base[ i] = qhat;
417+
418+ if qhat != 0 {
419+ r. sub( & prod) ;
420+ while r. size > 1 && r. base[ r. size - 1 ] == 0 {
421+ r. size -= 1 ;
368422 }
369- q. base[ digit_idx] |= 1 << bit_idx;
370423 }
371424 }
372- debug_assert!( q. base[ q. size..] . iter( ) . all( |& d| d == 0 ) ) ;
373- debug_assert!( r. base[ r. size..] . iter( ) . all( |& d| d == 0 ) ) ;
425+
426+ let mut qsz = q. size;
427+ while qsz > 1 && q. base[ qsz - 1 ] == 0 {
428+ qsz -= 1 ;
429+ }
430+ q. size = qsz;
431+
432+ if r. size == 0 {
433+ r. size = 1 ;
434+ }
374435 }
375436 }
376437
0 commit comments