Copyright 2009 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
This file provides Go implementations of elementary multi-precision arithmetic operations on word vectors. These have the suffix _g. These are needed for platforms without assembly implementations of these routines. This file also contains elementary operations that can be implemented sufficiently efficiently in Go.
package big
import
A Word represents a single digit of a multi-precision unsigned integer.
typeWorduintconst (
_S = _W / 8// word size in bytes_W = bits.UintSize// word size in bits_B = 1 << _W// digit base_M = _B - 1// digit mask
)
Many of the loops in this file are of the form for i := 0; i < len(z) && i < len(x) && i < len(y); i++ i < len(z) is the real condition. However, checking i < len(x) && i < len(y) as well is faster than having the compiler do a bounds check in the body of the loop; remarkably it is even faster than hoisting the bounds check out of the loop, by doing something like _, _ = x[len(z)-1], y[len(z)-1] There are other ways to hoist the bounds check out of the loop, but the compiler's BCE isn't powerful enough for them (yet?). See the discussion in CL 164966.
---------------------------------------------------------------------------- Elementary operations on words These operations are used by the vector operations below.
addVWlarge is addVW, but intended for large z. The only difference is that we check on every iteration whether we are done with carries, and if so, switch to a much faster copy instead. This is only a good idea for large z, because the overhead of the check and the function call outweigh the benefits when z is small.
We know that m = ⎣(B^2-1)/d⎦-B ⎣(B^2-1)/d⎦ = m+B (B^2-1)/d = m+B+delta1 0 <= delta1 <= (d-1)/d B^2/d = m+B+delta2 0 <= delta2 <= 1 The quotient we're trying to compute is quotient = ⎣(x1*B+x0)/d⎦ = ⎣(x1*B*(B^2/d)+x0*(B^2/d))/B^2⎦ = ⎣(x1*B*(m+B+delta2)+x0*(m+B+delta2))/B^2⎦ = ⎣(x1*m+x1*B+x0)/B + x0*m/B^2 + delta2*(x1*B+x0)/B^2⎦ The latter two terms of this three-term sum are between 0 and 1. So we can compute just the first term, and we will be low by at most 2.
The remainder we just computed is bounded above by B+d: r = x1*B + x0 - d*q. = x1*B + x0 - d*⎣(x1*m+x1*B+x0)/B⎦ = x1*B + x0 - d*((x1*m+x1*B+x0)/B-alpha) 0 <= alpha < 1 = x1*B + x0 - x1*d/B*m - x1*d - x0*d/B + d*alpha = x1*B + x0 - x1*d/B*⎣(B^2-1)/d-B⎦ - x1*d - x0*d/B + d*alpha = x1*B + x0 - x1*d/B*⎣(B^2-1)/d-B⎦ - x1*d - x0*d/B + d*alpha = x1*B + x0 - x1*d/B*((B^2-1)/d-B-beta) - x1*d - x0*d/B + d*alpha 0 <= beta < 1 = x1*B + x0 - x1*B + x1/B + x1*d + x1*d/B*beta - x1*d - x0*d/B + d*alpha = x0 + x1/B + x1*d/B*beta - x0*d/B + d*alpha = x0*(1-d/B) + x1*(1+d*beta)/B + d*alpha < B*(1-d/B) + d*B/B + d because x0<B (and 1-d/B>0), x1<d, 1+d*beta<=B, alpha<1 = B - d + d + d = B+d So r1 can only be 0 or 1. If r1 is 1, then we know q was too small. Add 1 to q and subtract d from r. That guarantees that r is <B, so we no longer need to keep track of r1.
if != 0 {
++
-=
If the remainder is still too large, increment q one more time.
The pages are generated with Goldsv0.3.2-preview. (GOOS=darwin GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds.