summaryrefslogtreecommitdiff
path: root/src/pkg/big/int.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/big/int.go')
-rw-r--r--src/pkg/big/int.go139
1 files changed, 139 insertions, 0 deletions
diff --git a/src/pkg/big/int.go b/src/pkg/big/int.go
new file mode 100644
index 000000000..3e6bbd15e
--- /dev/null
+++ b/src/pkg/big/int.go
@@ -0,0 +1,139 @@
+// 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 implements signed multi-precision integers.
+
+package big
+
+// An Int represents a signed multi-precision integer.
+// The zero value for an Int represents the value 0.
+type Int struct {
+ neg bool; // sign
+ abs []Word; // absolute value of the integer
+}
+
+
+// New sets z to x.
+func (z *Int) New(x int64) *Int {
+ z.neg = false;
+ if x < 0 {
+ z.neg = true;
+ x = -x;
+ }
+ z.abs = newN(z.abs, uint64(x));
+ return z;
+}
+
+
+// Set sets z to x.
+func (z *Int) Set(x *Int) *Int {
+ z.neg = x.neg;
+ z.abs = setN(z.abs, x.abs);
+ return z;
+}
+
+
+// Add computes z = x+y.
+func (z *Int) Add(x, y *Int) *Int {
+ if x.neg == y.neg {
+ // x + y == x + y
+ // (-x) + (-y) == -(x + y)
+ z.neg = x.neg;
+ z.abs = addNN(z.abs, x.abs, y.abs);
+ } else {
+ // x + (-y) == x - y == -(y - x)
+ // (-x) + y == y - x == -(x - y)
+ if cmpNN(x.abs, y.abs) >= 0 {
+ z.neg = x.neg;
+ z.abs = subNN(z.abs, x.abs, y.abs);
+ } else {
+ z.neg = !x.neg;
+ z.abs = subNN(z.abs, y.abs, x.abs);
+ }
+ }
+ if len(z.abs) == 0 {
+ z.neg = false; // 0 has no sign
+ }
+ return z
+}
+
+
+// Sub computes z = x-y.
+func (z *Int) Sub(x, y *Int) *Int {
+ if x.neg != y.neg {
+ // x - (-y) == x + y
+ // (-x) - y == -(x + y)
+ z.neg = x.neg;
+ z.abs = addNN(z.abs, x.abs, y.abs);
+ } else {
+ // x - y == x - y == -(y - x)
+ // (-x) - (-y) == y - x == -(x - y)
+ if cmpNN(x.abs, y.abs) >= 0 {
+ z.neg = x.neg;
+ z.abs = subNN(z.abs, x.abs, y.abs);
+ } else {
+ z.neg = !x.neg;
+ z.abs = subNN(z.abs, y.abs, x.abs);
+ }
+ }
+ if len(z.abs) == 0 {
+ z.neg = false; // 0 has no sign
+ }
+ return z
+}
+
+
+// Mul computes z = x*y.
+func (z *Int) Mul(x, y *Int) *Int {
+ // x * y == x * y
+ // x * (-y) == -(x * y)
+ // (-x) * y == -(x * y)
+ // (-x) * (-y) == x * y
+ z.neg = x.neg != y.neg;
+ z.abs = mulNN(z.abs, x.abs, y.abs);
+ return z
+}
+
+
+// Neg computes z = -x.
+func (z *Int) Neg(x *Int) *Int {
+ z.neg = len(x.abs) > 0 && !x.neg; // 0 has no sign
+ z.abs = setN(z.abs, x.abs);
+ return z;
+}
+
+
+// CmpInt 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 CmpInt(x, y *Int) (r int) {
+ // x cmp y == x cmp y
+ // x cmp (-y) == x
+ // (-x) cmp y == y
+ // (-x) cmp (-y) == -(x cmp y)
+ switch {
+ case x.neg == y.neg:
+ r = cmpNN(x.abs, y.abs);
+ if x.neg {
+ r = -r;
+ }
+ case x.neg:
+ r = -1;
+ default:
+ r = 1;
+ }
+ return;
+}
+
+
+func (x *Int) String() string {
+ s := "";
+ if x.neg {
+ s = "-";
+ }
+ return s + stringN(x.abs, 10);
+}