2009-08-14 12:53:27 -06:00
|
|
|
// 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
|
|
|
|
|
2009-08-15 12:43:54 -06:00
|
|
|
// An Int represents a signed multi-precision integer.
|
|
|
|
// The zero value for an Int represents the value 0.
|
|
|
|
type Int struct {
|
2009-08-14 12:53:27 -06:00
|
|
|
neg bool; // sign
|
2009-08-15 12:43:54 -06:00
|
|
|
abs []Word; // absolute value of the integer
|
2009-08-14 12:53:27 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-08-15 12:43:54 -06:00
|
|
|
// New sets z to x.
|
|
|
|
func (z *Int) New(x int64) *Int {
|
2009-08-14 12:53:27 -06:00
|
|
|
z.neg = false;
|
|
|
|
if x < 0 {
|
|
|
|
z.neg = true;
|
|
|
|
x = -x;
|
|
|
|
}
|
2009-08-15 12:43:54 -06:00
|
|
|
z.abs = newN(z.abs, uint64(x));
|
2009-08-14 12:53:27 -06:00
|
|
|
return z;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-08-15 12:43:54 -06:00
|
|
|
// Set sets z to x.
|
|
|
|
func (z *Int) Set(x *Int) *Int {
|
2009-08-14 12:53:27 -06:00
|
|
|
z.neg = x.neg;
|
2009-08-15 12:43:54 -06:00
|
|
|
z.abs = setN(z.abs, x.abs);
|
2009-08-14 12:53:27 -06:00
|
|
|
return z;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-08-15 12:43:54 -06:00
|
|
|
// Add computes z = x+y.
|
|
|
|
func (z *Int) Add(x, y *Int) *Int {
|
2009-08-14 12:53:27 -06:00
|
|
|
if x.neg == y.neg {
|
|
|
|
// x + y == x + y
|
|
|
|
// (-x) + (-y) == -(x + y)
|
|
|
|
z.neg = x.neg;
|
2009-08-15 12:43:54 -06:00
|
|
|
z.abs = addNN(z.abs, x.abs, y.abs);
|
2009-08-14 12:53:27 -06:00
|
|
|
} else {
|
|
|
|
// x + (-y) == x - y == -(y - x)
|
|
|
|
// (-x) + y == y - x == -(x - y)
|
2009-08-15 12:43:54 -06:00
|
|
|
if cmpNN(x.abs, y.abs) >= 0 {
|
2009-08-14 12:53:27 -06:00
|
|
|
z.neg = x.neg;
|
2009-08-15 12:43:54 -06:00
|
|
|
z.abs = subNN(z.abs, x.abs, y.abs);
|
2009-08-14 12:53:27 -06:00
|
|
|
} else {
|
|
|
|
z.neg = !x.neg;
|
2009-08-15 12:43:54 -06:00
|
|
|
z.abs = subNN(z.abs, y.abs, x.abs);
|
2009-08-14 12:53:27 -06:00
|
|
|
}
|
|
|
|
}
|
2009-08-15 12:43:54 -06:00
|
|
|
if len(z.abs) == 0 {
|
2009-08-14 12:53:27 -06:00
|
|
|
z.neg = false; // 0 has no sign
|
|
|
|
}
|
|
|
|
return z
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-08-15 12:43:54 -06:00
|
|
|
// Sub computes z = x-y.
|
|
|
|
func (z *Int) Sub(x, y *Int) *Int {
|
2009-08-14 12:53:27 -06:00
|
|
|
if x.neg != y.neg {
|
|
|
|
// x - (-y) == x + y
|
|
|
|
// (-x) - y == -(x + y)
|
|
|
|
z.neg = x.neg;
|
2009-08-15 12:43:54 -06:00
|
|
|
z.abs = addNN(z.abs, x.abs, y.abs);
|
2009-08-14 12:53:27 -06:00
|
|
|
} else {
|
|
|
|
// x - y == x - y == -(y - x)
|
|
|
|
// (-x) - (-y) == y - x == -(x - y)
|
2009-08-15 12:43:54 -06:00
|
|
|
if cmpNN(x.abs, y.abs) >= 0 {
|
2009-08-14 12:53:27 -06:00
|
|
|
z.neg = x.neg;
|
2009-08-15 12:43:54 -06:00
|
|
|
z.abs = subNN(z.abs, x.abs, y.abs);
|
2009-08-14 12:53:27 -06:00
|
|
|
} else {
|
|
|
|
z.neg = !x.neg;
|
2009-08-15 12:43:54 -06:00
|
|
|
z.abs = subNN(z.abs, y.abs, x.abs);
|
2009-08-14 12:53:27 -06:00
|
|
|
}
|
|
|
|
}
|
2009-08-15 12:43:54 -06:00
|
|
|
if len(z.abs) == 0 {
|
2009-08-14 12:53:27 -06:00
|
|
|
z.neg = false; // 0 has no sign
|
|
|
|
}
|
|
|
|
return z
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-08-15 12:43:54 -06:00
|
|
|
// Mul computes z = x*y.
|
|
|
|
func (z *Int) Mul(x, y *Int) *Int {
|
2009-08-14 12:53:27 -06:00
|
|
|
// x * y == x * y
|
|
|
|
// x * (-y) == -(x * y)
|
|
|
|
// (-x) * y == -(x * y)
|
|
|
|
// (-x) * (-y) == x * y
|
|
|
|
z.neg = x.neg != y.neg;
|
2009-08-15 12:43:54 -06:00
|
|
|
z.abs = mulNN(z.abs, x.abs, y.abs);
|
2009-08-14 12:53:27 -06:00
|
|
|
return z
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-08-15 12:43:54 -06:00
|
|
|
// 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);
|
2009-08-14 12:53:27 -06:00
|
|
|
return z;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-08-15 12:43:54 -06:00
|
|
|
// CmpInt compares x and y. The result is an int value that is
|
2009-08-14 12:53:27 -06:00
|
|
|
//
|
|
|
|
// < 0 if x < y
|
|
|
|
// == 0 if x == y
|
|
|
|
// > 0 if x > y
|
|
|
|
//
|
2009-08-15 12:43:54 -06:00
|
|
|
func CmpInt(x, y *Int) (r int) {
|
2009-08-14 12:53:27 -06:00
|
|
|
// 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:
|
2009-08-15 12:43:54 -06:00
|
|
|
r = cmpNN(x.abs, y.abs);
|
2009-08-14 12:53:27 -06:00
|
|
|
if x.neg {
|
|
|
|
r = -r;
|
|
|
|
}
|
|
|
|
case x.neg:
|
|
|
|
r = -1;
|
|
|
|
default:
|
|
|
|
r = 1;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-08-15 12:43:54 -06:00
|
|
|
func (x *Int) String() string {
|
2009-08-14 12:53:27 -06:00
|
|
|
s := "";
|
|
|
|
if x.neg {
|
|
|
|
s = "-";
|
|
|
|
}
|
2009-08-15 12:43:54 -06:00
|
|
|
return s + stringN(x.abs, 10);
|
2009-08-14 12:53:27 -06:00
|
|
|
}
|