// Convert words of q to base b digits in s. If q is large, it is recursively "split in half"
// by nat/nat division using tabulated divisors. Otherwise, it is converted iteratively using
// repeated nat/Word divison.
//
// The iterative method processes n Words by n divW() calls, each of which visits every Word in the 
// incrementally shortened q for a total of n + (n-1) + (n-2) ... + 2 + 1, or n(n+1)/2 divW()'s. 
// Recursive conversion divides q by its approximate square root, yielding two parts, each half 
// the size of q. Using the iterative method on both halves means 2 * (n/2)(n/2 + 1)/2 divW()'s
// plus the expensive long div(). Asymptotically, the ratio is favorable at 1/2 the divW()'s, and
// is made better by splitting the subblocks recursively. Best is to split blocks until one more 
// split would take longer (because of the nat/nat div()) than the twice as many divW()'s of the 
// iterative approach. This threshold is represented by leafSize. Benchmarking of leafSize in the 
// range 2..64 shows that values of 8 and 16 work well, with a 4x speedup at medium lengths and 
// ~30x for 20000 digits. Use nat_test.go's BenchmarkLeafSize tests to optimize leafSize for 
// specific hardware.
//
Convert words of q to base b digits in s. If q is large, it is recursively "split in half"
by nat/nat division using tabulated divisors. Otherwise, it is converted iteratively using
repeated nat/Word divison.

The iterative method processes n Words by n divW() calls, each of which visits every Word in the
incrementally shortened q for a total of n + (n-1) + (n-2) ...
// Convert words of q to base b digits in s . If q is large it is recursively " split in half " // by nat / nat division using tabulated divisors . Otherwise it is converted iteratively using // repeated nat / Word divison . // // The iterative method processes n Words by n divW () calls each of which visits every Word in the // incrementally shortened q for a total of n + ( n - 1 ) + ( n - 2 ) ... + 2 + 1 or n ( n + 1 ) / 2 divW () ' s . // Recursive conversion divides q by its approximate square root yielding two parts each half // the size of q . Using the iterative method on both halves means 2 * ( n / 2 ) ( n / 2 + 1 ) / 2 divW () ' s // plus the expensive long div () . Asymptotically the ratio is favorable at 1 / 2 the divW () ' s and // is made better by splitting the subblocks recursively . Best is to split blocks until one more // split would take longer ( because of the nat / nat div () ) than the twice as many divW () ' s of the // iterative approach . This threshold is represented by leafSize . Benchmarking of leafSize in the // range 2 .. 64 shows that values of 8 and 16 work well with a 4x speedup at medium lengths and // ~30x for 20000 digits . Use nat_test . go ' s BenchmarkLeafSize tests to optimize leafSize for // specific hardware . //
func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word, table []divisor) {
	if table != nil {
		var r nat
		index := len(table) - 1
		for len(q) > leafSize {
			maxLength := q.bitLen()     
			minLength := maxLength >> 1 
			for index > 0 && table[index-1].nbits > minLength {
				index-- 
			}
			if table[index].nbits >= maxLength && table[index].bbb.cmp(q) >= 0 {
				index--
				if index < 0 {
					panic("internal inconsistency")
				}
			}
			q, r = q.div(r, q, table[index].bbb)
			h := len(s) - table[index].ndigits
			r.convertWords(s[h:], charset, b, ndigits, bb, table[0:index])
			s = s[:h] 
		}
	}
	i := len(s)
	var r Word
	if b == 10 {
		for len(q) > 0 {
			q, r = q.divW(q, bb)
			for j := 0; j < ndigits && i > 0; j++ {
				i--
				t := r / 10
				s[i] = charset[r-t<<3-t-t] 
				r = t
			}
		}
	} else {
		for len(q) > 0 {
			q, r = q.divW(q, bb)
			for j := 0; j < ndigits && i > 0; j++ {
				i--
				s[i] = charset[r%b]
				r /= b
			}
		}
	}
	zero := charset[0]
	for i > 0 { 
		i--
		s[i] = zero
	}
}
func ( q nat ) convertWords ( s [ ] byte , charset string , b Word , ndigits int , bb Word , table [ ] divisor ) { if table != nil { var r nat index := len ( table ) - 1 for len ( q ) > leafSize { maxLength := q . bitLen ( ) minLength := maxLength >> 1 for index > 0 && table [ index - 1 ] . nbits > minLength { index -- } if table [ index ] . nbits >= maxLength && table [ index ] . bbb . cmp ( q ) >= 0 { index -- if index < 0 { panic ( " " ) } } q , r = q . div ( r , q , table [ index ] . bbb ) h := len ( s ) - table [ index ] . ndigits r . convertWords ( s [ h : ] , charset , b , ndigits , bb , table [ 0 : index ] ) s = s [ : h ] } } i := len ( s ) var r Word if b == 10 { for len ( q ) > 0 { q , r = q . divW ( q , bb ) for j := 0 ; j < ndigits && i > 0 ; j ++ { i -- t := r / 10 s [ i ] = charset [ r - t << 3 - t - t ] r = t } } } else { for len ( q ) > 0 { q , r = q . divW ( q , bb ) for j := 0 ; j < ndigits && i > 0 ; j ++ { i -- s [ i ] = charset [ r % b ] r /= b } } } zero := charset [ 0 ] for i > 0 { i -- s [ i ] = zero } }
Convert words of q to base b digits in s. If q is large, it is recursively "split in half"
by nat/nat division using tabulated divisors.
Convert words of q to base b digits in s . If q is large it is recursively " split in half " by nat / nat division using tabulated divisors .
// split larger blocks recursively // len(q) > leafSize > 0 // find divisor close to sqrt(q) if possible, but in any case < q // ~= log2 q, or at of least largest possible q of this bit length // ~= log2 sqrt(q) // desired // split q into the two digit number (q'*bbb + r) to form independent subblocks // convert subblocks and collect results in s[:h] and s[h:] // == q.convertWords(s, charset, b, ndigits, bb, table[0:index+1]) // having split any large blocks now process the remaining (small) block iteratively // hard-coding for 10 here speeds this up by 1.25x (allows for / and % by constants) // extract least significant, base bb "digit" // avoid % computation since r%10 == r - int(r/10)*10; // this appears to be faster for BenchmarkString10000Base10 // and smaller strings (but a bit slower for larger ones) // TODO(gri) replace w/ t*10 once compiler produces better code // extract least significant, base bb "digit" // prepend high-order zeroes // while need more leading zeroes