mirror of
https://github.com/golang/go
synced 2024-11-26 02:27:56 -07:00
snapshot:
- renamed Z -> Int - made Int ops methods on *Int - "install" assembly routines dynamically - replace mulVW functions with mulAddVWW of equivalent performance but symmetric functionality to divWVW - implemented scanN status: - need mulNN (trivial) - need division/modulo after which the set of elementary operations is complete - to/from string conversion working R=rsc DELTA=320 (124 added, 50 deleted, 146 changed) OCL=33308 CL=33341
This commit is contained in:
parent
b21425ddee
commit
e5874223ef
@ -13,11 +13,13 @@ import "unsafe"
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Elementary operations on words
|
// Elementary operations on words
|
||||||
|
//
|
||||||
|
// These operations are used by the vector operations below.
|
||||||
|
|
||||||
func addWW_s(x, y, c Word) (z1, z0 Word)
|
func addWW_s(x, y, c Word) (z1, z0 Word)
|
||||||
|
|
||||||
// z1<<_W + z0 = x+y+c, with c == 0 or 1
|
// z1<<_W + z0 = x+y+c, with c == 0 or 1
|
||||||
func addWW(x, y, c Word) (z1, z0 Word) {
|
func addWW_g(x, y, c Word) (z1, z0 Word) {
|
||||||
yc := y+c;
|
yc := y+c;
|
||||||
z0 = x+yc;
|
z0 = x+yc;
|
||||||
if z0 < x || yc < y {
|
if z0 < x || yc < y {
|
||||||
@ -30,7 +32,7 @@ func addWW(x, y, c Word) (z1, z0 Word) {
|
|||||||
func subWW_s(x, y, c Word) (z1, z0 Word)
|
func subWW_s(x, y, c Word) (z1, z0 Word)
|
||||||
|
|
||||||
// z1<<_W + z0 = x-y-c, with c == 0 or 1
|
// z1<<_W + z0 = x-y-c, with c == 0 or 1
|
||||||
func subWW(x, y, c Word) (z1, z0 Word) {
|
func subWW_g(x, y, c Word) (z1, z0 Word) {
|
||||||
yc := y+c;
|
yc := y+c;
|
||||||
z0 = x-yc;
|
z0 = x-yc;
|
||||||
if z0 > x || yc < y {
|
if z0 > x || yc < y {
|
||||||
@ -40,8 +42,12 @@ func subWW(x, y, c Word) (z1, z0 Word) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO(gri) mulWW_g is not needed anymore. Keep around for
|
||||||
|
// now since mulAddWWW_g should use some of the
|
||||||
|
// optimizations from mulWW_g eventually.
|
||||||
|
|
||||||
// z1<<_W + z0 = x*y
|
// z1<<_W + z0 = x*y
|
||||||
func mulW(x, y Word) (z1, z0 Word) {
|
func mulWW_g(x, y Word) (z1, z0 Word) {
|
||||||
// Split x and y into 2 halfWords each, multiply
|
// Split x and y into 2 halfWords each, multiply
|
||||||
// the halfWords separately while avoiding overflow,
|
// the halfWords separately while avoiding overflow,
|
||||||
// and return the product as 2 Words.
|
// and return the product as 2 Words.
|
||||||
@ -96,7 +102,7 @@ func mulW(x, y Word) (z1, z0 Word) {
|
|||||||
|
|
||||||
|
|
||||||
// z1<<_W + z0 = x*y + c
|
// z1<<_W + z0 = x*y + c
|
||||||
func mulAddWW(x, y, c Word) (z1, z0 Word) {
|
func mulAddWWW_g(x, y, c Word) (z1, z0 Word) {
|
||||||
// Split x and y into 2 halfWords each, multiply
|
// Split x and y into 2 halfWords each, multiply
|
||||||
// the halfWords separately while avoiding overflow,
|
// the halfWords separately while avoiding overflow,
|
||||||
// and return the product as 2 Words.
|
// and return the product as 2 Words.
|
||||||
@ -124,17 +130,17 @@ func mulAddWW(x, y, c Word) (z1, z0 Word) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func divWW_s(x1, x0, y Word) (q, r Word)
|
func divWWW_s(x1, x0, y Word) (q, r Word)
|
||||||
|
|
||||||
// q = (x1<<_W + x0 - r)/y
|
// q = (x1<<_W + x0 - r)/y
|
||||||
func divWW(x1, x0, y Word) (q, r Word) {
|
func divWW_g(x1, x0, y Word) (q, r Word) {
|
||||||
if x1 == 0 {
|
if x1 == 0 {
|
||||||
q, r = x0/y, x0%y;
|
q, r = x0/y, x0%y;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(gri) implement general case w/o assembly code
|
// TODO(gri) implement general case w/o assembly code
|
||||||
q, r = divWW_s(x1, x0, y);
|
q, r = divWWW_s(x1, x0, y);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,98 +148,105 @@ func divWW(x1, x0, y Word) (q, r Word) {
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Elementary operations on vectors
|
// Elementary operations on vectors
|
||||||
|
|
||||||
// For each function f there is a corresponding function f_s which
|
// All higher-level functions use these elementary vector operations.
|
||||||
// implements the same functionality as f but is written in assembly.
|
// The function pointers f are initialized with default implementations
|
||||||
|
// f_g, written in Go for portability. The corresponding assembly routines
|
||||||
|
// f_s should be installed if they exist.
|
||||||
|
var (
|
||||||
|
// addVV sets z and returns c such that z+c = x+y.
|
||||||
|
addVV func(z, x, y *Word, n int) (c Word) = addVV_g;
|
||||||
|
|
||||||
|
// subVV sets z and returns c such that z-c = x-y.
|
||||||
|
subVV func(z, x, y *Word, n int) (c Word) = subVV_g;
|
||||||
|
|
||||||
|
// addVW sets z and returns c such that z+c = x-y.
|
||||||
|
addVW func(z, x *Word, y Word, n int) (c Word) = addVW_g;
|
||||||
|
|
||||||
|
// subVW sets z and returns c such that z-c = x-y.
|
||||||
|
subVW func(z, x *Word, y Word, n int) (c Word) = subVW_g;
|
||||||
|
|
||||||
|
// mulAddVWW sets z and returns c such that z+c = x*y + r.
|
||||||
|
mulAddVWW func(z, x *Word, y, r Word, n int) (c Word) = mulAddVWW_g;
|
||||||
|
|
||||||
|
// divWVW sets z and returns r such that z-r = (xn<<(n*_W) + x) / y.
|
||||||
|
divWVW func(z* Word, xn Word, x *Word, y Word, n int) (r Word) = divWVW_g;
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func useAsm() bool
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if useAsm() {
|
||||||
|
// Install assemby routines.
|
||||||
|
// TODO(gri) This should only be done if the assembly routines are present.
|
||||||
|
addVV = addVV_s;
|
||||||
|
subVV = subVV_s;
|
||||||
|
addVW = addVW_s;
|
||||||
|
subVW = subVW_s;
|
||||||
|
mulAddVWW = mulAddVWW_s;
|
||||||
|
divWVW = divWVW_s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (p *Word) at(i int) *Word {
|
||||||
|
return (*Word)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + uintptr(i)*_S));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func addVV_s(z, x, y *Word, n int) (c Word)
|
func addVV_s(z, x, y *Word, n int) (c Word)
|
||||||
|
func addVV_g(z, x, y *Word, n int) (c Word) {
|
||||||
// addVV sets z and returns c such that z+c = x+y.
|
|
||||||
// z, x, y are n-word vectors.
|
|
||||||
func addVV(z, x, y *Word, n int) (c Word) {
|
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
c, *z = addWW(*x, *y, c);
|
c, *z.at(i) = addWW_g(*x.at(i), *y.at(i), c);
|
||||||
x = (*Word)(unsafe.Pointer((uintptr(unsafe.Pointer(x)) + _S)));
|
|
||||||
y = (*Word)(unsafe.Pointer((uintptr(unsafe.Pointer(y)) + _S)));
|
|
||||||
z = (*Word)(unsafe.Pointer((uintptr(unsafe.Pointer(z)) + _S)));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func subVV_s(z, x, y *Word, n int) (c Word)
|
func subVV_s(z, x, y *Word, n int) (c Word)
|
||||||
|
func subVV_g(z, x, y *Word, n int) (c Word) {
|
||||||
// subVV sets z and returns c such that z-c = x-y.
|
|
||||||
// z, x, y are n-word vectors.
|
|
||||||
func subVV(z, x, y *Word, n int) (c Word) {
|
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
c, *z = subWW(*x, *y, c);
|
c, *z.at(i) = subWW_g(*x.at(i), *y.at(i), c);
|
||||||
x = (*Word)(unsafe.Pointer((uintptr(unsafe.Pointer(x)) + _S)));
|
|
||||||
y = (*Word)(unsafe.Pointer((uintptr(unsafe.Pointer(y)) + _S)));
|
|
||||||
z = (*Word)(unsafe.Pointer((uintptr(unsafe.Pointer(z)) + _S)));
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func addVW_s(z, x *Word, y Word, n int) (c Word)
|
func addVW_s(z, x *Word, y Word, n int) (c Word)
|
||||||
|
func addVW_g(z, x *Word, y Word, n int) (c Word) {
|
||||||
// addVW sets z and returns c such that z+c = x-y.
|
|
||||||
// z, x are n-word vectors.
|
|
||||||
func addVW(z, x *Word, y Word, n int) (c Word) {
|
|
||||||
c = y;
|
c = y;
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
c, *z = addWW(*x, c, 0);
|
c, *z.at(i) = addWW_g(*x.at(i), c, 0);
|
||||||
x = (*Word)(unsafe.Pointer((uintptr(unsafe.Pointer(x)) + _S)));
|
|
||||||
z = (*Word)(unsafe.Pointer((uintptr(unsafe.Pointer(z)) + _S)));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func subVW_s(z, x *Word, y Word, n int) (c Word)
|
func subVW_s(z, x *Word, y Word, n int) (c Word)
|
||||||
|
func subVW_g(z, x *Word, y Word, n int) (c Word) {
|
||||||
// subVW sets z and returns c such that z-c = x-y.
|
|
||||||
// z, x are n-word vectors.
|
|
||||||
func subVW(z, x *Word, y Word, n int) (c Word) {
|
|
||||||
c = y;
|
c = y;
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
c, *z = subWW(*x, c, 0);
|
c, *z.at(i) = subWW_g(*x.at(i), c, 0);
|
||||||
x = (*Word)(unsafe.Pointer((uintptr(unsafe.Pointer(x)) + _S)));
|
|
||||||
z = (*Word)(unsafe.Pointer((uintptr(unsafe.Pointer(z)) + _S)));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func mulVW_s(z, x *Word, y Word, n int) (c Word)
|
func mulAddVWW_s(z, x *Word, y, r Word, n int) (c Word)
|
||||||
|
func mulAddVWW_g(z, x *Word, y, r Word, n int) (c Word) {
|
||||||
// mulVW sets z and returns c such that z+c = x*y.
|
c = r;
|
||||||
// z, x are n-word vectors.
|
|
||||||
func mulVW(z, x *Word, y Word, n int) (c Word) {
|
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
c, *z = mulAddWW(*x, y, c);
|
c, *z.at(i) = mulAddWWW_g(*x.at(i), y, c);
|
||||||
x = (*Word)(unsafe.Pointer((uintptr(unsafe.Pointer(x)) + _S)));
|
|
||||||
z = (*Word)(unsafe.Pointer((uintptr(unsafe.Pointer(z)) + _S)));
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func divWVW_s(z* Word, xn Word, x *Word, y Word, n int) (r Word)
|
func divWVW_s(z* Word, xn Word, x *Word, y Word, n int) (r Word)
|
||||||
|
func divWVW_g(z* Word, xn Word, x *Word, y Word, n int) (r Word) {
|
||||||
// divWVW sets z and returns r such that z-r = (xn<<(n*_W) + x) / y.
|
|
||||||
// z, x are n-word vectors; xn is the extra word x[n] of x.
|
|
||||||
func divWVW(z* Word, xn Word, x *Word, y Word, n int) (r Word) {
|
|
||||||
r = xn;
|
r = xn;
|
||||||
x = (*Word)(unsafe.Pointer((uintptr(unsafe.Pointer(x)) + uintptr(n-1)*_S)));
|
|
||||||
z = (*Word)(unsafe.Pointer((uintptr(unsafe.Pointer(z)) + uintptr(n-1)*_S)));
|
|
||||||
for i := n-1; i >= 0; i-- {
|
for i := n-1; i >= 0; i-- {
|
||||||
*z, r = divWW(r, *x, y);
|
*z.at(i), r = divWW_g(r, *x.at(i), y);
|
||||||
x = (*Word)(unsafe.Pointer((uintptr(unsafe.Pointer(x)) - _S)));
|
|
||||||
z = (*Word)(unsafe.Pointer((uintptr(unsafe.Pointer(z)) - _S)));
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,11 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// This file provides fast assembly versions of the routines in arith.go.
|
// This file provides fast assembly versions of the routines in arith.go.
|
||||||
//
|
|
||||||
// Note: Eventually, these functions should be named like their corresponding
|
TEXT big·useAsm(SB),7,$0
|
||||||
// Go implementations. For now their names have "_s" appended so that
|
MOVB $1, 8(SP)
|
||||||
// they can be linked and tested together.
|
RET
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Elementary operations on words
|
// Elementary operations on words
|
||||||
@ -39,21 +40,10 @@ TEXT big·subWW_s(SB),7,$0
|
|||||||
RET
|
RET
|
||||||
|
|
||||||
|
|
||||||
// func mulWW_s(x, y Word) (z1, z0 Word)
|
// func mulAddWWW_s(x, y, c Word) (z1, z0 Word)
|
||||||
// z1<<64 + z0 = x*y
|
|
||||||
//
|
|
||||||
TEXT big·mulWW_s(SB),7,$0
|
|
||||||
MOVQ a+0(FP), AX
|
|
||||||
MULQ a+8(FP)
|
|
||||||
MOVQ DX, a+16(FP)
|
|
||||||
MOVQ AX, a+24(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
|
|
||||||
// func mulAddWW_s(x, y, c Word) (z1, z0 Word)
|
|
||||||
// z1<<64 + z0 = x*y + c
|
// z1<<64 + z0 = x*y + c
|
||||||
//
|
//
|
||||||
TEXT big·mulAddWW_s(SB),7,$0
|
TEXT big·mulAddWWW_s(SB),7,$0
|
||||||
MOVQ a+0(FP), AX
|
MOVQ a+0(FP), AX
|
||||||
MULQ a+8(FP)
|
MULQ a+8(FP)
|
||||||
ADDQ a+16(FP), AX
|
ADDQ a+16(FP), AX
|
||||||
@ -63,10 +53,10 @@ TEXT big·mulAddWW_s(SB),7,$0
|
|||||||
RET
|
RET
|
||||||
|
|
||||||
|
|
||||||
// func divWW_s(x1, x0, y Word) (q, r Word)
|
// func divWWW_s(x1, x0, y Word) (q, r Word)
|
||||||
// q = (x1<<64 + x0)/y + r
|
// q = (x1<<64 + x0)/y + r
|
||||||
//
|
//
|
||||||
TEXT big·divWW_s(SB),7,$0
|
TEXT big·divWWW_s(SB),7,$0
|
||||||
MOVQ a+0(FP), DX
|
MOVQ a+0(FP), DX
|
||||||
MOVQ a+8(FP), AX
|
MOVQ a+8(FP), AX
|
||||||
DIVQ a+16(FP)
|
DIVQ a+16(FP)
|
||||||
@ -174,17 +164,17 @@ E4: CMPQ BX, R11 // i < n
|
|||||||
RET
|
RET
|
||||||
|
|
||||||
|
|
||||||
// func mulVW_s(z, x *Word, y Word, n int) (c Word)
|
// func mulAddVWW_s(z, x *Word, y, r Word, n int) (c Word)
|
||||||
TEXT big·mulVW_s(SB),7,$0
|
TEXT big·mulAddVWW_s(SB),7,$0
|
||||||
MOVQ a+0(FP), R10 // z
|
MOVQ a+0(FP), R10 // z
|
||||||
MOVQ a+8(FP), R8 // x
|
MOVQ a+8(FP), R8 // x
|
||||||
MOVQ a+16(FP), R9 // y
|
MOVQ a+16(FP), R9 // y
|
||||||
MOVL a+24(FP), R11 // n
|
MOVQ a+24(FP), CX // c = r
|
||||||
|
MOVL a+32(FP), R11 // n
|
||||||
XORQ BX, BX // i = 0
|
XORQ BX, BX // i = 0
|
||||||
XORQ CX, CX // c = 0
|
JMP E6
|
||||||
JMP E5
|
|
||||||
|
|
||||||
L5: MOVQ (R8)(BX*8), AX
|
L6: MOVQ (R8)(BX*8), AX
|
||||||
MULQ R9
|
MULQ R9
|
||||||
ADDQ CX, AX
|
ADDQ CX, AX
|
||||||
ADCQ $0, DX
|
ADCQ $0, DX
|
||||||
@ -192,10 +182,10 @@ L5: MOVQ (R8)(BX*8), AX
|
|||||||
MOVQ DX, CX
|
MOVQ DX, CX
|
||||||
ADDL $1, BX // i++
|
ADDL $1, BX // i++
|
||||||
|
|
||||||
E5: CMPQ BX, R11 // i < n
|
E6: CMPQ BX, R11 // i < n
|
||||||
JL L5
|
JL L6
|
||||||
|
|
||||||
MOVQ CX, a+32(FP) // return c
|
MOVQ CX, a+40(FP) // return c
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
|
||||||
@ -206,14 +196,14 @@ TEXT big·divWVW_s(SB),7,$0
|
|||||||
MOVQ a+16(FP), R8 // x
|
MOVQ a+16(FP), R8 // x
|
||||||
MOVQ a+24(FP), R9 // y
|
MOVQ a+24(FP), R9 // y
|
||||||
MOVL a+32(FP), BX // i = n
|
MOVL a+32(FP), BX // i = n
|
||||||
JMP E6
|
JMP E7
|
||||||
|
|
||||||
L6: MOVQ (R8)(BX*8), AX
|
L7: MOVQ (R8)(BX*8), AX
|
||||||
DIVQ R9
|
DIVQ R9
|
||||||
MOVQ AX, (R10)(BX*8)
|
MOVQ AX, (R10)(BX*8)
|
||||||
|
|
||||||
E6: SUBL $1, BX
|
E7: SUBL $1, BX // i--
|
||||||
JGE L6
|
JGE L7 // i >= 0
|
||||||
|
|
||||||
MOVQ DX, a+40(FP) // return r
|
MOVQ DX, a+40(FP) // return r
|
||||||
RET
|
RET
|
||||||
|
@ -36,19 +36,19 @@ func testFunWW(t *testing.T, msg string, f funWW, a argWW) {
|
|||||||
func TestFunWW(t *testing.T) {
|
func TestFunWW(t *testing.T) {
|
||||||
for _, a := range sumWW {
|
for _, a := range sumWW {
|
||||||
arg := a;
|
arg := a;
|
||||||
testFunWW(t, "addWW", addWW, arg);
|
testFunWW(t, "addWW_g", addWW_g, arg);
|
||||||
testFunWW(t, "addWW_s", addWW_s, arg);
|
testFunWW(t, "addWW_s", addWW_s, arg);
|
||||||
|
|
||||||
arg = argWW{a.y, a.x, a.c, a.z1, a.z0};
|
arg = argWW{a.y, a.x, a.c, a.z1, a.z0};
|
||||||
testFunWW(t, "addWW symmetric", addWW, arg);
|
testFunWW(t, "addWW_g symmetric", addWW_g, arg);
|
||||||
testFunWW(t, "addWW_s symmetric", addWW_s, arg);
|
testFunWW(t, "addWW_s symmetric", addWW_s, arg);
|
||||||
|
|
||||||
arg = argWW{a.z0, a.x, a.c, a.z1, a.y};
|
arg = argWW{a.z0, a.x, a.c, a.z1, a.y};
|
||||||
testFunWW(t, "subWW", subWW, arg);
|
testFunWW(t, "subWW_g", subWW_g, arg);
|
||||||
testFunWW(t, "subWW_s", subWW_s, arg);
|
testFunWW(t, "subWW_s", subWW_s, arg);
|
||||||
|
|
||||||
arg = argWW{a.z0, a.y, a.c, a.z1, a.x};
|
arg = argWW{a.z0, a.y, a.c, a.z1, a.x};
|
||||||
testFunWW(t, "subWW symmetric", subWW, arg);
|
testFunWW(t, "subWW_g symmetric", subWW_g, arg);
|
||||||
testFunWW(t, "subWW_s symmetric", subWW_s, arg);
|
testFunWW(t, "subWW_s symmetric", subWW_s, arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,19 +97,19 @@ func testFunVV(t *testing.T, msg string, f funVV, a argVV) {
|
|||||||
func TestFunVV(t *testing.T) {
|
func TestFunVV(t *testing.T) {
|
||||||
for _, a := range sumVV {
|
for _, a := range sumVV {
|
||||||
arg := a;
|
arg := a;
|
||||||
testFunVV(t, "addVV", addVV, arg);
|
testFunVV(t, "addVV_g", addVV_g, arg);
|
||||||
testFunVV(t, "addVV_s", addVV_s, arg);
|
testFunVV(t, "addVV_s", addVV_s, arg);
|
||||||
|
|
||||||
arg = argVV{a.z, a.y, a.x, a.c};
|
arg = argVV{a.z, a.y, a.x, a.c};
|
||||||
testFunVV(t, "addVV symmetric", addVV, arg);
|
testFunVV(t, "addVV_g symmetric", addVV_g, arg);
|
||||||
testFunVV(t, "addVV_s symmetric", addVV_s, arg);
|
testFunVV(t, "addVV_s symmetric", addVV_s, arg);
|
||||||
|
|
||||||
arg = argVV{a.x, a.z, a.y, a.c};
|
arg = argVV{a.x, a.z, a.y, a.c};
|
||||||
testFunVV(t, "subVV", subVV, arg);
|
testFunVV(t, "subVV_g", subVV_g, arg);
|
||||||
testFunVV(t, "subVV_s", subVV_s, arg);
|
testFunVV(t, "subVV_s", subVV_s, arg);
|
||||||
|
|
||||||
arg = argVV{a.y, a.z, a.x, a.c};
|
arg = argVV{a.y, a.z, a.x, a.c};
|
||||||
testFunVV(t, "subVV symmetric", subVV, arg);
|
testFunVV(t, "subVV_g symmetric", subVV_g, arg);
|
||||||
testFunVV(t, "subVV_s symmetric", subVV_s, arg);
|
testFunVV(t, "subVV_s symmetric", subVV_s, arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -162,26 +162,64 @@ func testFunVW(t *testing.T, msg string, f funVW, a argVW) {
|
|||||||
func TestFunVW(t *testing.T) {
|
func TestFunVW(t *testing.T) {
|
||||||
for _, a := range sumVW {
|
for _, a := range sumVW {
|
||||||
arg := a;
|
arg := a;
|
||||||
testFunVW(t, "addVW", addVW, arg);
|
testFunVW(t, "addVW_g", addVW_g, arg);
|
||||||
testFunVW(t, "addVW_s", addVW_s, arg);
|
testFunVW(t, "addVW_s", addVW_s, arg);
|
||||||
|
|
||||||
arg = argVW{a.x, a.z, a.y, a.c};
|
arg = argVW{a.x, a.z, a.y, a.c};
|
||||||
testFunVW(t, "subVW", subVW, arg);
|
testFunVW(t, "subVW_g", subVW_g, arg);
|
||||||
testFunVW(t, "subVW_s", subVW_s, arg);
|
testFunVW(t, "subVW_s", subVW_s, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, a := range prodVW {
|
|
||||||
arg := a;
|
|
||||||
testFunVW(t, "mulVW", mulVW, arg);
|
|
||||||
testFunVW(t, "mulVW_s", mulVW_s, arg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO(gri) Vector mul and div are not quite symmetric.
|
type funVWW func(z, x *Word, y, r Word, n int) (c Word)
|
||||||
// make it symmetric, mulVW should become mulAddVWW.
|
type argVWW struct { z, x []Word; y, r Word; c Word }
|
||||||
// Correct decision may become obvious after implementing
|
|
||||||
// the higher-level routines.
|
var prodVWW = []argVWW{
|
||||||
|
argVWW{},
|
||||||
|
argVWW{[]Word{0}, []Word{0}, 0, 0, 0},
|
||||||
|
argVWW{[]Word{991}, []Word{0}, 0, 991, 0},
|
||||||
|
argVWW{[]Word{0}, []Word{_M}, 0, 0, 0},
|
||||||
|
argVWW{[]Word{991}, []Word{_M}, 0, 991, 0},
|
||||||
|
argVWW{[]Word{0}, []Word{0}, _M, 0, 0},
|
||||||
|
argVWW{[]Word{991}, []Word{0}, _M, 991, 0},
|
||||||
|
argVWW{[]Word{1}, []Word{1}, 1, 0, 0},
|
||||||
|
argVWW{[]Word{992}, []Word{1}, 1, 991, 0},
|
||||||
|
argVWW{[]Word{22793}, []Word{991}, 23, 0, 0},
|
||||||
|
argVWW{[]Word{22800}, []Word{991}, 23, 7, 0},
|
||||||
|
argVWW{[]Word{0, 0, 0, 22793}, []Word{0, 0, 0, 991}, 23, 0, 0},
|
||||||
|
argVWW{[]Word{7, 0, 0, 22793}, []Word{0, 0, 0, 991}, 23, 7, 0},
|
||||||
|
argVWW{[]Word{0, 0, 0, 0}, []Word{7893475, 7395495, 798547395, 68943}, 0, 0, 0},
|
||||||
|
argVWW{[]Word{991, 0, 0, 0}, []Word{7893475, 7395495, 798547395, 68943}, 0, 991, 0},
|
||||||
|
argVWW{[]Word{0, 0, 0, 0}, []Word{0, 0, 0, 0}, 894375984, 0, 0},
|
||||||
|
argVWW{[]Word{991, 0, 0, 0}, []Word{0, 0, 0, 0}, 894375984, 991, 0},
|
||||||
|
argVWW{[]Word{_M<<1&_M}, []Word{_M}, 1<<1, 0, _M>>(_W-1)},
|
||||||
|
argVWW{[]Word{_M<<1&_M + 1}, []Word{_M}, 1<<1, 1, _M>>(_W-1)},
|
||||||
|
argVWW{[]Word{_M<<7&_M}, []Word{_M}, 1<<7, 0, _M>>(_W-7)},
|
||||||
|
argVWW{[]Word{_M<<7&_M + 1<<6}, []Word{_M}, 1<<7, 1<<6, _M>>(_W-7)},
|
||||||
|
argVWW{[]Word{_M<<7&_M, _M, _M, _M}, []Word{_M, _M, _M, _M}, 1<<7, 0, _M>>(_W-7)},
|
||||||
|
argVWW{[]Word{_M<<7&_M + 1<<6, _M, _M, _M}, []Word{_M, _M, _M, _M}, 1<<7, 1<<6, _M>>(_W-7)},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func testFunVWW(t *testing.T, msg string, f funVWW, a argVWW) {
|
||||||
|
n := len(a.z);
|
||||||
|
z := make([]Word, n);
|
||||||
|
c := f(addr(z), addr(a.x), a.y, a.r, n);
|
||||||
|
for i, zi := range z {
|
||||||
|
if zi != a.z[i] {
|
||||||
|
t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if c != a.c {
|
||||||
|
t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO(gri) mulAddVWW and divWVW are symmetric operations but
|
||||||
|
// their signature is not symmetric. Try to unify.
|
||||||
|
|
||||||
type funWVW func(z* Word, xn Word, x *Word, y Word, n int) (r Word)
|
type funWVW func(z* Word, xn Word, x *Word, y Word, n int) (r Word)
|
||||||
type argWVW struct { z []Word; xn Word; x []Word; y Word; r Word }
|
type argWVW struct { z []Word; xn Word; x []Word; y Word; r Word }
|
||||||
@ -203,10 +241,14 @@ func testFunWVW(t *testing.T, msg string, f funWVW, a argWVW) {
|
|||||||
|
|
||||||
|
|
||||||
func TestFunVWW(t *testing.T) {
|
func TestFunVWW(t *testing.T) {
|
||||||
for _, a := range prodVW {
|
for _, a := range prodVWW {
|
||||||
if a.y != 0 {
|
arg := a;
|
||||||
arg := argWVW{a.x, a.c, a.z, a.y, 0};
|
testFunVWW(t, "mulAddVWW_g", mulAddVWW_g, arg);
|
||||||
testFunWVW(t, "divWVW", divWVW, arg);
|
testFunVWW(t, "mulAddVWW_s", mulAddVWW_s, arg);
|
||||||
|
|
||||||
|
if a.y != 0 && a.r < a.y {
|
||||||
|
arg := argWVW{a.x, a.c, a.z, a.y, a.r};
|
||||||
|
testFunWVW(t, "divWVW_g", divWVW_g, arg);
|
||||||
testFunWVW(t, "divWVW_s", divWVW_s, arg);
|
testFunWVW(t, "divWVW_s", divWVW_s, arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,9 @@ package big
|
|||||||
// always normalized before returning the final result. The normalized
|
// always normalized before returning the final result. The normalized
|
||||||
// representation of 0 is the empty or nil slice (length = 0).
|
// representation of 0 is the empty or nil slice (length = 0).
|
||||||
|
|
||||||
|
// TODO(gri) - convert these routines into methods for type 'nat'
|
||||||
|
// - decide if type 'nat' should be exported
|
||||||
|
|
||||||
func normN(z []Word) []Word {
|
func normN(z []Word) []Word {
|
||||||
i := len(z);
|
i := len(z);
|
||||||
for i > 0 && z[i-1] == 0 {
|
for i > 0 && z[i-1] == 0 {
|
||||||
@ -45,7 +48,7 @@ func makeN(z []Word, m int) []Word {
|
|||||||
|
|
||||||
func newN(z []Word, x uint64) []Word {
|
func newN(z []Word, x uint64) []Word {
|
||||||
if x == 0 {
|
if x == 0 {
|
||||||
return nil; // len == 0
|
return makeN(z, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// single-digit values
|
// single-digit values
|
||||||
@ -95,6 +98,7 @@ func addNN(z, x, y []Word) []Word {
|
|||||||
// result is x
|
// result is x
|
||||||
return setN(z, x);
|
return setN(z, x);
|
||||||
}
|
}
|
||||||
|
// m > 0
|
||||||
|
|
||||||
z = makeN(z, m);
|
z = makeN(z, m);
|
||||||
c := addVV(&z[0], &x[0], &y[0], n);
|
c := addVV(&z[0], &x[0], &y[0], n);
|
||||||
@ -124,6 +128,7 @@ func subNN(z, x, y []Word) []Word {
|
|||||||
// result is x
|
// result is x
|
||||||
return setN(z, x);
|
return setN(z, x);
|
||||||
}
|
}
|
||||||
|
// m > 0
|
||||||
|
|
||||||
z = makeN(z, m);
|
z = makeN(z, m);
|
||||||
c := subVV(&z[0], &x[0], &y[0], n);
|
c := subVV(&z[0], &x[0], &y[0], n);
|
||||||
@ -133,8 +138,8 @@ func subNN(z, x, y []Word) []Word {
|
|||||||
if c != 0 {
|
if c != 0 {
|
||||||
panic("underflow");
|
panic("underflow");
|
||||||
}
|
}
|
||||||
|
|
||||||
z = normN(z);
|
z = normN(z);
|
||||||
|
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,27 +165,38 @@ func cmpNN(x, y []Word) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func mulNW(z, x []Word, y Word) []Word {
|
func mulAddNWW(z, x []Word, y, r Word) []Word {
|
||||||
m := len(x);
|
m := len(x);
|
||||||
switch {
|
if m == 0 || y == 0 {
|
||||||
case m == 0 || y == 0:
|
return newN(z, uint64(r)); // result is r
|
||||||
return setN(z, nil); // result is 0
|
|
||||||
case y == 1:
|
|
||||||
return setN(z, x); // result is x
|
|
||||||
}
|
}
|
||||||
// m > 0
|
// m > 0
|
||||||
z = makeN(z, m+1);
|
|
||||||
c := mulVW(&z[0], &x[0], y, m);
|
z = makeN(z, m);
|
||||||
|
c := mulAddVWW(&z[0], &x[0], y, r, m);
|
||||||
if c > 0 {
|
if c > 0 {
|
||||||
z = z[0 : m+1];
|
z = z[0 : m+1];
|
||||||
z[m] = c;
|
z[m] = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func mulNN(z, x, y []Word) []Word {
|
func mulNN(z, x, y []Word) []Word {
|
||||||
|
m := len(x);
|
||||||
|
n := len(y);
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case m < n:
|
||||||
|
return mulNN(z, x, y);
|
||||||
|
case m == 0 || n == 0:
|
||||||
|
return makeN(z, 0);
|
||||||
|
}
|
||||||
|
// m > 0 && n > 0 && m >= n
|
||||||
|
|
||||||
panic("mulNN unimplemented");
|
panic("mulNN unimplemented");
|
||||||
|
|
||||||
return z
|
return z
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,7 +290,7 @@ func scanN(z []Word, s string, base int) ([]Word, int, int) {
|
|||||||
for ; i < n; i++ {
|
for ; i < n; i++ {
|
||||||
d := hexValue(s[i]);
|
d := hexValue(s[i]);
|
||||||
if 0 <= d && d < base {
|
if 0 <= d && d < base {
|
||||||
panic("scanN needs mulAddVWW");
|
z = mulAddNWW(z, z, Word(base), Word(d));
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -73,5 +73,16 @@ func TestStringN(t *testing.T) {
|
|||||||
if s != a.s {
|
if s != a.s {
|
||||||
t.Errorf("stringN%+v\n\tgot s = %s; want %s", a, s, a.s);
|
t.Errorf("stringN%+v\n\tgot s = %s; want %s", a, s, a.s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
x, b, n := scanN(nil, a.s, a.b);
|
||||||
|
if cmpNN(x, a.x) != 0 {
|
||||||
|
t.Errorf("scanN%+v\n\tgot z = %v; want %v", a, x, a.x);
|
||||||
|
}
|
||||||
|
if b != a.b {
|
||||||
|
t.Errorf("scanN%+v\n\tgot b = %d; want %d", a, b, a.b);
|
||||||
|
}
|
||||||
|
if n != len(a.s) {
|
||||||
|
t.Errorf("scanN%+v\n\tgot n = %d; want %d", a, n, len(a.s));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,118 +6,118 @@
|
|||||||
|
|
||||||
package big
|
package big
|
||||||
|
|
||||||
// A Z represents a signed multi-precision integer.
|
// An Int represents a signed multi-precision integer.
|
||||||
// The zero value for a Z represents the value 0.
|
// The zero value for an Int represents the value 0.
|
||||||
type Z struct {
|
type Int struct {
|
||||||
neg bool; // sign
|
neg bool; // sign
|
||||||
m []Word; // mantissa
|
abs []Word; // absolute value of the integer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// NewZ sets z to x.
|
// New sets z to x.
|
||||||
func NewZ(z Z, x int64) Z {
|
func (z *Int) New(x int64) *Int {
|
||||||
z.neg = false;
|
z.neg = false;
|
||||||
if x < 0 {
|
if x < 0 {
|
||||||
z.neg = true;
|
z.neg = true;
|
||||||
x = -x;
|
x = -x;
|
||||||
}
|
}
|
||||||
z.m = newN(z.m, uint64(x));
|
z.abs = newN(z.abs, uint64(x));
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// SetZ sets z to x.
|
// Set sets z to x.
|
||||||
func SetZ(z, x Z) Z {
|
func (z *Int) Set(x *Int) *Int {
|
||||||
z.neg = x.neg;
|
z.neg = x.neg;
|
||||||
z.m = setN(z.m, x.m);
|
z.abs = setN(z.abs, x.abs);
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// AddZZ computes z = x+y.
|
// Add computes z = x+y.
|
||||||
func AddZZ(z, x, y Z) Z {
|
func (z *Int) Add(x, y *Int) *Int {
|
||||||
if x.neg == y.neg {
|
if x.neg == y.neg {
|
||||||
// x + y == x + y
|
// x + y == x + y
|
||||||
// (-x) + (-y) == -(x + y)
|
// (-x) + (-y) == -(x + y)
|
||||||
z.neg = x.neg;
|
z.neg = x.neg;
|
||||||
z.m = addNN(z.m, x.m, y.m);
|
z.abs = addNN(z.abs, x.abs, y.abs);
|
||||||
} else {
|
} else {
|
||||||
// x + (-y) == x - y == -(y - x)
|
// x + (-y) == x - y == -(y - x)
|
||||||
// (-x) + y == y - x == -(x - y)
|
// (-x) + y == y - x == -(x - y)
|
||||||
if cmpNN(x.m, y.m) >= 0 {
|
if cmpNN(x.abs, y.abs) >= 0 {
|
||||||
z.neg = x.neg;
|
z.neg = x.neg;
|
||||||
z.m = subNN(z.m, x.m, y.m);
|
z.abs = subNN(z.abs, x.abs, y.abs);
|
||||||
} else {
|
} else {
|
||||||
z.neg = !x.neg;
|
z.neg = !x.neg;
|
||||||
z.m = subNN(z.m, y.m, x.m);
|
z.abs = subNN(z.abs, y.abs, x.abs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(z.m) == 0 {
|
if len(z.abs) == 0 {
|
||||||
z.neg = false; // 0 has no sign
|
z.neg = false; // 0 has no sign
|
||||||
}
|
}
|
||||||
return z
|
return z
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// AddZZ computes z = x-y.
|
// Sub computes z = x-y.
|
||||||
func SubZZ(z, x, y Z) Z {
|
func (z *Int) Sub(x, y *Int) *Int {
|
||||||
if x.neg != y.neg {
|
if x.neg != y.neg {
|
||||||
// x - (-y) == x + y
|
// x - (-y) == x + y
|
||||||
// (-x) - y == -(x + y)
|
// (-x) - y == -(x + y)
|
||||||
z.neg = x.neg;
|
z.neg = x.neg;
|
||||||
z.m = addNN(z.m, x.m, y.m);
|
z.abs = addNN(z.abs, x.abs, y.abs);
|
||||||
} else {
|
} else {
|
||||||
// x - y == x - y == -(y - x)
|
// x - y == x - y == -(y - x)
|
||||||
// (-x) - (-y) == y - x == -(x - y)
|
// (-x) - (-y) == y - x == -(x - y)
|
||||||
if cmpNN(x.m, y.m) >= 0 {
|
if cmpNN(x.abs, y.abs) >= 0 {
|
||||||
z.neg = x.neg;
|
z.neg = x.neg;
|
||||||
z.m = subNN(z.m, x.m, y.m);
|
z.abs = subNN(z.abs, x.abs, y.abs);
|
||||||
} else {
|
} else {
|
||||||
z.neg = !x.neg;
|
z.neg = !x.neg;
|
||||||
z.m = subNN(z.m, y.m, x.m);
|
z.abs = subNN(z.abs, y.abs, x.abs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(z.m) == 0 {
|
if len(z.abs) == 0 {
|
||||||
z.neg = false; // 0 has no sign
|
z.neg = false; // 0 has no sign
|
||||||
}
|
}
|
||||||
return z
|
return z
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// MulZZ computes z = x*y.
|
// Mul computes z = x*y.
|
||||||
func MulZZ(z, x, y Z) Z {
|
func (z *Int) Mul(x, y *Int) *Int {
|
||||||
// x * y == x * y
|
// x * y == x * y
|
||||||
// x * (-y) == -(x * y)
|
// x * (-y) == -(x * y)
|
||||||
// (-x) * y == -(x * y)
|
// (-x) * y == -(x * y)
|
||||||
// (-x) * (-y) == x * y
|
// (-x) * (-y) == x * y
|
||||||
z.neg = x.neg != y.neg;
|
z.neg = x.neg != y.neg;
|
||||||
z.m = mulNN(z.m, x.m, y.m);
|
z.abs = mulNN(z.abs, x.abs, y.abs);
|
||||||
return z
|
return z
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// NegZ computes z = -x.
|
// Neg computes z = -x.
|
||||||
func NegZ(z, x Z) Z {
|
func (z *Int) Neg(x *Int) *Int {
|
||||||
z.neg = len(x.m) > 0 && !x.neg; // 0 has no sign
|
z.neg = len(x.abs) > 0 && !x.neg; // 0 has no sign
|
||||||
z.m = setN(z.m, x.m);
|
z.abs = setN(z.abs, x.abs);
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Cmp compares x and y. The result is an int value that is
|
// 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
|
// == 0 if x == y
|
||||||
// > 0 if x > y
|
// > 0 if x > y
|
||||||
//
|
//
|
||||||
func CmpZZ(x, y Z) (r int) {
|
func CmpInt(x, y *Int) (r int) {
|
||||||
// x cmp y == x cmp y
|
// x cmp y == x cmp y
|
||||||
// x cmp (-y) == x
|
// x cmp (-y) == x
|
||||||
// (-x) cmp y == y
|
// (-x) cmp y == y
|
||||||
// (-x) cmp (-y) == -(x cmp y)
|
// (-x) cmp (-y) == -(x cmp y)
|
||||||
switch {
|
switch {
|
||||||
case x.neg == y.neg:
|
case x.neg == y.neg:
|
||||||
r = cmpNN(x.m, y.m);
|
r = cmpNN(x.abs, y.abs);
|
||||||
if x.neg {
|
if x.neg {
|
||||||
r = -r;
|
r = -r;
|
||||||
}
|
}
|
||||||
@ -130,10 +130,10 @@ func CmpZZ(x, y Z) (r int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (x Z) String() string {
|
func (x *Int) String() string {
|
||||||
s := "";
|
s := "";
|
||||||
if x.neg {
|
if x.neg {
|
||||||
s = "-";
|
s = "-";
|
||||||
}
|
}
|
||||||
return s + stringN(x.m, 10);
|
return s + stringN(x.abs, 10);
|
||||||
}
|
}
|
||||||
|
@ -7,14 +7,14 @@ package big
|
|||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
|
|
||||||
func newZ(x int64) Z {
|
func newZ(x int64) *Int {
|
||||||
var z Z;
|
var z Int;
|
||||||
return NewZ(z, x);
|
return z.New(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type funZZ func(z, x, y Z) Z
|
type funZZ func(z, x, y *Int) *Int
|
||||||
type argZZ struct { z, x, y Z }
|
type argZZ struct { z, x, y *Int }
|
||||||
|
|
||||||
var sumZZ = []argZZ{
|
var sumZZ = []argZZ{
|
||||||
argZZ{newZ(0), newZ(0), newZ(0)},
|
argZZ{newZ(0), newZ(0), newZ(0)},
|
||||||
@ -28,9 +28,9 @@ var sumZZ = []argZZ{
|
|||||||
|
|
||||||
func TestSetZ(t *testing.T) {
|
func TestSetZ(t *testing.T) {
|
||||||
for _, a := range sumZZ {
|
for _, a := range sumZZ {
|
||||||
var z Z;
|
var z Int;
|
||||||
z = SetZ(z, a.z);
|
z.Set(a.z);
|
||||||
if CmpZZ(z, a.z) != 0 {
|
if CmpInt(&z, a.z) != 0 {
|
||||||
t.Errorf("got z = %v; want %v", z, a.z);
|
t.Errorf("got z = %v; want %v", z, a.z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -38,15 +38,17 @@ func TestSetZ(t *testing.T) {
|
|||||||
|
|
||||||
|
|
||||||
func testFunZZ(t *testing.T, msg string, f funZZ, a argZZ) {
|
func testFunZZ(t *testing.T, msg string, f funZZ, a argZZ) {
|
||||||
var z Z;
|
var z Int;
|
||||||
z = f(z, a.x, a.y);
|
f(&z, a.x, a.y);
|
||||||
if CmpZZ(z, a.z) != 0 {
|
if CmpInt(&z, a.z) != 0 {
|
||||||
t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, z, a.z);
|
t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, &z, a.z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func TestFunZZ(t *testing.T) {
|
func TestFunZZ(t *testing.T) {
|
||||||
|
AddZZ := func(z, x, y *Int) *Int { return z.Add(x, y) };
|
||||||
|
SubZZ := func(z, x, y *Int) *Int { return z.Sub(x, y) };
|
||||||
for _, a := range sumZZ {
|
for _, a := range sumZZ {
|
||||||
arg := a;
|
arg := a;
|
||||||
testFunZZ(t, "AddZZ", AddZZ, arg);
|
testFunZZ(t, "AddZZ", AddZZ, arg);
|
||||||
|
Loading…
Reference in New Issue
Block a user