github.com/q45/go@v0.0.0-20151101211701-a4fb8c13db3f/src/cmd/compile/internal/big/natconv.go (about)

     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  	if b < 2 || b > 256 {
   256  		panic("invalid character set length")
   257  	}
   258  
   259  	// x == 0
   260  	if len(x) == 0 {
   261  		return string(charset[0])
   262  	}
   263  	// len(x) > 0
   264  
   265  	// allocate buffer for conversion
   266  	i := int(float64(x.bitLen())/math.Log2(float64(b))) + 1 // off by one at most
   267  	s := make([]byte, i)
   268  
   269  	// convert power of two and non power of two bases separately
   270  	if b == b&-b {
   271  		// shift is base b digit size in bits
   272  		shift := trailingZeroBits(b) // shift > 0 because b >= 2
   273  		mask := Word(1<<shift - 1)
   274  		w := x[0]         // current word
   275  		nbits := uint(_W) // number of unprocessed bits in w
   276  
   277  		// convert less-significant words (include leading zeros)
   278  		for k := 1; k < len(x); k++ {
   279  			// convert full digits
   280  			for nbits >= shift {
   281  				i--
   282  				s[i] = charset[w&mask]
   283  				w >>= shift
   284  				nbits -= shift
   285  			}
   286  
   287  			// convert any partial leading digit and advance to next word
   288  			if nbits == 0 {
   289  				// no partial digit remaining, just advance
   290  				w = x[k]
   291  				nbits = _W
   292  			} else {
   293  				// partial digit in current word w (== x[k-1]) and next word x[k]
   294  				w |= x[k] << nbits
   295  				i--
   296  				s[i] = charset[w&mask]
   297  
   298  				// advance
   299  				w = x[k] >> (shift - nbits)
   300  				nbits = _W - (shift - nbits)
   301  			}
   302  		}
   303  
   304  		// convert digits of most-significant word w (omit leading zeros)
   305  		for w != 0 {
   306  			i--
   307  			s[i] = charset[w&mask]
   308  			w >>= 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 zeros
   413  	zero := charset[0]
   414  	for i > 0 { // while need more leading zeros
   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 zeros) ~= 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  }