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.
5 // This file implements nat-to-string conversion functions.
18 const digits
= "0123456789abcdefghijklmnopqrstuvwxyz"
20 // Note: MaxBase = len(digits), but it must remain a rune constant
21 // for API compatibility.
23 // MaxBase is the largest number base accepted for string conversions.
24 const MaxBase
= 'z' - 'a' + 10 + 1
26 // maxPow returns (b**n, n) such that b**n is the largest power b**n <= _M.
27 // For instance maxPow(10) == (1e19, 19) for 19 decimal digits in a 64bit Word.
28 // In other words, at most n digits in base b fit into a Word.
29 // TODO(gri) replace this with a table, generated at build time.
30 func maxPow(b Word
) (p Word
, n
int) {
31 p
, n
= b
, 1 // assuming b <= _M
32 for max
:= _M
/ b
; p
<= max
; {
33 // p == b**n && p <= max
37 // p == b**n && p <= _M
41 // pow returns x**n for n > 0, and 1 otherwise.
42 func pow(x Word
, n
int) (p Word
) {
43 // n == sum of bi * 2**i, for 0 <= i < imax, and bi is 0 or 1
44 // thus x**n == product of x**(2**i) for all i where bi == 1
45 // (Russian Peasant Method for exponentiation)
57 // scan scans the number corresponding to the longest possible prefix
58 // from r representing an unsigned number in a given conversion base.
59 // It returns the corresponding natural number res, the actual base b,
60 // a digit count, and a read or syntax error err, if any.
62 // number = [ prefix ] mantissa .
63 // prefix = "0" [ "x" | "X" | "b" | "B" ] .
64 // mantissa = digits | digits "." [ digits ] | "." digits .
65 // digits = digit { digit } .
66 // digit = "0" ... "9" | "a" ... "z" | "A" ... "Z" .
68 // Unless fracOk is set, the base argument must be 0 or a value between
69 // 2 and MaxBase. If fracOk is set, the base argument must be one of
70 // 0, 2, 10, or 16. Providing an invalid base argument leads to a run-
73 // For base 0, the number prefix determines the actual base: A prefix of
74 // ``0x'' or ``0X'' selects base 16; if fracOk is not set, the ``0'' prefix
75 // selects base 8, and a ``0b'' or ``0B'' prefix selects base 2. Otherwise
76 // the selected base is 10 and no prefix is accepted.
78 // If fracOk is set, an octal prefix is ignored (a leading ``0'' simply
79 // stands for a zero digit), and a period followed by a fractional part
80 // is permitted. The result value is computed as if there were no period
81 // present; and the count value is used to determine the fractional part.
83 // A result digit count > 0 corresponds to the number of (non-prefix) digits
84 // parsed. A digit count <= 0 indicates the presence of a period (if fracOk
85 // is set, only), and -count is the number of fractional digits found.
86 // In this case, the actual value of the scanned number is res * b**count.
88 func (z nat
) scan(r io
.ByteScanner
, base
int, fracOk
bool) (res nat
, b
, count
int, err error
) {
89 // reject illegal bases
90 baseOk
:= base
== 0 ||
91 !fracOk
&& 2 <= base
&& base
<= MaxBase ||
92 fracOk
&& (base
== 2 || base
== 10 || base
== 16)
94 panic(fmt
.Sprintf("illegal number base %d", base
))
97 // one char look-ahead
98 ch
, err
:= r
.ReadByte()
103 // determine actual base
106 // actual base is 10 unless there's a base prefix
110 switch ch
, err
= r
.ReadByte(); err
{
112 // possibly one of 0x, 0X, 0b, 0B
124 count
= 0 // prefix is not counted
125 if ch
, err
= r
.ReadByte(); err
!= nil {
126 // io.EOF is also an error in this case
130 count
= 0 // prefix is not counted
145 // Algorithm: Collect digits in groups of at most n digits in di
146 // and then use mulAddWW for every such group to add them to the
150 bn
, n
:= maxPow(b1
) // at most n digits in base b1 fit into Word
151 di
:= Word(0) // 0 <= di < b1**i < bn
153 dp
:= -1 // position of decimal point
155 if fracOk
&& ch
== '.' {
159 if ch
, err
= r
.ReadByte(); err
!= nil {
168 // convert rune into digit value d1
171 case '0' <= ch
&& ch
<= '9':
173 case 'a' <= ch
&& ch
<= 'z':
174 d1
= Word(ch
- 'a' + 10)
175 case 'A' <= ch
&& ch
<= 'Z':
176 d1
= Word(ch
- 'A' + 10)
181 r
.UnreadByte() // ch does not belong to number anymore
190 // if di is "full", add it to the result
192 z
= z
.mulAddWW(z
, bn
, di
)
198 if ch
, err
= r
.ReadByte(); err
!= nil {
210 case base
== 0 && b
== 8:
211 // there was only the octal prefix 0 (possibly followed by digits > 7);
212 // count as one digit and return base 10, not 8
215 case base
!= 0 || b
!= 8:
216 // there was neither a mantissa digit nor the octal prefix 0
217 err
= errors
.New("syntax error scanning number")
223 // add remaining digits to result
225 z
= z
.mulAddWW(z
, pow(b1
, i
), di
)
229 // adjust for fraction, if any
231 // 0 <= dp <= count > 0
238 // utoa converts x to an ASCII representation in the given base;
239 // base must be between 2 and MaxBase, inclusive.
240 func (x nat
) utoa(base
int) []byte {
241 return x
.itoa(false, base
)
244 // itoa is like utoa but it prepends a '-' if neg && x != 0.
245 func (x nat
) itoa(neg
bool, base
int) []byte {
246 if base
< 2 || base
> MaxBase
{
247 panic("invalid base")
256 // allocate buffer for conversion
257 i
:= int(float64(x
.bitLen())/math
.Log2(float64(base
))) + 1 // off by 1 at most
263 // convert power of two and non power of two bases separately
264 if b
:= Word(base
); b
== b
&-b
{
265 // shift is base b digit size in bits
266 shift
:= uint(bits
.TrailingZeros(uint(b
))) // shift > 0 because b >= 2
267 mask
:= Word(1<<shift
- 1)
268 w
:= x
[0] // current word
269 nbits
:= uint(_W
) // number of unprocessed bits in w
271 // convert less-significant words (include leading zeros)
272 for k
:= 1; k
< len(x
); k
++ {
273 // convert full digits
276 s
[i
] = digits
[w
&mask
]
281 // convert any partial leading digit and advance to next word
283 // no partial digit remaining, just advance
287 // partial digit in current word w (== x[k-1]) and next word x[k]
290 s
[i
] = digits
[w
&mask
]
293 w
= x
[k
] >> (shift
- nbits
)
294 nbits
= _W
- (shift
- nbits
)
298 // convert digits of most-significant word w (omit leading zeros)
301 s
[i
] = digits
[w
&mask
]
306 bb
, ndigits
:= maxPow(b
)
308 // construct table of successive squares of bb*leafSize to use in subdivisions
309 // result (table != nil) <=> (len(x) > leafSize > 0)
310 table
:= divisors(len(x
), b
, ndigits
, bb
)
312 // preserve x, create local copy for use by convertWords
315 // convert q to string s in base b
316 q
.convertWords(s
, b
, ndigits
, bb
, table
)
318 // strip leading zeros
319 // (x != 0; thus s must contain at least one non-zero digit
320 // and the loop will terminate)
335 // Convert words of q to base b digits in s. If q is large, it is recursively "split in half"
336 // by nat/nat division using tabulated divisors. Otherwise, it is converted iteratively using
337 // repeated nat/Word division.
339 // The iterative method processes n Words by n divW() calls, each of which visits every Word in the
340 // incrementally shortened q for a total of n + (n-1) + (n-2) ... + 2 + 1, or n(n+1)/2 divW()'s.
341 // Recursive conversion divides q by its approximate square root, yielding two parts, each half
342 // the size of q. Using the iterative method on both halves means 2 * (n/2)(n/2 + 1)/2 divW()'s
343 // plus the expensive long div(). Asymptotically, the ratio is favorable at 1/2 the divW()'s, and
344 // is made better by splitting the subblocks recursively. Best is to split blocks until one more
345 // split would take longer (because of the nat/nat div()) than the twice as many divW()'s of the
346 // iterative approach. This threshold is represented by leafSize. Benchmarking of leafSize in the
347 // range 2..64 shows that values of 8 and 16 work well, with a 4x speedup at medium lengths and
348 // ~30x for 20000 digits. Use nat_test.go's BenchmarkLeafSize tests to optimize leafSize for
349 // specific hardware.
351 func (q nat
) convertWords(s
[]byte, b Word
, ndigits
int, bb Word
, table
[]divisor
) {
352 // split larger blocks recursively
354 // len(q) > leafSize > 0
356 index
:= len(table
) - 1
357 for len(q
) > leafSize
{
358 // find divisor close to sqrt(q) if possible, but in any case < q
359 maxLength
:= q
.bitLen() // ~= log2 q, or at of least largest possible q of this bit length
360 minLength
:= maxLength
>> 1 // ~= log2 sqrt(q)
361 for index
> 0 && table
[index
-1].nbits
> minLength
{
364 if table
[index
].nbits
>= maxLength
&& table
[index
].bbb
.cmp(q
) >= 0 {
367 panic("internal inconsistency")
371 // split q into the two digit number (q'*bbb + r) to form independent subblocks
372 q
, r
= q
.div(r
, q
, table
[index
].bbb
)
374 // convert subblocks and collect results in s[:h] and s[h:]
375 h
:= len(s
) - table
[index
].ndigits
376 r
.convertWords(s
[h
:], b
, ndigits
, bb
, table
[0:index
])
377 s
= s
[:h
] // == q.convertWords(s, b, ndigits, bb, table[0:index+1])
381 // having split any large blocks now process the remaining (small) block iteratively
385 // hard-coding for 10 here speeds this up by 1.25x (allows for / and % by constants)
387 // extract least significant, base bb "digit"
389 for j
:= 0; j
< ndigits
&& i
> 0; j
++ {
391 // avoid % computation since r%10 == r - int(r/10)*10;
392 // this appears to be faster for BenchmarkString10000Base10
393 // and smaller strings (but a bit slower for larger ones)
395 s
[i
] = '0' + byte(r
-t
*10)
401 // extract least significant, base bb "digit"
403 for j
:= 0; j
< ndigits
&& i
> 0; j
++ {
411 // prepend high-order zeros
412 for i
> 0 { // while need more leading zeros
418 // Split blocks greater than leafSize Words (or set to 0 to disable recursive conversion)
419 // Benchmark and configure leafSize using: go test -bench="Leaf"
420 // 8 and 16 effective on 3.0 GHz Xeon "Clovertown" CPU (128 byte cache lines)
421 // 8 and 16 effective on 2.66 GHz Core 2 Duo "Penryn" CPU
422 var leafSize
int = 8 // number of Word-size binary values treat as a monolithic block
424 type divisor
struct {
426 nbits
int // bit length of divisor (discounting leading zeros) ~= log2(bbb)
427 ndigits
int // digit length of divisor in terms of output base digits
430 var cacheBase10
struct {
432 table
[64]divisor
// cached divisors for base 10
435 // expWW computes x**y
436 func (z nat
) expWW(x
, y Word
) nat
{
437 return z
.expNN(nat(nil).setWord(x
), nat(nil).setWord(y
), nil)
440 // construct table of powers of bb*leafSize to use in subdivisions
441 func divisors(m
int, b Word
, ndigits
int, bb Word
) []divisor
{
442 // only compute table when recursive conversion is enabled and x is large
443 if leafSize
== 0 || m
<= leafSize
{
447 // determine k where (bb**leafSize)**(2**k) >= sqrt(x)
449 for words
:= leafSize
; words
< m
>>1 && k
< len(cacheBase10
.table
); words
<<= 1 {
453 // reuse and extend existing table of divisors or create new table as appropriate
454 var table
[]divisor
// for b == 10, table overlaps with cacheBase10.table
457 table
= cacheBase10
.table
[0:k
] // reuse old table for this conversion
459 table
= make([]divisor
, k
) // create new table for this conversion
463 if table
[k
-1].ndigits
== 0 {
464 // add new entries as needed
466 for i
:= 0; i
< k
; i
++ {
467 if table
[i
].ndigits
== 0 {
469 table
[0].bbb
= nat(nil).expWW(bb
, Word(leafSize
))
470 table
[0].ndigits
= ndigits
* leafSize
472 table
[i
].bbb
= nat(nil).mul(table
[i
-1].bbb
, table
[i
-1].bbb
)
473 table
[i
].ndigits
= 2 * table
[i
-1].ndigits
476 // optimization: exploit aggregated extra bits in macro blocks
477 larger
= nat(nil).set(table
[i
].bbb
)
478 for mulAddVWW(larger
, larger
, b
, 0) == 0 {
479 table
[i
].bbb
= table
[i
].bbb
.set(larger
)
483 table
[i
].nbits
= table
[i
].bbb
.bitLen()