}
-// Div calculates q = (x-r)/y where 0 <= r < y. The receiver is set to q.
-func (z *Int) Div(x, y *Int) (q, r *Int) {
- q = z
- r = new(Int)
- div(q, r, x, y)
- return
+// Div calculates q = (x-r)/y and sets z = q.
+func (z *Int) Div(x, y *Int) *Int {
+ r := new(Int)
+ div(z, r, x, y)
+ return z
}
-// Mod calculates q = (x-r)/y and returns r.
-func (z *Int) Mod(x, y *Int) (r *Int) {
+// Mod calculates q = (x-r)/y and sets z = r.
+func (z *Int) Mod(x, y *Int) *Int {
q := new(Int)
- r = z
- div(q, r, x, y)
- return
+ div(q, z, x, y)
+ return z
+}
+
+
+// DivMod calculates q = (x-r)/y and sets z = q. (It returns z, r.)
+func (z *Int) DivMod(x, y, r *Int) (*Int, *Int) {
+ div(z, r, x, y)
+ return z, r
}
}
+// 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 {
+ return 0
+ }
+ v := int64(z.abs[0])
+ if _W == 32 && len(z.abs) > 1 {
+ v |= int64(z.abs[1]) << 32
+ }
+ if z.neg {
+ v = -v
+ }
+ return v
+}
+
+
// SetString sets z to the value of s, interpreted in the given base.
// If base is 0 then SetString attempts to detect the base by at the prefix of
// s. '0x' implies base 16, '0' implies base 8. Otherwise base 10 is assumed.
temp := new(Int)
for len(B.abs) > 0 {
- q, r := q.Div(A, B)
+ r := new(Int)
+ q, r = q.DivMod(A, B, r)
A, B = B, r
func ProbablyPrime(z *Int, n int) bool { return !z.neg && probablyPrime(z.abs, n) }
-// Rsh sets z = x >> s and returns z.
-func (z *Int) Rsh(x *Int, n int) *Int {
- removedWords := n / _W
- z.abs = makeN(z.abs, len(x.abs)-removedWords, false)
+// Lsh sets z = x << n and returns z.
+func (z *Int) Lsh(x *Int, n uint) *Int {
+ addedWords := int(n) / _W
+ // Don't assign z.abs yet, in case z == x
+ znew := makeN(z.abs, len(x.abs)+addedWords+1, false)
z.neg = x.neg
- shiftRight(z.abs, x.abs[removedWords:], n%_W)
- z.abs = normN(z.abs)
+ shiftLeft(znew[addedWords:], x.abs, n%_W)
+ for i := range znew[0:addedWords] {
+ znew[i] = 0
+ }
+ z.abs = normN(znew)
+ return z
+}
+
+
+// Rsh sets z = x >> n and returns z.
+func (z *Int) Rsh(x *Int, n uint) *Int {
+ removedWords := int(n) / _W
+ // Don't assign z.abs yet, in case z == x
+ znew := makeN(z.abs, len(x.abs)-removedWords, false)
+ z.neg = x.neg
+ shiftRight(znew, x.abs[removedWords:], n%_W)
+ z.abs = normN(znew)
return z
}
for i, test := range divSignsTests {
x := new(Int).New(test.x)
y := new(Int).New(test.y)
- q, r := new(Int).Div(x, y)
+ r := new(Int)
+ q, r := new(Int).DivMod(x, y, r)
expectedQ := new(Int).New(test.q)
expectedR := new(Int).New(test.r)
return true
}
- q, r := new(Int).Div(u, v)
+ r := new(Int)
+ q, r := new(Int).DivMod(u, v, r)
if r.Cmp(v) >= 0 {
return false
expectedQ, _ := new(Int).SetString(test.q, 10)
expectedR, _ := new(Int).SetString(test.r, 10)
- q, r := new(Int).Div(x, y)
+ r := new(Int)
+ q, r := new(Int).DivMod(x, y, r)
if q.Cmp(expectedQ) != 0 || r.Cmp(expectedR) != 0 {
t.Errorf("#%d got (%s, %s) want (%s, %s)", i, q, r, expectedQ, expectedR)
u := &Int{false, []Word{0, 0, 1 + 1<<(_W-1), _M ^ (1 << (_W - 1))}}
v := &Int{false, []Word{5, 2 + 1<<(_W-1), 1 << (_W - 1)}}
- q, r := new(Int).Div(u, v)
+ r := new(Int)
+ q, r := new(Int).DivMod(u, v, r)
const expectedQ64 = "18446744073709551613"
const expectedR64 = "3138550867693340382088035895064302439801311770021610913807"
const expectedQ32 = "4294967293"
}
-type rshTest struct {
+type intShiftTest struct {
in string
- shift int
+ shift uint
out string
}
-var rshTests = []rshTest{
- rshTest{"0", 0, "0"},
- rshTest{"0", 1, "0"},
- rshTest{"0", 2, "0"},
- rshTest{"1", 0, "1"},
- rshTest{"1", 1, "0"},
- rshTest{"1", 2, "0"},
- rshTest{"2", 0, "2"},
- rshTest{"2", 1, "1"},
- rshTest{"2", 2, "0"},
- rshTest{"4294967296", 0, "4294967296"},
- rshTest{"4294967296", 1, "2147483648"},
- rshTest{"4294967296", 2, "1073741824"},
- rshTest{"18446744073709551616", 0, "18446744073709551616"},
- rshTest{"18446744073709551616", 1, "9223372036854775808"},
- rshTest{"18446744073709551616", 2, "4611686018427387904"},
- rshTest{"18446744073709551616", 64, "1"},
- rshTest{"340282366920938463463374607431768211456", 64, "18446744073709551616"},
- rshTest{"340282366920938463463374607431768211456", 128, "1"},
+var rshTests = []intShiftTest{
+ intShiftTest{"0", 0, "0"},
+ intShiftTest{"0", 1, "0"},
+ intShiftTest{"0", 2, "0"},
+ intShiftTest{"1", 0, "1"},
+ intShiftTest{"1", 1, "0"},
+ intShiftTest{"1", 2, "0"},
+ intShiftTest{"2", 0, "2"},
+ intShiftTest{"2", 1, "1"},
+ intShiftTest{"2", 2, "0"},
+ intShiftTest{"4294967296", 0, "4294967296"},
+ intShiftTest{"4294967296", 1, "2147483648"},
+ intShiftTest{"4294967296", 2, "1073741824"},
+ intShiftTest{"18446744073709551616", 0, "18446744073709551616"},
+ intShiftTest{"18446744073709551616", 1, "9223372036854775808"},
+ intShiftTest{"18446744073709551616", 2, "4611686018427387904"},
+ intShiftTest{"18446744073709551616", 64, "1"},
+ intShiftTest{"340282366920938463463374607431768211456", 64, "18446744073709551616"},
+ intShiftTest{"340282366920938463463374607431768211456", 128, "1"},
}
}
}
}
+
+
+func TestRshSelf(t *testing.T) {
+ for i, test := range rshTests {
+ z, _ := new(Int).SetString(test.in, 10)
+ expected, _ := new(Int).SetString(test.out, 10)
+ z.Rsh(z, test.shift)
+
+ if z.Cmp(expected) != 0 {
+ t.Errorf("#%d got %s want %s", i, z, expected)
+ }
+ }
+}
+
+
+var lshTests = []intShiftTest{
+ intShiftTest{"0", 0, "0"},
+ intShiftTest{"0", 1, "0"},
+ intShiftTest{"0", 2, "0"},
+ intShiftTest{"1", 0, "1"},
+ intShiftTest{"1", 1, "2"},
+ intShiftTest{"1", 2, "4"},
+ intShiftTest{"2", 0, "2"},
+ intShiftTest{"2", 1, "4"},
+ intShiftTest{"2", 2, "8"},
+ intShiftTest{"-87", 1, "-174"},
+ intShiftTest{"4294967296", 0, "4294967296"},
+ intShiftTest{"4294967296", 1, "8589934592"},
+ intShiftTest{"4294967296", 2, "17179869184"},
+ intShiftTest{"18446744073709551616", 0, "18446744073709551616"},
+ intShiftTest{"9223372036854775808", 1, "18446744073709551616"},
+ intShiftTest{"4611686018427387904", 2, "18446744073709551616"},
+ intShiftTest{"1", 64, "18446744073709551616"},
+ intShiftTest{"18446744073709551616", 64, "340282366920938463463374607431768211456"},
+ intShiftTest{"1", 128, "340282366920938463463374607431768211456"},
+}
+
+
+func TestLsh(t *testing.T) {
+ for i, test := range lshTests {
+ in, _ := new(Int).SetString(test.in, 10)
+ expected, _ := new(Int).SetString(test.out, 10)
+ out := new(Int).Lsh(in, test.shift)
+
+ if out.Cmp(expected) != 0 {
+ t.Errorf("#%d got %s want %s", i, out, expected)
+ }
+ }
+}
+
+
+func TestLshSelf(t *testing.T) {
+ for i, test := range lshTests {
+ z, _ := new(Int).SetString(test.in, 10)
+ expected, _ := new(Int).SetString(test.out, 10)
+ z.Lsh(z, test.shift)
+
+ if z.Cmp(expected) != 0 {
+ t.Errorf("#%d got %s want %s", i, z, expected)
+ }
+ }
+}
+
+
+func TestLshRsh(t *testing.T) {
+ for i, test := range rshTests {
+ in, _ := new(Int).SetString(test.in, 10)
+ out := new(Int).Lsh(in, test.shift)
+ out = out.Rsh(out, test.shift)
+
+ if in.Cmp(out) != 0 {
+ t.Errorf("#%d got %s want %s", i, out, in)
+ }
+ }
+ for i, test := range lshTests {
+ in, _ := new(Int).SetString(test.in, 10)
+ out := new(Int).Lsh(in, test.shift)
+ out.Rsh(out, test.shift)
+
+ if in.Cmp(out) != 0 {
+ t.Errorf("#%d got %s want %s", i, out, in)
+ }
+ }
+}
+
+
+var int64Tests = []int64{
+ 0,
+ 1,
+ -1,
+ 4294967295,
+ -4294967295,
+ 4294967296,
+ -4294967296,
+ 9223372036854775807,
+ -9223372036854775807,
+ -9223372036854775808,
+}
+
+func TestInt64(t *testing.T) {
+ for i, testVal := range int64Tests {
+ in := NewInt(testVal)
+ out := in.Int64()
+
+ if out != testVal {
+ t.Errorf("#%d got %d want %d", i, out, testVal)
+ }
+ }
+}