Skip to content

Commit

Permalink
Merge pull request #208 from gonum/c64/dot
Browse files Browse the repository at this point in the history
asm/c64:  Adding dot product asm functions.
  • Loading branch information
Kunde21 committed Sep 13, 2017
2 parents 00ece78 + 9523cc3 commit 7acac0b
Show file tree
Hide file tree
Showing 12 changed files with 1,156 additions and 138 deletions.
59 changes: 59 additions & 0 deletions internal/asm/c64/benchDot_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright ©2017 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build go1.7

package c64

import (
"fmt"
"testing"
)

var benchSink complex64

func BenchmarkDotUnitary(t *testing.B) {
for _, tst := range []struct {
name string
f func(x, y []complex64) complex64
}{
{"DotcUnitary", DotcUnitary},
{"DotuUnitary", DotuUnitary},
} {
for _, v := range []int64{1, 2, 3, 4, 5, 10, 100, 1e3, 5e3, 1e4, 5e4} {
t.Run(fmt.Sprintf("%s-%d", tst.name, v), func(b *testing.B) {
x, y := x[:v], y[:v]
b.SetBytes(128 * v)
for i := 0; i < b.N; i++ {
benchSink = tst.f(x, y)
}
})
}
}
}

func BenchmarkDotInc(t *testing.B) {
for _, tst := range []struct {
name string
f func(x, y []complex64, n, incX, incY, ix, iy uintptr) complex64
}{
{"DotcInc", DotcInc},
{"DotuInc", DotuInc},
} {
for _, ln := range []int{1, 2, 3, 4, 5, 10, 100, 1e3, 5e3, 1e4, 5e4} {
for _, inc := range []int{1, 2, 4, 10, -1, -2, -4, -10} {
t.Run(fmt.Sprintf("%s-%d-inc%d", tst.name, ln, inc), func(b *testing.B) {
b.SetBytes(int64(128 * ln))
var idx int
if inc < 0 {
idx = (-ln + 1) * inc
}
for i := 0; i < b.N; i++ {
benchSink = tst.f(x, y, uintptr(ln), uintptr(inc), uintptr(inc), uintptr(idx), uintptr(idx))
}
})
}
}
}
}
178 changes: 178 additions & 0 deletions internal/asm/c64/dot_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
// Copyright ©2017 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package c64

import (
"fmt"
"math"
"testing"
)

const (
msgVal = "%v: unexpected value at %v Got: %v Expected: %v"
msgGuard = "%v: Guard violated in %s vector %v %v"
)

var (
inf = float32(math.Inf(1))
)

var dotTests = []struct {
x, y []complex64
wantu, wantc complex64
wantuRev, wantcRev complex64
n int
}{
{
x: []complex64{},
y: []complex64{},
n: 0,
wantu: 0, wantc: 0,
wantuRev: 0, wantcRev: 0,
},
{
x: []complex64{1 + 1i},
y: []complex64{1 + 1i},
n: 1,
wantu: 0 + 2i, wantc: 2,
wantuRev: 0 + 2i, wantcRev: 2,
},
{
x: []complex64{1 + 2i},
y: []complex64{1 + 1i},
n: 1,
wantu: -1 + 3i, wantc: 3 - 1i,
wantuRev: -1 + 3i, wantcRev: 3 - 1i,
},
{
x: []complex64{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i},
y: []complex64{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i},
n: 10,
wantu: -210 + 2860i, wantc: 2870 + 0i,
wantuRev: -210 + 1540i, wantcRev: 1550 + 0i,
},
{
x: []complex64{1 + 1i, 1 + 1i, 1 + 2i, 1 + 1i, 1 + 1i, 1 + 1i, 1 + 3i, 1 + 1i, 1 + 1i, 1 + 4i},
y: []complex64{1 + 2i, 1 + 2i, 1 + 2i, 1 + 2i, 1 + 2i, 1 + 2i, 1 + 2i, 1 + 2i, 1 + 2i, 1 + 2i},
n: 10,
wantu: -22 + 36i, wantc: 42 + 4i,
wantuRev: -22 + 36i, wantcRev: 42 + 4i,
},
{
x: []complex64{1 + 1i, 1 + 1i, 2 + 1i, 1 + 1i, 1 + 1i, 1 + 1i, 1 + 1i, 1 + 1i, 1 + 1i, 2 + 1i},
y: []complex64{1 + 2i, 1 + 2i, 1 + 3i, 1 + 2i, 1 + 3i, 1 + 2i, 1 + 2i, 1 + 2i, 1 + 2i, 1 + 2i},
n: 10,
wantu: -10 + 37i, wantc: 34 + 17i,
wantuRev: -10 + 36i, wantcRev: 34 + 16i,
},
{
x: []complex64{1 + 1i, 1 + 1i, 1 + 1i, 1 + 1i, complex(inf, 1), 1 + 1i, 1 + 1i, 1 + 1i, 1 + 1i, 1 + 1i},
y: []complex64{1 + 2i, 1 + 2i, 1 + 2i, 1 + 2i, 1 + 2i, 1 + 2i, 1 + 2i, 1 + 2i, 1 + 2i, 1 + 2i},
n: 10,
wantu: complex(inf, inf), wantc: complex(inf, inf),
wantuRev: complex(inf, inf), wantcRev: complex(inf, inf),
},
}

