1// Copyright ©2017 The Gonum Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package f64_test
6
7import (
8	"fmt"
9	"testing"
10
11	. "gonum.org/v1/gonum/internal/asm/f64"
12)
13
14const testLen = 1e5
15
16var (
17	a = 2.0
18	x = make([]float64, testLen)
19	y = make([]float64, testLen)
20	z = make([]float64, testLen)
21)
22
23func init() {
24	for n := range x {
25		x[n] = float64(n)
26		y[n] = float64(n)
27	}
28}
29
30func BenchmarkAxpyUnitary(t *testing.B) {
31	naiveaxpyu := func(a float64, x, y []float64) {
32		for i, v := range x {
33			y[i] += a * v
34		}
35	}
36	tests := []struct {
37		name string
38		f    func(a float64, x, y []float64)
39	}{
40		{"AxpyUnitary", AxpyUnitary},
41		{"NaiveAxpyUnitary", naiveaxpyu},
42	}
43	for _, test := range tests {
44		for _, ln := range []uintptr{1, 3, 10, 30, 1e2, 3e2, 1e3, 3e3, 1e4, 3e4, 1e5} {
45			t.Run(fmt.Sprintf("%s-%d", test.name, ln), func(b *testing.B) {
46				b.SetBytes(int64(64 * ln))
47				x, y := x[:ln], y[:ln]
48				b.ResetTimer()
49				for i := 0; i < b.N; i++ {
50					test.f(a, x, y)
51				}
52			})
53		}
54	}
55}
56
57func BenchmarkAxpyUnitaryTo(t *testing.B) {
58	naiveaxpyut := func(d []float64, a float64, x, y []float64) {
59		for i, v := range x {
60			d[i] = y[i] + a*v
61		}
62	}
63	tests := []struct {
64		name string
65		f    func(z []float64, a float64, x, y []float64)
66	}{
67		{"AxpyUnitaryTo", AxpyUnitaryTo},
68		{"NaiveAxpyUnitaryTo", naiveaxpyut},
69	}
70	for _, test := range tests {
71		for _, ln := range []uintptr{1, 3, 10, 30, 1e2, 3e2, 1e3, 3e3, 1e4, 3e4, 1e5} {
72			t.Run(fmt.Sprintf("%s-%d", test.name, ln), func(b *testing.B) {
73				b.SetBytes(int64(64 * ln))
74				x, y, z := x[:ln], y[:ln], z[:ln]
75				b.ResetTimer()
76				for i := 0; i < b.N; i++ {
77					test.f(z, a, x, y)
78				}
79			})
80		}
81	}
82}
83
84var incsAxpy = []struct {
85	len uintptr
86	inc []int
87}{
88	{1, []int{1}},
89	{2, []int{1, 2, 4, 10}},
90	{3, []int{1, 2, 4, 10}},
91	{4, []int{1, 2, 4, 10}},
92	{5, []int{1, 2, 4, 10}},
93	{10, []int{1, 2, 4, 10}},
94	{500, []int{1, 2, 4, 10}},
95	{1e3, []int{1, 2, 4, 10}},
96	{1e4, []int{1, 2, 4, 10, -1, -2, -4, -10}},
97}
98
99func BenchmarkAxpyInc(t *testing.B) {
100	naiveaxpyinc := func(alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) {
101		for i := 0; i < int(n); i++ {
102			y[iy] += alpha * x[ix]
103			ix += incX
104			iy += incY
105		}
106	}
107	tests := []struct {
108		name string
109		f    func(alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr)
110	}{
111		{"AxpyInc", AxpyInc},
112		{"NaiveAxpyInc", naiveaxpyinc},
113	}
114	for _, test := range tests {
115		for _, tt := range incsAxpy {
116			for _, inc := range tt.inc {
117				t.Run(fmt.Sprintf("%s-%d-inc(%d)", test.name, tt.len, inc), func(b *testing.B) {
118					b.SetBytes(int64(64 * tt.len))
119					var idx, tstInc uintptr = 0, uintptr(inc)
120					if inc < 0 {
121						idx = uintptr((-int(tt.len) + 1) * inc)
122					}
123					for i := 0; i < b.N; i++ {
124						test.f(a, x, y, uintptr(tt.len), tstInc, tstInc, idx, idx)
125					}
126				})
127			}
128		}
129	}
130}
131
132func BenchmarkAxpyIncTo(t *testing.B) {
133	naiveaxpyincto := func(dst []float64, incDst, idst uintptr, alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) {
134		for i := 0; i < int(n); i++ {
135			dst[idst] = alpha*x[ix] + y[iy]
136			ix += incX
137			iy += incY
138			idst += incDst
139		}
140	}
141	tests := []struct {
142		name string
143		f    func(dst []float64, incDst, idst uintptr, alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr)
144	}{
145		{"AxpyIncTo", AxpyIncTo},
146		{"NaiveAxpyIncTo", naiveaxpyincto},
147	}
148	for _, test := range tests {
149		for _, tt := range incsAxpy {
150			for _, inc := range tt.inc {
151				t.Run(fmt.Sprintf("%s-%d-inc(%d)", test.name, tt.len, inc), func(b *testing.B) {
152					b.SetBytes(int64(64 * tt.len))
153					var idx, tstInc uintptr = 0, uintptr(inc)
154					if inc < 0 {
155						idx = uintptr((-int(tt.len) + 1) * inc)
156					}
157					for i := 0; i < b.N; i++ {
158						test.f(z, tstInc, idx, a, x, y, uintptr(tt.len),
159							tstInc, tstInc, idx, idx)
160					}
161				})
162			}
163		}
164	}
165}
166