diff options
Diffstat (limited to 'src/pkg/big/int.go')
| -rwxr-xr-x | src/pkg/big/int.go | 81 |
1 files changed, 68 insertions, 13 deletions
diff --git a/src/pkg/big/int.go b/src/pkg/big/int.go index 4126ce62d..cdf5a7d55 100755 --- a/src/pkg/big/int.go +++ b/src/pkg/big/int.go @@ -6,6 +6,9 @@ package big +import "fmt" + + // An Int represents a signed multi-precision integer. // The zero value for an Int represents the value 0. type Int struct { @@ -19,12 +22,13 @@ var intOne = &Int{false, natOne} // SetInt64 sets z to x and returns z. func (z *Int) SetInt64(x int64) *Int { - z.neg = false + neg := false if x < 0 { - z.neg = true + neg = true x = -x } - z.abs = z.abs.new(uint64(x)) + z.abs = z.abs.setUint64(uint64(x)) + z.neg = neg return z } @@ -37,8 +41,8 @@ func NewInt(x int64) *Int { // Set sets z to x. func (z *Int) Set(x *Int) *Int { - z.neg = x.neg z.abs = z.abs.set(x.abs) + z.neg = x.neg return z } @@ -99,6 +103,30 @@ func (z *Int) Mul(x, y *Int) *Int { } +// 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. +func (z *Int) MulRange(a, b int64) *Int { + switch { + case a > b: + return z.SetInt64(1) // empty range + case a <= 0 && b >= 0: + return z.SetInt64(0) // range includes 0 + } + // a <= b && (b < 0 || a > 0) + + neg := false + if a < 0 { + neg = (b-a)&1 == 0 + a, b = -b, -a + } + + z.abs = z.abs.mulRange(uint64(a), uint64(b)) + z.neg = neg + return z +} + + // 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. @@ -243,26 +271,53 @@ func (x *Int) Cmp(y *Int) (r int) { } -func (z *Int) String() string { +func (x *Int) String() string { s := "" - if z.neg { + if x.neg { s = "-" } - return s + z.abs.string(10) + return s + x.abs.string(10) +} + + +func fmtbase(ch int) int { + switch ch { + case 'b': + return 2 + case 'o': + return 8 + case 'd': + return 10 + case 'x': + return 16 + } + return 10 +} + + +// Format is a support routine for fmt.Formatter. It accepts +// the formats 'b' (binary), 'o' (octal), 'd' (decimal) and +// 'x' (hexadecimal). +// +func (x *Int) Format(s fmt.State, ch int) { + if x.neg { + fmt.Fprint(s, "-") + } + fmt.Fprint(s, x.abs.string(fmtbase(ch))) } // Int64 returns the int64 representation of z. // If z cannot be represented in an int64, the result is undefined. -func (z *Int) Int64() int64 { - if len(z.abs) == 0 { +func (x *Int) Int64() int64 { + if len(x.abs) == 0 { return 0 } - v := int64(z.abs[0]) - if _W == 32 && len(z.abs) > 1 { - v |= int64(z.abs[1]) << 32 + v := int64(x.abs[0]) + if _W == 32 && len(x.abs) > 1 { + v |= int64(x.abs[1]) << 32 } - if z.neg { + if x.neg { v = -v } return v |
