Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(431)

Side by Side Diff: src/pkg/big/nat.go

Issue 1258042: code review 1258042: big: potential bug fix, cleanups (Closed)
Patch Set: code review 1258042: big: potential bug fix, cleanups Created 14 years, 10 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pkg/big/arith_amd64.s ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // This file contains operations on unsigned multi-precision integers. 5 // This file contains operations on unsigned multi-precision integers.
6 // These are the building blocks for the operations on signed integers 6 // These are the building blocks for the operations on signed integers
7 // and rationals. 7 // and rationals.
8 8
9 // This package implements multi-precision arithmetic (big numbers). 9 // This package implements multi-precision arithmetic (big numbers).
10 // The following numeric types are supported: 10 // The following numeric types are supported:
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 if n <= cap(z) { 62 if n <= cap(z) {
63 return z[0:n] // reuse z 63 return z[0:n] // reuse z
64 } 64 }
65 // Choosing a good value for e has significant performance impact 65 // Choosing a good value for e has significant performance impact
66 // because it increases the chance that a value can be reused. 66 // because it increases the chance that a value can be reused.
67 const e = 4 // extra capacity 67 const e = 4 // extra capacity
68 return make(nat, n, n+e) 68 return make(nat, n, n+e)
69 } 69 }
70 70
71 71
72 func (z nat) setWord(x Word) nat {
73 if x == 0 {
74 return z.make(0)
75 }
76 z = z.make(1)
77 z[0] = x
78 return z
79 }
80
81
72 func (z nat) setUint64(x uint64) nat { 82 func (z nat) setUint64(x uint64) nat {
73 if x == 0 {
74 return z.make(0)
75 }
76
77 // single-digit values 83 // single-digit values
78 » if x == uint64(Word(x)) { 84 » if w := Word(x); uint64(w) == x {
79 » » z = z.make(1) 85 » » return z.setWord(w)
80 » » z[0] = Word(x)
81 » » return z
82 } 86 }
83 87
84 // compute number of words n required to represent x 88 // compute number of words n required to represent x
85 n := 0 89 n := 0
86 for t := x; t > 0; t >>= _W { 90 for t := x; t > 0; t >>= _W {
87 n++ 91 n++
88 } 92 }
89 93
90 // split x into n words 94 // split x into n words
91 z = z.make(n) 95 z = z.make(n)
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 case x[i] > y[i]: 191 case x[i] > y[i]:
188 r = 1 192 r = 1
189 } 193 }
190 return 194 return
191 } 195 }
192 196
193 197
194 func (z nat) mulAddWW(x nat, y, r Word) nat { 198 func (z nat) mulAddWW(x nat, y, r Word) nat {
195 m := len(x) 199 m := len(x)
196 if m == 0 || y == 0 { 200 if m == 0 || y == 0 {
197 » » return z.setUint64(uint64(r)) // result is r 201 » » return z.setWord(r) // result is r
198 } 202 }
199 // m > 0 203 // m > 0
200 204
201 z = z.make(m + 1) 205 z = z.make(m + 1)
202 z[m] = mulAddVWW(z[0:m], x, y, r) 206 z[m] = mulAddVWW(z[0:m], x, y, r)
203 207
204 return z.norm() 208 return z.norm()
205 } 209 }
206 210
207 211
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 // Uses z as storage for q, and u as storage for r if possible. 526 // Uses z as storage for q, and u as storage for r if possible.
523 // See Knuth, Volume 2, section 4.3.1, Algorithm D. 527 // See Knuth, Volume 2, section 4.3.1, Algorithm D.
524 // Preconditions: 528 // Preconditions:
525 // len(v) >= 2 529 // len(v) >= 2
526 // len(uIn) >= len(v) 530 // len(uIn) >= len(v)
527 func (z nat) divLarge(u, uIn, v nat) (q, r nat) { 531 func (z nat) divLarge(u, uIn, v nat) (q, r nat) {
528 n := len(v) 532 n := len(v)
529 m := len(uIn) - n 533 m := len(uIn) - n
530 534
531 // determine if z can be reused 535 // determine if z can be reused
536 // TODO(gri) should find a better solution - this if statement
537 // is very costly (see e.g. time pidigits -s -n 10000)
532 if alias(z, uIn) || alias(z, v) { 538 if alias(z, uIn) || alias(z, v) {
533 z = nil // z is an alias for uIn or v - cannot reuse 539 z = nil // z is an alias for uIn or v - cannot reuse
534 } 540 }
535 q = z.make(m + 1) 541 q = z.make(m + 1)
536 542
537 qhatv := make(nat, n+1) 543 qhatv := make(nat, n+1)
538 if alias(u, uIn) || alias(u, v) { 544 if alias(u, uIn) || alias(u, v) {
539 u = nil // u is an alias for uIn or v - cannot reuse 545 u = nil // u is an alias for uIn or v - cannot reuse
540 } 546 }
541 u = u.make(len(uIn) + 1) 547 u = u.make(len(uIn) + 1)
542 u.clear() 548 u.clear()
543 549
544 // D1. 550 // D1.
545 shift := Word(leadingZeros(v[n-1])) 551 shift := Word(leadingZeros(v[n-1]))
546 shlVW(v, v, shift) 552 shlVW(v, v, shift)
547 u[len(uIn)] = shlVW(u[0:len(uIn)], uIn, shift) 553 u[len(uIn)] = shlVW(u[0:len(uIn)], uIn, shift)
548 554
549 // D2. 555 // D2.
550 for j := m; j >= 0; j-- { 556 for j := m; j >= 0; j-- {
551 // D3. 557 // D3.
552 » » var qhat Word 558 » » qhat := Word(_M)
553 » » if u[j+n] == v[n-1] { 559 » » if u[j+n] != v[n-1] {
554 » » » qhat = _B - 1
555 » » } else {
556 var rhat Word 560 var rhat Word
557 » » » qhat, rhat = divWW_g(u[j+n], u[j+n-1], v[n-1]) 561 » » » qhat, rhat = divWW(u[j+n], u[j+n-1], v[n-1])
558 562
559 // x1 | x2 = q̂v_{n-2} 563 // x1 | x2 = q̂v_{n-2}
560 » » » x1, x2 := mulWW_g(qhat, v[n-2]) 564 » » » x1, x2 := mulWW(qhat, v[n-2])
561 // test if q̂v_{n-2} > br̂ + u_{j+n-2} 565 // test if q̂v_{n-2} > br̂ + u_{j+n-2}
562 for greaterThan(x1, x2, rhat, u[j+n-2]) { 566 for greaterThan(x1, x2, rhat, u[j+n-2]) {
563 qhat-- 567 qhat--
564 prevRhat := rhat 568 prevRhat := rhat
565 rhat += v[n-1] 569 rhat += v[n-1]
566 // v[n-1] >= 0, so this tests for overflow. 570 // v[n-1] >= 0, so this tests for overflow.
567 if rhat < prevRhat { 571 if rhat < prevRhat {
568 break 572 break
569 } 573 }
570 » » » » x1, x2 = mulWW_g(qhat, v[n-2]) 574 » » » » x1, x2 = mulWW(qhat, v[n-2])
571 } 575 }
572 } 576 }
573 577
574 // D4. 578 // D4.
575 qhatv[n] = mulAddVWW(qhatv[0:n], v, qhat, 0) 579 qhatv[n] = mulAddVWW(qhatv[0:n], v, qhat, 0)
576 580
577 c := subVV(u[j:j+len(qhatv)], u[j:], qhatv) 581 c := subVV(u[j:j+len(qhatv)], u[j:], qhatv)
578 if c != 0 { 582 if c != 0 {
579 c := addVV(u[j:j+n], u[j:], v) 583 c := addVV(u[j:j+n], u[j:], v)
580 u[j+n] += c 584 u[j+n] += c
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after
1052 } 1056 }
1053 if y.cmp(natOne) == 0 { 1057 if y.cmp(natOne) == 0 {
1054 return false 1058 return false
1055 } 1059 }
1056 } 1060 }
1057 return false 1061 return false
1058 } 1062 }
1059 1063
1060 return true 1064 return true
1061 } 1065 }
OLDNEW
« no previous file with comments | « src/pkg/big/arith_amd64.s ('k') | no next file » | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b