| // 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. | |
| // Integer numbers | |
| // | |
| // Integers are normalized if the mantissa is normalized and the sign is | |
| // false for mant == 0. Use MakeInt to create normalized Integers. | |
| package bignum | |
| import ( | |
| "fmt" | |
| ) | |
| // TODO(gri) Complete the set of in-place operations. | |
| // Integer represents a signed integer value of arbitrary precision. | |
| // | |
| type Integer struct { | |
| sign bool | |
| mant Natural | |
| } | |
| // MakeInt makes an integer given a sign and a mantissa. | |
| // The number is positive (>= 0) if sign is false or the | |
| // mantissa is zero; it is negative otherwise. | |
| // | |
| func MakeInt(sign bool, mant Natural) *Integer { | |
| if mant.IsZero() { | |
| sign = false // normalize | |
| } | |
| return &Integer{sign, mant} | |
| } | |
| // Int creates a small integer with value x. | |
| // | |
| func Int(x int64) *Integer { | |
| var ux uint64 | |
| if x < 0 { | |
| // For the most negative x, -x == x, and | |
| // the bit pattern has the correct value. | |
| ux = uint64(-x) | |
| } else { | |
| ux = uint64(x) | |
| } | |
| return MakeInt(x < 0, Nat(ux)) | |
| } | |
| // Value returns the value of x, if x fits into an int64; | |
| // otherwise the result is undefined. | |
| // | |
| func (x *Integer) Value() int64 { | |
| z := int64(x.mant.Value()) | |
| if x.sign { | |
| z = -z | |
| } | |
| return z | |
| } | |
| // Abs returns the absolute value of x. | |
| // | |
| func (x *Integer) Abs() Natural { return x.mant } | |
| // Predicates | |
| // IsEven returns true iff x is divisible by 2. | |
| // | |
| func (x *Integer) IsEven() bool { return x.mant.IsEven() } | |
| // IsOdd returns true iff x is not divisible by 2. | |
| // | |
| func (x *Integer) IsOdd() bool { return x.mant.IsOdd() } | |
| // IsZero returns true iff x == 0. | |
| // | |
| func (x *Integer) IsZero() bool { return x.mant.IsZero() } | |
| // IsNeg returns true iff x < 0. | |
| // | |
| func (x *Integer) IsNeg() bool { return x.sign && !x.mant.IsZero() } | |
| // IsPos returns true iff x >= 0. | |
| // | |
| func (x *Integer) IsPos() bool { return !x.sign && !x.mant.IsZero() } | |
| // Operations | |
| // Neg returns the negated value of x. | |
| // | |
| func (x *Integer) Neg() *Integer { return MakeInt(!x.sign, x.mant) } | |
| // Iadd sets z to the sum x + y. | |
| // z must exist and may be x or y. | |
| // | |
| func Iadd(z, x, y *Integer) { | |
| if x.sign == y.sign { | |
| // x + y == x + y | |
| // (-x) + (-y) == -(x + y) | |
| z.sign = x.sign | |
| Nadd(&z.mant, x.mant, y.mant) | |
| } else { | |
| // x + (-y) == x - y == -(y - x) | |
| // (-x) + y == y - x == -(x - y) | |
| if x.mant.Cmp(y.mant) >= 0 { | |
| z.sign = x.sign | |
| Nsub(&z.mant, x.mant, y.mant) | |
| } else { | |
| z.sign = !x.sign | |
| Nsub(&z.mant, y.mant, x.mant) | |
| } | |
| } | |
| } | |
| // Add returns the sum x + y. | |
| // | |
| func (x *Integer) Add(y *Integer) *Integer { | |
| var z Integer | |
| Iadd(&z, x, y) | |
| return &z | |
| } | |
| func Isub(z, x, y *Integer) { | |
| if x.sign != y.sign { | |
| // x - (-y) == x + y | |
| // (-x) - y == -(x + y) | |
| z.sign = x.sign | |
| Nadd(&z.mant, x.mant, y.mant) | |
| } else { | |
| // x - y == x - y == -(y - x) | |
| // (-x) - (-y) == y - x == -(x - y) | |
| if x.mant.Cmp(y.mant) >= 0 { | |
| z.sign = x.sign | |
| Nsub(&z.mant, x.mant, y.mant) | |
| } else { | |
| z.sign = !x.sign | |
| Nsub(&z.mant, y.mant, x.mant) | |
| } | |
| } | |
| } | |
| // Sub returns the difference x - y. | |
| // | |
| func (x *Integer) Sub(y *Integer) *Integer { | |
| var z Integer | |
| Isub(&z, x, y) | |
| return &z | |
| } | |
| // Nscale sets *z to the scaled value (*z) * d. | |
| // | |
| func Iscale(z *Integer, d int64) { | |
| f := uint64(d) | |
| if d < 0 { | |
| f = uint64(-d) | |
| } | |
| z.sign = z.sign != (d < 0) | |
| Nscale(&z.mant, f) | |
| } | |
| // Mul1 returns the product x * d. | |
| // | |
| func (x *Integer) Mul1(d int64) *Integer { | |
| f := uint64(d) | |
| if d < 0 { | |
| f = uint64(-d) | |
| } | |
| return MakeInt(x.sign != (d < 0), x.mant.Mul1(f)) | |
| } | |
| // Mul returns the product x * y. | |
| // | |
| func (x *Integer) Mul(y *Integer) *Integer { | |
| // x * y == x * y | |
| // x * (-y) == -(x * y) | |
| // (-x) * y == -(x * y) | |
| // (-x) * (-y) == x * y | |
| return MakeInt(x.sign != y.sign, x.mant.Mul(y.mant)) | |
| } | |
| // MulNat returns the product x * y, where y is a (unsigned) natural number. | |
| // | |
| func (x *Integer) MulNat(y Natural) *Integer { | |
| // x * y == x * y | |
| // (-x) * y == -(x * y) | |
| return MakeInt(x.sign, x.mant.Mul(y)) | |
| } | |
| // Quo returns the quotient q = x / y for y != 0. | |
| // If y == 0, a division-by-zero run-time error occurs. | |
| // | |
| // Quo and Rem implement T-division and modulus (like C99): | |
| // | |
| // q = x.Quo(y) = trunc(x/y) (truncation towards zero) | |
| // r = x.Rem(y) = x - y*q | |
| // | |
| // (Daan Leijen, ``Division and Modulus for Computer Scientists''.) | |
| // | |
| func (x *Integer) Quo(y *Integer) *Integer { | |
| // x / y == x / y | |
| // x / (-y) == -(x / y) | |
| // (-x) / y == -(x / y) | |
| // (-x) / (-y) == x / y | |
| return MakeInt(x.sign != y.sign, x.mant.Div(y.mant)) | |
| } | |
| // Rem returns the remainder r of the division x / y for y != 0, | |
| // with r = x - y*x.Quo(y). Unless r is zero, its sign corresponds | |
| // to the sign of x. | |
| // If y == 0, a division-by-zero run-time error occurs. | |
| // | |
| func (x *Integer) Rem(y *Integer) *Integer { | |
| // x % y == x % y | |
| // x % (-y) == x % y | |
| // (-x) % y == -(x % y) | |
| // (-x) % (-y) == -(x % y) | |
| return MakeInt(x.sign, x.mant.Mod(y.mant)) | |
| } | |
| // QuoRem returns the pair (x.Quo(y), x.Rem(y)) for y != 0. | |
| // If y == 0, a division-by-zero run-time error occurs. | |
| // | |
| func (x *Integer) QuoRem(y *Integer) (*Integer, *Integer) { | |
| q, r := x.mant.DivMod(y.mant) | |
| return MakeInt(x.sign != y.sign, q), MakeInt(x.sign, r) | |
| } | |
| // Div returns the quotient q = x / y for y != 0. | |
| // If y == 0, a division-by-zero run-time error occurs. | |
| // | |
| // Div and Mod implement Euclidian division and modulus: | |
| // | |
| // q = x.Div(y) | |
| // r = x.Mod(y) with: 0 <= r < |q| and: x = y*q + r | |
| // | |
| // (Raymond T. Boute, ``The Euclidian definition of the functions | |
| // div and mod''. ACM Transactions on Programming Languages and | |
| // Systems (TOPLAS), 14(2):127-144, New York, NY, USA, 4/1992. | |
| // ACM press.) | |
| // | |
| func (x *Integer) Div(y *Integer) *Integer { | |
| q, r := x.QuoRem(y) | |
| if r.IsNeg() { | |
| if y.IsPos() { | |
| q = q.Sub(Int(1)) | |
| } else { | |
| q = q.Add(Int(1)) | |
| } | |
| } | |
| return q | |
| } | |
| // Mod returns the modulus r of the division x / y for y != 0, | |
| // with r = x - y*x.Div(y). r is always positive. | |
| // If y == 0, a division-by-zero run-time error occurs. | |
| // | |
| func (x *Integer) Mod(y *Integer) *Integer { | |
| r := x.Rem(y) | |
| if r.IsNeg() { | |
| if y.IsPos() { | |
| r = r.Add(y) | |
| } else { | |
| r = r.Sub(y) | |
| } | |
| } | |
| return r | |
| } | |
| // DivMod returns the pair (x.Div(y), x.Mod(y)). | |
| // | |
| func (x *Integer) DivMod(y *Integer) (*Integer, *Integer) { | |
| q, r := x.QuoRem(y) | |
| if r.IsNeg() { | |
| if y.IsPos() { | |
| q = q.Sub(Int(1)) | |
| r = r.Add(y) | |
| } else { | |
| q = q.Add(Int(1)) | |
| r = r.Sub(y) | |
| } | |
| } | |
| return q, r | |
| } | |
| // Shl implements ``shift left'' x << s. It returns x * 2^s. | |
| // | |
| func (x *Integer) Shl(s uint) *Integer { return MakeInt(x.sign, x.mant.Shl(s)) } | |
| // The bitwise operations on integers are defined on the 2's-complement | |
| // representation of integers. From | |
| // | |
| // -x == ^x + 1 (1) 2's complement representation | |
| // | |
| // follows: | |
| // | |
| // -(x) == ^(x) + 1 | |
| // -(-x) == ^(-x) + 1 | |
| // x-1 == ^(-x) | |
| // ^(x-1) == -x (2) | |
| // | |
| // Using (1) and (2), operations on negative integers of the form -x are | |
| // converted to operations on negated positive integers of the form ~(x-1). | |
| // Shr implements ``shift right'' x >> s. It returns x / 2^s. | |
| // | |
| func (x *Integer) Shr(s uint) *Integer { | |
| if x.sign { | |
| // (-x) >> s == ^(x-1) >> s == ^((x-1) >> s) == -(((x-1) >> s) + 1) | |
| return MakeInt(true, x.mant.Sub(Nat(1)).Shr(s).Add(Nat(1))) | |
| } | |
| return MakeInt(false, x.mant.Shr(s)) | |
| } | |
| // Not returns the ``bitwise not'' ^x for the 2's-complement representation of x. | |
| func (x *Integer) Not() *Integer { | |
| if x.sign { | |
| // ^(-x) == ^(^(x-1)) == x-1 | |
| return MakeInt(false, x.mant.Sub(Nat(1))) | |
| } | |
| // ^x == -x-1 == -(x+1) | |
| return MakeInt(true, x.mant.Add(Nat(1))) | |
| } | |
| // And returns the ``bitwise and'' x & y for the 2's-complement representation of x and y. | |
| // | |
| func (x *Integer) And(y *Integer) *Integer { | |
| if x.sign == y.sign { | |
| if x.sign { | |
| // (-x) & (-y) == ^(x-1) & ^(y-1) == ^((x-1) | (y-1)) == -(((x-1) | (y-1)) + 1) | |
| return MakeInt(true, x.mant.Sub(Nat(1)).Or(y.mant.Sub(Nat(1))).Add(Nat(1))) | |
| } | |
| // x & y == x & y | |
| return MakeInt(false, x.mant.And(y.mant)) | |
| } | |
| // x.sign != y.sign | |
| if x.sign { | |
| x, y = y, x // & is symmetric | |
| } | |
| // x & (-y) == x & ^(y-1) == x &^ (y-1) | |
| return MakeInt(false, x.mant.AndNot(y.mant.Sub(Nat(1)))) | |
| } | |
| // AndNot returns the ``bitwise clear'' x &^ y for the 2's-complement representation of x and y. | |
| // | |
| func (x *Integer) AndNot(y *Integer) *Integer { | |
| if x.sign == y.sign { | |
| if x.sign { | |
| // (-x) &^ (-y) == ^(x-1) &^ ^(y-1) == ^(x-1) & (y-1) == (y-1) &^ (x-1) | |
| return MakeInt(false, y.mant.Sub(Nat(1)).AndNot(x.mant.Sub(Nat(1)))) | |
| } | |
| // x &^ y == x &^ y | |
| return MakeInt(false, x.mant.AndNot(y.mant)) | |
| } | |
| if x.sign { | |
| // (-x) &^ y == ^(x-1) &^ y == ^(x-1) & ^y == ^((x-1) | y) == -(((x-1) | y) + 1) | |
| return MakeInt(true, x.mant.Sub(Nat(1)).Or(y.mant).Add(Nat(1))) | |
| } | |
| // x &^ (-y) == x &^ ^(y-1) == x & (y-1) | |
| return MakeInt(false, x.mant.And(y.mant.Sub(Nat(1)))) | |
| } | |
| // Or returns the ``bitwise or'' x | y for the 2's-complement representation of x and y. | |
| // | |
| func (x *Integer) Or(y *Integer) *Integer { | |
| if x.sign == y.sign { | |
| if x.sign { | |
| // (-x) | (-y) == ^(x-1) | ^(y-1) == ^((x-1) & (y-1)) == -(((x-1) & (y-1)) + 1) | |
| return MakeInt(true, x.mant.Sub(Nat(1)).And(y.mant.Sub(Nat(1))).Add(Nat(1))) | |
| } | |
| // x | y == x | y | |
| return MakeInt(false, x.mant.Or(y.mant)) | |
| } | |
| // x.sign != y.sign | |
| if x.sign { | |
| x, y = y, x // | or symmetric | |
| } | |
| // x | (-y) == x | ^(y-1) == ^((y-1) &^ x) == -(^((y-1) &^ x) + 1) | |
| return MakeInt(true, y.mant.Sub(Nat(1)).AndNot(x.mant).Add(Nat(1))) | |
| } | |
| // Xor returns the ``bitwise xor'' x | y for the 2's-complement representation of x and y. | |
| // | |
| func (x *Integer) Xor(y *Integer) *Integer { | |
| if x.sign == y.sign { | |
| if x.sign { | |
| // (-x) ^ (-y) == ^(x-1) ^ ^(y-1) == (x-1) ^ (y-1) | |
| return MakeInt(false, x.mant.Sub(Nat(1)).Xor(y.mant.Sub(Nat(1)))) | |
| } | |
| // x ^ y == x ^ y | |
| return MakeInt(false, x.mant.Xor(y.mant)) | |
| } | |
| // x.sign != y.sign | |
| if x.sign { | |
| x, y = y, x // ^ is symmetric | |
| } | |
| // x ^ (-y) == x ^ ^(y-1) == ^(x ^ (y-1)) == -((x ^ (y-1)) + 1) | |
| return MakeInt(true, x.mant.Xor(y.mant.Sub(Nat(1))).Add(Nat(1))) | |
| } | |
| // Cmp compares x and y. The result is an int value that is | |
| // | |
| // < 0 if x < y | |
| // == 0 if x == y | |
| // > 0 if x > y | |
| // | |
| func (x *Integer) Cmp(y *Integer) int { | |
| // x cmp y == x cmp y | |
| // x cmp (-y) == x | |
| // (-x) cmp y == y | |
| // (-x) cmp (-y) == -(x cmp y) | |
| var r int | |
| switch { | |
| case x.sign == y.sign: | |
| r = x.mant.Cmp(y.mant) | |
| if x.sign { | |
| r = -r | |
| } | |
| case x.sign: | |
| r = -1 | |
| case y.sign: | |
| r = 1 | |
| } | |
| return r | |
| } | |
| // ToString converts x to a string for a given base, with 2 <= base <= 16. | |
| // | |
| func (x *Integer) ToString(base uint) string { | |
| if x.mant.IsZero() { | |
| return "0" | |
| } | |
| var s string | |
| if x.sign { | |
| s = "-" | |
| } | |
| return s + x.mant.ToString(base) | |
| } | |
| // String converts x to its decimal string representation. | |
| // x.String() is the same as x.ToString(10). | |
| // | |
| func (x *Integer) String() string { return x.ToString(10) } | |
| // Format is a support routine for fmt.Formatter. It accepts | |
| // the formats 'b' (binary), 'o' (octal), and 'x' (hexadecimal). | |
| // | |
| func (x *Integer) Format(h fmt.State, c int) { fmt.Fprintf(h, "%s", x.ToString(fmtbase(c))) } | |
| // IntFromString returns the integer corresponding to the | |
| // longest possible prefix of s representing an integer in a | |
| // given conversion base, the actual conversion base used, and | |
| // the prefix length. The syntax of integers follows the syntax | |
| // of signed integer literals in Go. | |
| // | |
| // If the base argument is 0, the string prefix determines the actual | |
| // conversion base. A prefix of ``0x'' or ``0X'' selects base 16; the | |
| // ``0'' prefix selects base 8. Otherwise the selected base is 10. | |
| // | |
| func IntFromString(s string, base uint) (*Integer, uint, int) { | |
| // skip sign, if any | |
| i0 := 0 | |
| if len(s) > 0 && (s[0] == '-' || s[0] == '+') { | |
| i0 = 1 | |
| } | |
| mant, base, slen := NatFromString(s[i0:], base) | |
| return MakeInt(i0 > 0 && s[0] == '-', mant), base, i0 + slen | |
| } |