259 lines
5.1 KiB
Go
259 lines
5.1 KiB
Go
// 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.
|
|
|
|
//go:build gmp
|
|
// +build gmp
|
|
|
|
// Test extra functionality
|
|
|
|
package gmp
|
|
|
|
import (
|
|
"math/rand"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
type binaryFun func(a, b int64) bool
|
|
type ternaryFun func(a, b, c int64) bool
|
|
|
|
var random *rand.Rand
|
|
var perFuncTests []int
|
|
|
|
func init() {
|
|
random = rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
perFuncTests = random.Perm(50)
|
|
}
|
|
|
|
func randoms(num int, bits int) <-chan int64 {
|
|
channel := make(chan int64)
|
|
go func(out chan<- int64) {
|
|
for _, i := range random.Perm(num) {
|
|
ran := random.Int63n(1<<uint(bits-1) - 1)
|
|
if i&1 == 1 {
|
|
ran = -ran
|
|
}
|
|
out <- ran
|
|
}
|
|
close(out)
|
|
}(channel)
|
|
return channel
|
|
}
|
|
|
|
func absi(i int64) int64 {
|
|
if i < 0 {
|
|
return -i
|
|
}
|
|
return i
|
|
}
|
|
|
|
func cmpi(a, b int64) int {
|
|
if a < b {
|
|
return -1
|
|
}
|
|
if a > b {
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func testBinary(t *testing.T, name string, fun binaryFun, maxBits int) {
|
|
small := [...]int64{0, 1, -1, 2, -2, 3, -3}
|
|
for _, x := range small {
|
|
for _, y := range small {
|
|
if !fun(x, y) {
|
|
t.Errorf("%s failed for %v and %v", name, x, y)
|
|
}
|
|
}
|
|
}
|
|
for x := range randoms(10, maxBits) {
|
|
for y := range randoms(10, maxBits) {
|
|
if !fun(x, y) {
|
|
t.Errorf("%s failed for %v and %v", name, x, y)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func testTernary(t *testing.T, name string, fun ternaryFun) {
|
|
small := [...]int64{0, 1, -1, 2, -2, 3, -3}
|
|
for _, x := range small {
|
|
for _, y := range small {
|
|
for _, z := range small {
|
|
if !fun(x, y, z) {
|
|
t.Errorf("%s failed for %v, %v and %v", name, x, y, z)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
num, bits := 6, 30
|
|
for x := range randoms(num, bits) {
|
|
for y := range randoms(num, bits) {
|
|
for z := range randoms(num, bits) {
|
|
if !fun(x, y, z) {
|
|
t.Errorf("%s failed for %v, %v and %v", name, x, y, z)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSwap(t *testing.T) {
|
|
fun := func(i, j int64) bool {
|
|
a := NewInt(i)
|
|
b := NewInt(j)
|
|
a.Swap(b)
|
|
return i == b.Int64() && j == a.Int64()
|
|
}
|
|
testBinary(t, "Swap", fun, 64)
|
|
}
|
|
|
|
func TestAddMul(t *testing.T) {
|
|
fun := func(i, j, k int64) bool {
|
|
a := NewInt(i)
|
|
return a.AddMul(NewInt(j), NewInt(k)).Int64() == i+j*k
|
|
}
|
|
testTernary(t, "AddMul", fun)
|
|
}
|
|
|
|
func TestAddUint32(t *testing.T) {
|
|
fun := func(i, j int64) bool {
|
|
a := NewInt(i)
|
|
k := uint32(j)
|
|
return a.AddUint32(a, k).Int64() == i+int64(k)
|
|
}
|
|
testBinary(t, "AddUint32", fun, 62)
|
|
}
|
|
|
|
func TestSubUint32(t *testing.T) {
|
|
fun := func(i, j int64) bool {
|
|
a := NewInt(i)
|
|
k := uint32(j)
|
|
return a.SubUint32(a, k).Int64() == i-int64(k)
|
|
}
|
|
testBinary(t, "SubUint32", fun, 62)
|
|
}
|
|
|
|
func TestUint32Sub(t *testing.T) {
|
|
fun := func(i, j int64) bool {
|
|
a := NewInt(i)
|
|
k := uint32(j)
|
|
return a.Uint32Sub(k, a).Int64() == int64(k)-i
|
|
}
|
|
testBinary(t, "Uint32Sub", fun, 62)
|
|
}
|
|
|
|
func TestMulUint32(t *testing.T) {
|
|
fun := func(i, j int64) bool {
|
|
a := NewInt(i)
|
|
k := uint32(j)
|
|
return a.MulUint32(a, k).Int64() == i*int64(k)
|
|
}
|
|
testBinary(t, "MulUint32", fun, 30)
|
|
}
|
|
|
|
func TestMulInt32(t *testing.T) {
|
|
fun := func(i, j int64) bool {
|
|
a := NewInt(i)
|
|
k := int32(j)
|
|
return a.MulInt32(a, k).Int64() == i*int64(k)
|
|
}
|
|
testBinary(t, "MulInt32", fun, 30)
|
|
}
|
|
|
|
func TestAddMulUint32(t *testing.T) {
|
|
fun := func(i, j, k int64) bool {
|
|
a := NewInt(i)
|
|
n := uint32(k)
|
|
return a.AddMulUint32(NewInt(j), n).Int64() == i+j*int64(n)
|
|
}
|
|
testTernary(t, "AddMulUint32", fun)
|
|
}
|
|
|
|
func TestSubMul(t *testing.T) {
|
|
fun := func(i, j, k int64) bool {
|
|
a := NewInt(i)
|
|
return a.SubMul(NewInt(j), NewInt(k)).Int64() == i-j*k
|
|
}
|
|
testTernary(t, "SubMul", fun)
|
|
}
|
|
|
|
func TestSubMulUint32(t *testing.T) {
|
|
fun := func(i, j, k int64) bool {
|
|
a := NewInt(i)
|
|
n := uint32(k)
|
|
return a.SubMulUint32(NewInt(j), n).Int64() == i-j*int64(n)
|
|
}
|
|
testTernary(t, "SubMulUint32", fun)
|
|
}
|
|
|
|
func TestCmpUint32(t *testing.T) {
|
|
fun := func(i, j int64) bool {
|
|
a := NewInt(i)
|
|
k := uint32(j)
|
|
return a.CmpUint32(k) == cmpi(i, int64(k))
|
|
}
|
|
testBinary(t, "CmpUint32", fun, 64)
|
|
}
|
|
|
|
func TestCmpInt32(t *testing.T) {
|
|
fun := func(i, j int64) bool {
|
|
a := NewInt(i)
|
|
k := int32(j)
|
|
return a.CmpInt32(k) == cmpi(i, int64(k))
|
|
}
|
|
testBinary(t, "CmpInt32", fun, 64)
|
|
}
|
|
|
|
func TestCmpAbs(t *testing.T) {
|
|
fun := func(i, j int64) bool {
|
|
a := NewInt(i)
|
|
return a.CmpAbs(NewInt(j)) == cmpi(absi(i), absi(j))
|
|
}
|
|
testBinary(t, "CmpAbs", fun, 64)
|
|
}
|
|
|
|
func TestCmpAbsUint32(t *testing.T) {
|
|
fun := func(i, j int64) bool {
|
|
a := NewInt(i)
|
|
k := uint32(j)
|
|
return a.CmpAbsUint32(k) == cmpi(absi(i), int64(k))
|
|
}
|
|
testBinary(t, "CmpAbsUint32", fun, 64)
|
|
}
|
|
|
|
func TestUint32(t *testing.T) {
|
|
for range perFuncTests {
|
|
var n = uint32(random.Int63())
|
|
if NewInt(int64(n)).Uint32() != n {
|
|
t.Errorf("Uint32 failed for %v", n)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestInt32(t *testing.T) {
|
|
for range perFuncTests {
|
|
var n = int32(random.Int63())
|
|
if NewInt(int64(n)).Int32() != n {
|
|
t.Errorf("Int32 failed for %v", n)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSqrt(t *testing.T) {
|
|
a := NewInt(1)
|
|
aSquared := NewInt(1)
|
|
ten := NewInt(10)
|
|
hundred := NewInt(100)
|
|
root := new(Int)
|
|
for range perFuncTests {
|
|
root := root.Sqrt(aSquared)
|
|
if root.Cmp(a) != 0 {
|
|
t.Errorf("Sqrt failed got %d expecting %d", root, a)
|
|
}
|
|
a.Mul(a, ten)
|
|
aSquared.Mul(aSquared, hundred)
|
|
}
|
|
}
|