func TestDotcUnitary(t *testing.T) {
const gd = 1 + 5i
for i, test := range dotTests {
for _, align := range align2 {
prefix := fmt.Sprintf("Test %v (x:%v y:%v)", i, align.x, align.y)
xgLn, ygLn := 4+align.x, 4+align.y
xg, yg := guardVector(test.x, gd, xgLn), guardVector(test.y, gd, ygLn)
x, y := xg[xgLn:len(xg)-xgLn], yg[ygLn:len(yg)-ygLn]
res := DotcUnitary(x, y)
if !same(res, test.wantc) {
t.Errorf(msgVal, prefix, i, res, test.wantc)
}
if !isValidGuard(xg, gd, xgLn) {
t.Errorf(msgGuard, prefix, "x", xg[:xgLn], xg[len(xg)-xgLn:])
}
if !isValidGuard(yg, gd, ygLn) {
t.Errorf(msgGuard, prefix, "y", yg[:ygLn], yg[len(yg)-ygLn:])
}
}
}
}

func TestDotcInc(t *testing.T) {
const gd, gdLn = 2 + 5i, 4
for i, test := range dotTests {
for _, inc := range newIncSet(1, 2, 5, 10, -1, -2, -5, -10) {
xg, yg := guardIncVector(test.x, gd, inc.x, gdLn), guardIncVector(test.y, gd, inc.y, gdLn)
x, y := xg[gdLn:len(xg)-gdLn], yg[gdLn:len(yg)-gdLn]
want := test.wantc
var ix, iy int
if inc.x < 0 {
ix, want = -inc.x*(test.n-1), test.wantcRev
}
if inc.y < 0 {
iy, want = -inc.y*(test.n-1), test.wantcRev
}
prefix := fmt.Sprintf("Test %v (x:%v y:%v) (ix:%v iy:%v)", i, inc.x, inc.y, ix, iy)
res := DotcInc(x, y, uintptr(test.n), uintptr(inc.x), uintptr(inc.y), uintptr(ix), uintptr(iy))
if inc.x*inc.y > 0 {
want = test.wantc
}
if !same(res, want) {
t.Errorf(msgVal, prefix, i, res, want)
t.Error(x, y)
}
checkValidIncGuard(t, xg, gd, inc.x, gdLn)
checkValidIncGuard(t, yg, gd, inc.y, gdLn)
}
}
}

func TestDotuUnitary(t *testing.T) {
const gd = 1 + 5i
for i, test := range dotTests {
for _, align := range align2 {
prefix := fmt.Sprintf("Test %v (x:%v y:%v)", i, align.x, align.y)
xgLn, ygLn := 4+align.x, 4+align.y
xg, yg := guardVector(test.x, gd, xgLn), guardVector(test.y, gd, ygLn)
x, y := xg[xgLn:len(xg)-xgLn], yg[ygLn:len(yg)-ygLn]
res := DotuUnitary(x, y)
if !same(res, test.wantu) {
t.Errorf(msgVal, prefix, i, res, test.wantu)
}
if !isValidGuard(xg, gd, xgLn) {
t.Errorf(msgGuard, prefix, "x", xg[:xgLn], xg[len(xg)-xgLn:])
}
if !isValidGuard(yg, gd, ygLn) {
t.Errorf(msgGuard, prefix, "y", yg[:ygLn], yg[len(yg)-ygLn:])
}
}
}
}

func TestDotuInc(t *testing.T) {
const gd, gdLn = 1 + 5i, 4
for i, test := range dotTests {
for _, inc := range newIncSet(1, 2, 5, 10, -1, -2, -5, -10) {
prefix := fmt.Sprintf("Test %v (x:%v y:%v)", i, inc.x, inc.y)
xg, yg := guardIncVector(test.x, gd, inc.x, gdLn), guardIncVector(test.y, gd, inc.y, gdLn)
x, y := xg[gdLn:len(xg)-gdLn], yg[gdLn:len(yg)-gdLn]
want := test.wantc
var ix, iy int
if inc.x < 0 {
ix, want = -inc.x*(test.n-1), test.wantuRev
}
if inc.y < 0 {
iy, want = -inc.y*(test.n-1), test.wantuRev
}
res := DotuInc(x, y, uintptr(test.n), uintptr(inc.x), uintptr(inc.y), uintptr(ix), uintptr(iy))
if inc.x*inc.y > 0 {
want = test.wantu
}
if !same(res, want) {
t.Errorf(msgVal, prefix, i, res, want)
}
checkValidIncGuard(t, xg, gd, inc.x, gdLn)
checkValidIncGuard(t, yg, gd, inc.y, gdLn)
}
}
}
33 changes: 0 additions & 33 deletions internal/asm/c64/dotc.go

This file was deleted.

0 comments on commit 7acac0b

Please sign in to comment.