diff options
Diffstat (limited to 'src/pkg/big/int.go')
-rwxr-xr-x | src/pkg/big/int.go | 170 |
1 files changed, 71 insertions, 99 deletions
diff --git a/src/pkg/big/int.go b/src/pkg/big/int.go index 0948919cd..701b69715 100755 --- a/src/pkg/big/int.go +++ b/src/pkg/big/int.go @@ -21,10 +21,8 @@ type Int struct { abs nat // absolute value of the integer } - var intOne = &Int{false, natOne} - // Sign returns: // // -1 if x < 0 @@ -41,7 +39,6 @@ func (x *Int) Sign() int { return 1 } - // SetInt64 sets z to x and returns z. func (z *Int) SetInt64(x int64) *Int { neg := false @@ -54,13 +51,11 @@ func (z *Int) SetInt64(x int64) *Int { return z } - // NewInt allocates and returns a new Int set to x. func NewInt(x int64) *Int { return new(Int).SetInt64(x) } - // Set sets z to x and returns z. func (z *Int) Set(x *Int) *Int { z.abs = z.abs.set(x.abs) @@ -68,7 +63,6 @@ func (z *Int) Set(x *Int) *Int { return z } - // Abs sets z to |x| (the absolute value of x) and returns z. func (z *Int) Abs(x *Int) *Int { z.abs = z.abs.set(x.abs) @@ -76,7 +70,6 @@ func (z *Int) Abs(x *Int) *Int { return z } - // Neg sets z to -x and returns z. func (z *Int) Neg(x *Int) *Int { z.abs = z.abs.set(x.abs) @@ -84,7 +77,6 @@ func (z *Int) Neg(x *Int) *Int { return z } - // Add sets z to the sum x+y and returns z. func (z *Int) Add(x, y *Int) *Int { neg := x.neg @@ -106,7 +98,6 @@ func (z *Int) Add(x, y *Int) *Int { return z } - // Sub sets z to the difference x-y and returns z. func (z *Int) Sub(x, y *Int) *Int { neg := x.neg @@ -128,7 +119,6 @@ func (z *Int) Sub(x, y *Int) *Int { return z } - // Mul sets z to the product x*y and returns z. func (z *Int) Mul(x, y *Int) *Int { // x * y == x * y @@ -140,7 +130,6 @@ func (z *Int) Mul(x, y *Int) *Int { return z } - // MulRange sets z to the product of all integers // in the range [a, b] inclusively and returns z. // If a > b (empty range), the result is 1. @@ -164,7 +153,6 @@ func (z *Int) MulRange(a, b int64) *Int { return z } - // Binomial sets z to the binomial coefficient of (n, k) and returns z. func (z *Int) Binomial(n, k int64) *Int { var a, b Int @@ -173,7 +161,6 @@ func (z *Int) Binomial(n, k int64) *Int { return z.Quo(&a, &b) } - // Quo sets z to the quotient x/y for y != 0 and returns z. // If y == 0, a division-by-zero run-time panic occurs. // See QuoRem for more details. @@ -183,7 +170,6 @@ func (z *Int) Quo(x, y *Int) *Int { return z } - // Rem sets z to the remainder x%y for y != 0 and returns z. // If y == 0, a division-by-zero run-time panic occurs. // See QuoRem for more details. @@ -193,7 +179,6 @@ func (z *Int) Rem(x, y *Int) *Int { return z } - // QuoRem sets z to the quotient x/y and r to the remainder x%y // and returns the pair (z, r) for y != 0. // If y == 0, a division-by-zero run-time panic occurs. @@ -211,7 +196,6 @@ func (z *Int) QuoRem(x, y, r *Int) (*Int, *Int) { return z, r } - // Div sets z to the quotient x/y for y != 0 and returns z. // If y == 0, a division-by-zero run-time panic occurs. // See DivMod for more details. @@ -229,7 +213,6 @@ func (z *Int) Div(x, y *Int) *Int { return z } - // Mod sets z to the modulus x%y for y != 0 and returns z. // If y == 0, a division-by-zero run-time panic occurs. // See DivMod for more details. @@ -250,7 +233,6 @@ func (z *Int) Mod(x, y *Int) *Int { return z } - // DivMod sets z to the quotient x div y and m to the modulus x mod y // and returns the pair (z, m) for y != 0. // If y == 0, a division-by-zero run-time panic occurs. @@ -283,7 +265,6 @@ func (z *Int) DivMod(x, y, m *Int) (*Int, *Int) { return z, m } - // Cmp compares x and y and returns: // // -1 if x < y @@ -309,7 +290,6 @@ func (x *Int) Cmp(y *Int) (r int) { return } - func (x *Int) String() string { switch { case x == nil: @@ -320,7 +300,6 @@ func (x *Int) String() string { return x.abs.decimalString() } - func charset(ch int) string { switch ch { case 'b': @@ -337,10 +316,26 @@ func charset(ch int) string { return "" // unknown format } +// write count copies of text to s +func writeMultiple(s fmt.State, text string, count int) { + if len(text) > 0 { + b := []byte(text) + for ; count > 0; count-- { + s.Write(b) + } + } +} // Format is a support routine for fmt.Formatter. It accepts // the formats 'b' (binary), 'o' (octal), 'd' (decimal), 'x' // (lowercase hexadecimal), and 'X' (uppercase hexadecimal). +// Also supported are the full suite of package fmt's format +// verbs for integral types, including '+', '-', and ' ' +// for sign control, '#' for leading zero in octal and for +// hexadecimal, a leading "0x" or "0X" for "%#x" and "%#X" +// respectively, specification of minimum digits precision, +// output field width, space or zero padding, and left or +// right justification. // func (x *Int) Format(s fmt.State, ch int) { cs := charset(ch) @@ -356,75 +351,74 @@ func (x *Int) Format(s fmt.State, ch int) { return } - // determine format - format := "%s" + // determine sign character + sign := "" + switch { + case x.neg: + sign = "-" + case s.Flag('+'): // supersedes ' ' when both specified + sign = "+" + case s.Flag(' '): + sign = " " + } + + // determine prefix characters for indicating output base + prefix := "" if s.Flag('#') { switch ch { - case 'o': - format = "0%s" - case 'x': - format = "0x%s" + case 'o': // octal + prefix = "0" + case 'x': // hexadecimal + prefix = "0x" case 'X': - format = "0X%s" - } - } - t := fmt.Sprintf(format, x.abs.string(cs)) - - // insert spaces in hexadecimal formats if needed - if len(t) > 0 && s.Flag(' ') && (ch == 'x' || ch == 'X') { - spaces := (len(t)+1)/2 - 1 - spaced := make([]byte, len(t)+spaces) - var i, j int - spaced[i] = t[j] - i++ - j++ - if len(t)&1 == 0 { - spaced[i] = t[j] - i++ - j++ + prefix = "0X" } - for j < len(t) { - spaced[i] = ' ' - i++ - spaced[i] = t[j] - i++ - j++ - spaced[i] = t[j] - i++ - j++ - } - t = string(spaced) } - // determine sign prefix - prefix := "" - switch { - case x.neg: - prefix = "-" - case s.Flag('+'): - prefix = "+" - case s.Flag(' ') && ch != 'x' && ch != 'X': - prefix = " " + // determine digits with base set by len(cs) and digit characters from cs + digits := x.abs.string(cs) + + // number of characters for the three classes of number padding + var left int // space characters to left of digits for right justification ("%8d") + var zeroes int // zero characters (actually cs[0]) as left-most digits ("%.8d") + var right int // space characters to right of digits for left justification ("%-8d") + + // determine number padding from precision: the least number of digits to output + precision, precisionSet := s.Precision() + if precisionSet { + switch { + case len(digits) < precision: + zeroes = precision - len(digits) // count of zero padding + case digits == "0" && precision == 0: + return // print nothing if zero value (x == 0) and zero precision ("." or ".0") + } } - // fill to minimum width and prepend sign prefix - if width, ok := s.Width(); ok && len(t)+len(prefix) < width { - if s.Flag('0') { - t = fmt.Sprintf("%s%0*d%s", prefix, width-len(t)-len(prefix), 0, t) - } else { - if s.Flag('-') { - width = -width - } - t = fmt.Sprintf("%*s", width, prefix+t) + // determine field pad from width: the least number of characters to output + length := len(sign) + len(prefix) + zeroes + len(digits) + if width, widthSet := s.Width(); widthSet && length < width { // pad as specified + switch d := width - length; { + case s.Flag('-'): + // pad on the right with spaces; supersedes '0' when both specified + right = d + case s.Flag('0') && !precisionSet: + // pad with zeroes unless precision also specified + zeroes = d + default: + // pad on the left with spaces + left = d } - } else if prefix != "" { - t = prefix + t } - fmt.Fprint(s, t) + // print number as [left pad][sign][prefix][zero pad][digits][right pad] + writeMultiple(s, " ", left) + writeMultiple(s, sign, 1) + writeMultiple(s, prefix, 1) + writeMultiple(s, "0", zeroes) + writeMultiple(s, digits, 1) + writeMultiple(s, " ", right) } - // scan sets z to the integer value corresponding to the longest possible prefix // read from r representing a signed integer number in a given conversion base. // It returns z, the actual conversion base used, and an error, if any. In the @@ -461,7 +455,6 @@ func (z *Int) scan(r io.RuneScanner, base int) (*Int, int, os.Error) { return z, base, nil } - // Scan is a support routine for fmt.Scanner; it sets z to the value of // the scanned number. It accepts the formats 'b' (binary), 'o' (octal), // 'd' (decimal), 'x' (lowercase hexadecimal), and 'X' (uppercase hexadecimal). @@ -486,7 +479,6 @@ func (z *Int) Scan(s fmt.ScanState, ch int) os.Error { return err } - // Int64 returns the int64 representation of x. // If x cannot be represented in an int64, the result is undefined. func (x *Int) Int64() int64 { @@ -503,7 +495,6 @@ func (x *Int) Int64() int64 { return v } - // SetString sets z to the value of s, interpreted in the given base, // and returns z and a boolean indicating success. If SetString fails, // the value of z is undefined. @@ -523,7 +514,6 @@ func (z *Int) SetString(s string, base int) (*Int, bool) { return z, err == os.EOF // err == os.EOF => scan consumed all of s } - // SetBytes interprets buf as the bytes of a big-endian unsigned // integer, sets z to that value, and returns z. func (z *Int) SetBytes(buf []byte) *Int { @@ -532,21 +522,18 @@ func (z *Int) SetBytes(buf []byte) *Int { return z } - // Bytes returns the absolute value of z as a big-endian byte slice. func (z *Int) Bytes() []byte { buf := make([]byte, len(z.abs)*_S) return buf[z.abs.bytes(buf):] } - // BitLen returns the length of the absolute value of z in bits. // The bit length of 0 is 0. func (z *Int) BitLen() int { return z.abs.bitLen() } - // Exp sets z = x**y mod m. If m is nil, z = x**y. // See Knuth, volume 2, section 4.6.3. func (z *Int) Exp(x, y, m *Int) *Int { @@ -567,7 +554,6 @@ func (z *Int) Exp(x, y, m *Int) *Int { return z } - // GcdInt sets d to the greatest common divisor of a and b, which must be // positive numbers. // If x and y are not nil, GcdInt sets x and y such that d = a*x + b*y. @@ -626,7 +612,6 @@ func GcdInt(d, x, y, a, b *Int) { *d = *A } - // ProbablyPrime performs n Miller-Rabin tests to check whether z is prime. // If it returns true, z is prime with probability 1 - 1/4^n. // If it returns false, z is not prime. @@ -634,7 +619,6 @@ func ProbablyPrime(z *Int, n int) bool { return !z.neg && z.abs.probablyPrime(n) } - // Rand sets z to a pseudo-random number in [0, n) and returns z. func (z *Int) Rand(rnd *rand.Rand, n *Int) *Int { z.neg = false @@ -646,7 +630,6 @@ func (z *Int) Rand(rnd *rand.Rand, n *Int) *Int { return z } - // ModInverse sets z to the multiplicative inverse of g in the group ℤ/pℤ (where // p is a prime) and returns z. func (z *Int) ModInverse(g, p *Int) *Int { @@ -660,7 +643,6 @@ func (z *Int) ModInverse(g, p *Int) *Int { return z } - // Lsh sets z = x << n and returns z. func (z *Int) Lsh(x *Int, n uint) *Int { z.abs = z.abs.shl(x.abs, n) @@ -668,7 +650,6 @@ func (z *Int) Lsh(x *Int, n uint) *Int { return z } - // Rsh sets z = x >> n and returns z. func (z *Int) Rsh(x *Int, n uint) *Int { if x.neg { @@ -685,7 +666,6 @@ func (z *Int) Rsh(x *Int, n uint) *Int { return z } - // Bit returns the value of the i'th bit of z. That is, it // returns (z>>i)&1. The bit index i must be >= 0. func (z *Int) Bit(i int) uint { @@ -700,7 +680,6 @@ func (z *Int) Bit(i int) uint { return z.abs.bit(uint(i)) } - // SetBit sets the i'th bit of z to bit and returns z. // That is, if bit is 1 SetBit sets z = x | (1 << i); // if bit is 0 it sets z = x &^ (1 << i). If bit is not 0 or 1, @@ -721,7 +700,6 @@ func (z *Int) SetBit(x *Int, i int, b uint) *Int { return z } - // And sets z = x & y and returns z. func (z *Int) And(x, y *Int) *Int { if x.neg == y.neg { @@ -752,7 +730,6 @@ func (z *Int) And(x, y *Int) *Int { return z } - // AndNot sets z = x &^ y and returns z. func (z *Int) AndNot(x, y *Int) *Int { if x.neg == y.neg { @@ -786,7 +763,6 @@ func (z *Int) AndNot(x, y *Int) *Int { return z } - // Or sets z = x | y and returns z. func (z *Int) Or(x, y *Int) *Int { if x.neg == y.neg { @@ -817,7 +793,6 @@ func (z *Int) Or(x, y *Int) *Int { return z } - // Xor sets z = x ^ y and returns z. func (z *Int) Xor(x, y *Int) *Int { if x.neg == y.neg { @@ -848,7 +823,6 @@ func (z *Int) Xor(x, y *Int) *Int { return z } - // Not sets z = ^x and returns z. func (z *Int) Not(x *Int) *Int { if x.neg { @@ -864,7 +838,6 @@ func (z *Int) Not(x *Int) *Int { return z } - // Gob codec version. Permits backward-compatible changes to the encoding. const intGobVersion byte = 1 @@ -880,7 +853,6 @@ func (z *Int) GobEncode() ([]byte, os.Error) { return buf[i:], nil } - // GobDecode implements the gob.GobDecoder interface. func (z *Int) GobDecode(buf []byte) os.Error { if len(buf) == 0 { |