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 }