Home | History | Annotate | Download | only in big
      1 // Copyright 2015 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // This file implements nat-to-string conversion functions.
      6 
      7 package big
      8 
      9 import (
     10 	"errors"
     11 	"fmt"
     12 	"io"
     13 	"math"
     14 	"sync"
     15 )
     16 
     17 // MaxBase is the largest number base accepted for string conversions.
     18 const MaxBase = 'z' - 'a' + 10 + 1
     19 
     20 // maxPow returns (b**n, n) such that b**n is the largest power b**n <= _M.
     21 // For instance maxPow(10) == (1e19, 19) for 19 decimal digits in a 64bit Word.
     22 // In other words, at most n digits in base b fit into a Word.
     23 // TODO(gri) replace this with a table, generated at build time.
     24 func maxPow(b Word) (p Word, n int) {
     25 	p, n = b, 1 // assuming b <= _M
     26 	for max := _M / b; p <= max; {
     27 		// p == b**n && p <= max
     28 		p *= b
     29 		n++
     30 	}
     31 	// p == b**n && p <= _M
     32 	return
     33 }
     34 
     35 // pow returns x**n for n > 0, and 1 otherwise.
     36 func pow(x Word, n int) (p Word) {
     37 	// n == sum of bi * 2**i, for 0 <= i < imax, and bi is 0 or 1
     38 	// thus x**n == product of x**(2**i) for all i where bi == 1
     39 	// (Russian Peasant Method for exponentiation)
     40 	p = 1
     41 	for n > 0 {
     42 		if n&1 != 0 {
     43 			p *= x
     44 		}
     45 		x *= x
     46 		n >>= 1
     47 	}
     48 	return
     49 }
     50 
     51 // scan scans the number corresponding to the longest possible prefix
     52 // from r representing an unsigned number in a given conversion base.
     53 // It returns the corresponding natural number res, the actual base b,
     54 // a digit count, and a read or syntax error err, if any.
     55 //
     56 //	number   = [ prefix ] mantissa .
     57 //	prefix   = "0" [ "x" | "X" | "b" | "B" ] .
     58 //      mantissa = digits | digits "." [ digits ] | "." digits .
     59 //	digits   = digit { digit } .
     60 //	digit    = "0" ... "9" | "a" ... "z" | "A" ... "Z" .
     61 //
     62 // Unless fracOk is set, the base argument must be 0 or a value between
     63 // 2 and MaxBase. If fracOk is set, the base argument must be one of
     64 // 0, 2, 10, or 16. Providing an invalid base argument leads to a run-
     65 // time panic.
     66 //
     67 // For base 0, the number prefix determines the actual base: A prefix of
     68 // ``0x'' or ``0X'' selects base 16; if fracOk is not set, the ``0'' prefix
     69 // selects base 8, and a ``0b'' or ``0B'' prefix selects base 2. Otherwise
     70 // the selected base is 10 and no prefix is accepted.
     71 //
     72 // If fracOk is set, an octal prefix is ignored (a leading ``0'' simply
     73 // stands for a zero digit), and a period followed by a fractional part
     74 // is permitted. The result value is computed as if there were no period
     75 // present; and the count value is used to determine the fractional part.
     76 //
     77 // A result digit count > 0 corresponds to the number of (non-prefix) digits
     78 // parsed. A digit count <= 0 indicates the presence of a period (if fracOk
     79 // is set, only), and -count is the number of fractional digits found.
     80 // In this case, the actual value of the scanned number is res * b**count.
     81 //
     82 func (z nat) scan(r io.ByteScanner, base int, fracOk bool) (res nat, b, count int, err error) {
     83 	// reject illegal bases
     84 	baseOk := base == 0 ||
     85 		!fracOk && 2 <= base && base <= MaxBase ||
     86 		fracOk && (base == 2 || base == 10 || base == 16)
     87 	if !baseOk {
     88 		panic(fmt.Sprintf("illegal number base %d", base))
     89 	}
     90 
     91 	// one char look-ahead
     92 	ch, err := r.ReadByte()
     93 	if err != nil {
     94 		return
     95 	}
     96 
     97 	// determine actual base
     98 	b = base
     99 	if base == 0 {
    100 		// actual base is 10 unless there's a base prefix
    101 		b = 10
    102 		if ch == '0' {
    103 			count = 1
    104 			switch ch, err = r.ReadByte(); err {
    105 			case nil:
    106 				// possibly one of 0x, 0X, 0b, 0B
    107 				if !fracOk {
    108 					b = 8
    109 				}
    110 				switch ch {
    111 				case 'x', 'X':
    112 					b = 16
    113 				case 'b', 'B':
    114 					b = 2
    115 				}
    116 				switch b {
    117 				case 16, 2:
    118 					count = 0 // prefix is not counted
    119 					if ch, err = r.ReadByte(); err != nil {
    120 						// io.EOF is also an error in this case
    121 						return
    122 					}
    123 				case 8:
    124 					count = 0 // prefix is not counted
    125 				}
    126 			case io.EOF:
    127 				// input is "0"
    128 				res = z[:0]
    129 				err = nil
    130 				return
    131 			default:
    132 				// read error
    133 				return
    134 			}
    135 		}
    136 	}
    137 
    138 	// convert string
    139 	// Algorithm: Collect digits in groups of at most n digits in di
    140 	// and then use mulAddWW for every such group to add them to the
    141 	// result.
    142 	z = z[:0]
    143 	b1 := Word(b)
    144 	bn, n := maxPow(b1) // at most n digits in base b1 fit into Word
    145 	di := Word(0)       // 0 <= di < b1**i < bn
    146 	i := 0              // 0 <= i < n
    147 	dp := -1            // position of decimal point
    148 	for {
    149 		if fracOk && ch == '.' {
    150 			fracOk = false
    151 			dp = count
    152 			// advance
    153 			if ch, err = r.ReadByte(); err != nil {
    154 				if err == io.EOF {
    155 					err = nil
    156 					break
    157 				}
    158 				return
    159 			}
    160 		}
    161 
    162 		// convert rune into digit value d1
    163 		var d1 Word
    164 		switch {
    165 		case '0' <= ch && ch <= '9':
    166 			d1 = Word(ch - '0')
    167 		case 'a' <= ch && ch <= 'z':
    168 			d1 = Word(ch - 'a' + 10)
    169 		case 'A' <= ch && ch <= 'Z':
    170 			d1 = Word(ch - 'A' + 10)
    171 		default:
    172 			d1 = MaxBase + 1
    173 		}
    174 		if d1 >= b1 {
    175 			r.UnreadByte() // ch does not belong to number anymore
    176 			break
    177 		}
    178 		count++
    179 
    180 		// collect d1 in di
    181 		di = di*b1 + d1
    182 		i++
    183 
    184 		// if di is "full", add it to the result
    185 		if i == n {
    186 			z = z.mulAddWW(z, bn, di)
    187 			di = 0
    188 			i = 0
    189 		}
    190 
    191 		// advance
    192 		if ch, err = r.ReadByte(); err != nil {
    193 			if err == io.EOF {
    194 				err = nil
    195 				break
    196 			}
    197 			return
    198 		}
    199 	}
    200 
    201 	if count == 0 {
    202 		// no digits found
    203 		switch {
    204 		case base == 0 && b == 8:
    205 			// there was only the octal prefix 0 (possibly followed by digits > 7);
    206 			// count as one digit and return base 10, not 8
    207 			count = 1
    208 			b = 10
    209 		case base != 0 || b != 8:
    210 			// there was neither a mantissa digit nor the octal prefix 0
    211 			err = errors.New("syntax error scanning number")
    212 		}
    213 		return
    214 	}
    215 	// count > 0
    216 
    217 	// add remaining digits to result
    218 	if i > 0 {
    219 		z = z.mulAddWW(z, pow(b1, i), di)
    220 	}
    221 	res = z.norm()
    222 
    223 	// adjust for fraction, if any
    224 	if dp >= 0 {
    225 		// 0 <= dp <= count > 0
    226 		count = dp - count
    227 	}
    228 
    229 	return
    230 }
    231 
    232 // Character sets for string conversion.
    233 const (
    234 	lowercaseDigits = "0123456789abcdefghijklmnopqrstuvwxyz"
    235 	uppercaseDigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    236 )
    237 
    238 // decimalString returns a decimal representation of x.
    239 // It calls x.string with the charset "0123456789".
    240 func (x nat) decimalString() string {
    241 	return x.string(lowercaseDigits[:10])
    242 }
    243 
    244 // hexString returns a hexadecimal representation of x.
    245 // It calls x.string with the charset "0123456789abcdef".
    246 func (x nat) hexString() string {
    247 	return x.string(lowercaseDigits[:16])
    248 }
    249 
    250 // string converts x to a string using digits from a charset; a digit with
    251 // value d is represented by charset[d]. The conversion base is determined
    252 // by len(charset), which must be >= 2 and <= 256.
    253 func (x nat) string(charset string) string {
    254 	b := Word(len(charset))
    255 
    256 	// special cases
    257 	switch {
    258 	case b < 2 || b > 256:
    259 		panic("invalid character set length")
    260 	case len(x) == 0:
    261 		return string(charset[0])
    262 	}
    263 
    264 	// allocate buffer for conversion
    265 	i := int(float64(x.bitLen())/math.Log2(float64(b))) + 1 // off by one at most
    266 	s := make([]byte, i)
    267 
    268 	// convert power of two and non power of two bases separately
    269 	if b == b&-b {
    270 		// shift is base-b digit size in bits
    271 		shift := trailingZeroBits(b) // shift > 0 because b >= 2
    272 		mask := Word(1)<<shift - 1
    273 		w := x[0]
    274 		nbits := uint(_W) // number of unprocessed bits in w
    275 
    276 		// convert less-significant words
    277 		for k := 1; k < len(x); k++ {
    278 			// convert full digits
    279 			for nbits >= shift {
    280 				i--
    281 				s[i] = charset[w&mask]
    282 				w >>= shift
    283 				nbits -= shift
    284 			}
    285 
    286 			// convert any partial leading digit and advance to next word
    287 			if nbits == 0 {
    288 				// no partial digit remaining, just advance
    289 				w = x[k]
    290 				nbits = _W
    291 			} else {
    292 				// partial digit in current (k-1) and next (k) word
    293 				w |= x[k] << nbits
    294 				i--
    295 				s[i] = charset[w&mask]
    296 
    297 				// advance
    298 				w = x[k] >> (shift - nbits)
    299 				nbits = _W - (shift - nbits)
    300 			}
    301 		}
    302 
    303 		// convert digits of most-significant word (omit leading zeros)
    304 		for nbits >= 0 && w != 0 {
    305 			i--
    306 			s[i] = charset[w&mask]
    307 			w >>= shift
    308 			nbits -= shift
    309 		}
    310 
    311 	} else {
    312 		bb, ndigits := maxPow(Word(b))
    313 
    314 		// construct table of successive squares of bb*leafSize to use in subdivisions
    315 		// result (table != nil) <=> (len(x) > leafSize > 0)
    316 		table := divisors(len(x), b, ndigits, bb)
    317 
    318 		// preserve x, create local copy for use by convertWords
    319 		q := nat(nil).set(x)
    320 
    321 		// convert q to string s in base b
    322 		q.convertWords(s, charset, b, ndigits, bb, table)
    323 
    324 		// strip leading zeros
    325 		// (x != 0; thus s must contain at least one non-zero digit
    326 		// and the loop will terminate)
    327 		i = 0
    328 		for zero := charset[0]; s[i] == zero; {
    329 			i++
    330 		}
    331 	}
    332 
    333 	return string(s[i:])
    334 }
    335 
    336 // Convert words of q to base b digits in s. If q is large, it is recursively "split in half"
    337 // by nat/nat division using tabulated divisors. Otherwise, it is converted iteratively using
    338 // repeated nat/Word division.
    339 //
    340 // The iterative method processes n Words by n divW() calls, each of which visits every Word in the
    341 // incrementally shortened q for a total of n + (n-1) + (n-2) ... + 2 + 1, or n(n+1)/2 divW()'s.
    342 // Recursive conversion divides q by its approximate square root, yielding two parts, each half
    343 // the size of q. Using the iterative method on both halves means 2 * (n/2)(n/2 + 1)/2 divW()'s
    344 // plus the expensive long div(). Asymptotically, the ratio is favorable at 1/2 the divW()'s, and
    345 // is made better by splitting the subblocks recursively. Best is to split blocks until one more
    346 // split would take longer (because of the nat/nat div()) than the twice as many divW()'s of the
    347 // iterative approach. This threshold is represented by leafSize. Benchmarking of leafSize in the
    348 // range 2..64 shows that values of 8 and 16 work well, with a 4x speedup at medium lengths and
    349 // ~30x for 20000 digits. Use nat_test.go's BenchmarkLeafSize tests to optimize leafSize for
    350 // specific hardware.
    351 //
    352 func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word, table []divisor) {
    353 	// split larger blocks recursively
    354 	if table != nil {
    355 		// len(q) > leafSize > 0
    356 		var r nat
    357 		index := len(table) - 1
    358 		for len(q) > leafSize {
    359 			// find divisor close to sqrt(q) if possible, but in any case < q
    360 			maxLength := q.bitLen()     // ~= log2 q, or at of least largest possible q of this bit length
    361 			minLength := maxLength >> 1 // ~= log2 sqrt(q)
    362 			for index > 0 && table[index-1].nbits > minLength {
    363 				index-- // desired
    364 			}
    365 			if table[index].nbits >= maxLength && table[index].bbb.cmp(q) >= 0 {
    366 				index--
    367 				if index < 0 {
    368 					panic("internal inconsistency")
    369 				}
    370 			}
    371 
    372 			// split q into the two digit number (q'*bbb + r) to form independent subblocks
    373 			q, r = q.div(r, q, table[index].bbb)
    374 
    375 			// convert subblocks and collect results in s[:h] and s[h:]
    376 			h := len(s) - table[index].ndigits
    377 			r.convertWords(s[h:], charset, b, ndigits, bb, table[0:index])
    378 			s = s[:h] // == q.convertWords(s, charset, b, ndigits, bb, table[0:index+1])
    379 		}
    380 	}
    381 
    382 	// having split any large blocks now process the remaining (small) block iteratively
    383 	i := len(s)
    384 	var r Word
    385 	if b == 10 {
    386 		// hard-coding for 10 here speeds this up by 1.25x (allows for / and % by constants)
    387 		for len(q) > 0 {
    388 			// extract least significant, base bb "digit"
    389 			q, r = q.divW(q, bb)
    390 			for j := 0; j < ndigits && i > 0; j++ {
    391 				i--
    392 				// avoid % computation since r%10 == r - int(r/10)*10;
    393 				// this appears to be faster for BenchmarkString10000Base10
    394 				// and smaller strings (but a bit slower for larger ones)
    395 				t := r / 10
    396 				s[i] = charset[r-t<<3-t-t] // TODO(gri) replace w/ t*10 once compiler produces better code
    397 				r = t
    398 			}
    399 		}
    400 	} else {
    401 		for len(q) > 0 {
    402 			// extract least significant, base bb "digit"
    403 			q, r = q.divW(q, bb)
    404 			for j := 0; j < ndigits && i > 0; j++ {
    405 				i--
    406 				s[i] = charset[r%b]
    407 				r /= b
    408 			}
    409 		}
    410 	}
    411 
    412 	// prepend high-order zeroes
    413 	zero := charset[0]
    414 	for i > 0 { // while need more leading zeroes
    415 		i--
    416 		s[i] = zero
    417 	}
    418 }
    419 
    420 // Split blocks greater than leafSize Words (or set to 0 to disable recursive conversion)
    421 // Benchmark and configure leafSize using: go test -bench="Leaf"
    422 //   8 and 16 effective on 3.0 GHz Xeon "Clovertown" CPU (128 byte cache lines)
    423 //   8 and 16 effective on 2.66 GHz Core 2 Duo "Penryn" CPU
    424 var leafSize int = 8 // number of Word-size binary values treat as a monolithic block
    425 
    426 type divisor struct {
    427 	bbb     nat // divisor
    428 	nbits   int // bit length of divisor (discounting leading zeroes) ~= log2(bbb)
    429 	ndigits int // digit length of divisor in terms of output base digits
    430 }
    431 
    432 var cacheBase10 struct {
    433 	sync.Mutex
    434 	table [64]divisor // cached divisors for base 10
    435 }
    436 
    437 // expWW computes x**y
    438 func (z nat) expWW(x, y Word) nat {
    439 	return z.expNN(nat(nil).setWord(x), nat(nil).setWord(y), nil)
    440 }
    441 
    442 // construct table of powers of bb*leafSize to use in subdivisions
    443 func divisors(m int, b Word, ndigits int, bb Word) []divisor {
    444 	// only compute table when recursive conversion is enabled and x is large
    445 	if leafSize == 0 || m <= leafSize {
    446 		return nil
    447 	}
    448 
    449 	// determine k where (bb**leafSize)**(2**k) >= sqrt(x)
    450 	k := 1
    451 	for words := leafSize; words < m>>1 && k < len(cacheBase10.table); words <<= 1 {
    452 		k++
    453 	}
    454 
    455 	// reuse and extend existing table of divisors or create new table as appropriate
    456 	var table []divisor // for b == 10, table overlaps with cacheBase10.table
    457 	if b == 10 {
    458 		cacheBase10.Lock()
    459 		table = cacheBase10.table[0:k] // reuse old table for this conversion
    460 	} else {
    461 		table = make([]divisor, k) // create new table for this conversion
    462 	}
    463 
    464 	// extend table
    465 	if table[k-1].ndigits == 0 {
    466 		// add new entries as needed
    467 		var larger nat
    468 		for i := 0; i < k; i++ {
    469 			if table[i].ndigits == 0 {
    470 				if i == 0 {
    471 					table[0].bbb = nat(nil).expWW(bb, Word(leafSize))
    472 					table[0].ndigits = ndigits * leafSize
    473 				} else {
    474 					table[i].bbb = nat(nil).mul(table[i-1].bbb, table[i-1].bbb)
    475 					table[i].ndigits = 2 * table[i-1].ndigits
    476 				}
    477 
    478 				// optimization: exploit aggregated extra bits in macro blocks
    479 				larger = nat(nil).set(table[i].bbb)
    480 				for mulAddVWW(larger, larger, b, 0) == 0 {
    481 					table[i].bbb = table[i].bbb.set(larger)
    482 					table[i].ndigits++
    483 				}
    484 
    485 				table[i].nbits = table[i].bbb.bitLen()
    486 			}
    487 		}
    488 	}
    489 
    490 	if b == 10 {
    491 		cacheBase10.Unlock()
    492 	}
    493 
    494 	return table
    495 }
    496