gonum.org/v1/gonum@v0.14.0/internal/asm/f64/dot_test.go (about) 1 // Copyright ©2015 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 5 package f64_test 6 7 import ( 8 "fmt" 9 "math" 10 "testing" 11 12 "golang.org/x/exp/rand" 13 14 . "gonum.org/v1/gonum/internal/asm/f64" 15 ) 16 17 func TestDotUnitary(t *testing.T) { 18 for i, test := range []struct { 19 xData []float64 20 yData []float64 21 22 want float64 23 }{ 24 { 25 xData: []float64{2}, 26 yData: []float64{-3}, 27 want: -6, 28 }, 29 { 30 xData: []float64{2, 3}, 31 yData: []float64{-3, 4}, 32 want: 6, 33 }, 34 { 35 xData: []float64{2, 3, -4}, 36 yData: []float64{-3, 4, 5}, 37 want: -14, 38 }, 39 { 40 xData: []float64{2, 3, -4, -5}, 41 yData: []float64{-3, 4, 5, -6}, 42 want: 16, 43 }, 44 { 45 xData: []float64{0, 2, 3, -4, -5}, 46 yData: []float64{0, -3, 4, 5, -6}, 47 want: 16, 48 }, 49 { 50 xData: []float64{0, 0, 2, 3, -4, -5}, 51 yData: []float64{0, 1, -3, 4, 5, -6}, 52 want: 16, 53 }, 54 { 55 xData: []float64{0, 0, 1, 1, 2, -3, -4}, 56 yData: []float64{0, 1, 0, 3, -4, 5, -6}, 57 want: 4, 58 }, 59 { 60 xData: []float64{0, 0, 1, 1, 2, -3, -4, 5}, 61 yData: []float64{0, 1, 0, 3, -4, 5, -6, 7}, 62 want: 39, 63 }, 64 } { 65 const msgGuard = "test %v: out-of-bounds write to %v argument\nfront guard: %v\nback guard: %v" 66 67 x, xFront, xBack := newGuardedVector(test.xData, 1) 68 y, yFront, yBack := newGuardedVector(test.yData, 1) 69 got := DotUnitary(x, y) 70 71 if !allNaN(xFront) || !allNaN(xBack) { 72 t.Errorf(msgGuard, i, "x", xFront, xBack) 73 } 74 if !allNaN(yFront) || !allNaN(yBack) { 75 t.Errorf(msgGuard, i, "y", yFront, yBack) 76 } 77 if !equalStrided(test.xData, x, 1) { 78 t.Errorf("test %v: modified read-only x argument", i) 79 } 80 if !equalStrided(test.yData, y, 1) { 81 t.Errorf("test %v: modified read-only y argument", i) 82 } 83 if math.IsNaN(got) { 84 t.Errorf("test %v: invalid memory read", i) 85 continue 86 } 87 88 if got != test.want { 89 t.Errorf("test %v: unexpected result. want %v, got %v", i, test.want, got) 90 } 91 } 92 } 93 94 func TestDotInc(t *testing.T) { 95 for i, test := range []struct { 96 xData []float64 97 yData []float64 98 99 want float64 100 wantRev float64 // Result when one of the vectors is reversed. 101 }{ 102 { 103 xData: []float64{2}, 104 yData: []float64{-3}, 105 want: -6, 106 wantRev: -6, 107 }, 108 { 109 xData: []float64{2, 3}, 110 yData: []float64{-3, 4}, 111 want: 6, 112 wantRev: -1, 113 }, 114 { 115 xData: []float64{2, 3, -4}, 116 yData: []float64{-3, 4, 5}, 117 want: -14, 118 wantRev: 34, 119 }, 120 { 121 xData: []float64{2, 3, -4, -5}, 122 yData: []float64{-3, 4, 5, -6}, 123 want: 16, 124 wantRev: 2, 125 }, 126 { 127 xData: []float64{0, 2, 3, -4, -5}, 128 yData: []float64{0, -3, 4, 5, -6}, 129 want: 16, 130 wantRev: 34, 131 }, 132 { 133 xData: []float64{0, 0, 2, 3, -4, -5}, 134 yData: []float64{0, 1, -3, 4, 5, -6}, 135 want: 16, 136 wantRev: -5, 137 }, 138 { 139 xData: []float64{0, 0, 1, 1, 2, -3, -4}, 140 yData: []float64{0, 1, 0, 3, -4, 5, -6}, 141 want: 4, 142 wantRev: -4, 143 }, 144 { 145 xData: []float64{0, 0, 1, 1, 2, -3, -4, 5}, 146 yData: []float64{0, 1, 0, 3, -4, 5, -6, 7}, 147 want: 39, 148 wantRev: 3, 149 }, 150 } { 151 const msgGuard = "%v: out-of-bounds write to %v argument\nfront guard: %v\nback guard: %v" 152 153 for _, incX := range []int{-7, -3, -2, -1, 1, 2, 3, 7} { 154 for _, incY := range []int{-7, -3, -2, -1, 1, 2, 3, 7} { 155 n := len(test.xData) 156 x, xFront, xBack := newGuardedVector(test.xData, incX) 157 y, yFront, yBack := newGuardedVector(test.yData, incY) 158 159 var ix, iy int 160 if incX < 0 { 161 ix = (-n + 1) * incX 162 } 163 if incY < 0 { 164 iy = (-n + 1) * incY 165 } 166 got := DotInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) 167 168 prefix := fmt.Sprintf("test %v, incX = %v, incY = %v", i, incX, incY) 169 if !allNaN(xFront) || !allNaN(xBack) { 170 t.Errorf(msgGuard, prefix, "x", xFront, xBack) 171 } 172 if !allNaN(yFront) || !allNaN(yBack) { 173 t.Errorf(msgGuard, prefix, "y", yFront, yBack) 174 } 175 if nonStridedWrite(x, incX) || !equalStrided(test.xData, x, incX) { 176 t.Errorf("%v: modified read-only x argument", prefix) 177 } 178 if nonStridedWrite(y, incY) || !equalStrided(test.yData, y, incY) { 179 t.Errorf("%v: modified read-only y argument", prefix) 180 } 181 if math.IsNaN(got) { 182 t.Errorf("%v: invalid memory read", prefix) 183 continue 184 } 185 186 want := test.want 187 if incX*incY < 0 { 188 want = test.wantRev 189 } 190 if got != want { 191 t.Errorf("%v: unexpected result. want %v, got %v", prefix, want, got) 192 } 193 } 194 } 195 } 196 } 197 198 func BenchmarkDotUnitaryN1(b *testing.B) { dotUnitaryBenchmark(b, 1) } 199 func BenchmarkDotUnitaryN2(b *testing.B) { dotUnitaryBenchmark(b, 2) } 200 func BenchmarkDotUnitaryN3(b *testing.B) { dotUnitaryBenchmark(b, 3) } 201 func BenchmarkDotUnitaryN4(b *testing.B) { dotUnitaryBenchmark(b, 4) } 202 func BenchmarkDotUnitaryN10(b *testing.B) { dotUnitaryBenchmark(b, 10) } 203 func BenchmarkDotUnitaryN100(b *testing.B) { dotUnitaryBenchmark(b, 100) } 204 func BenchmarkDotUnitaryN1000(b *testing.B) { dotUnitaryBenchmark(b, 1000) } 205 func BenchmarkDotUnitaryN10000(b *testing.B) { dotUnitaryBenchmark(b, 10000) } 206 func BenchmarkDotUnitaryN100000(b *testing.B) { dotUnitaryBenchmark(b, 100000) } 207 208 var r float64 209 210 func dotUnitaryBenchmark(b *testing.B, n int) { 211 x := make([]float64, n) 212 for i := range x { 213 x[i] = rand.Float64() 214 } 215 y := make([]float64, n) 216 for i := range y { 217 y[i] = rand.Float64() 218 } 219 b.ResetTimer() 220 for i := 0; i < b.N; i++ { 221 r = DotUnitary(x, y) 222 } 223 } 224 225 func BenchmarkDotIncN1Inc1(b *testing.B) { dotIncBenchmark(b, 1, 1) } 226 227 func BenchmarkDotIncN2Inc1(b *testing.B) { dotIncBenchmark(b, 2, 1) } 228 func BenchmarkDotIncN2Inc2(b *testing.B) { dotIncBenchmark(b, 2, 2) } 229 func BenchmarkDotIncN2Inc4(b *testing.B) { dotIncBenchmark(b, 2, 4) } 230 func BenchmarkDotIncN2Inc10(b *testing.B) { dotIncBenchmark(b, 2, 10) } 231 232 func BenchmarkDotIncN3Inc1(b *testing.B) { dotIncBenchmark(b, 3, 1) } 233 func BenchmarkDotIncN3Inc2(b *testing.B) { dotIncBenchmark(b, 3, 2) } 234 func BenchmarkDotIncN3Inc4(b *testing.B) { dotIncBenchmark(b, 3, 4) } 235 func BenchmarkDotIncN3Inc10(b *testing.B) { dotIncBenchmark(b, 3, 10) } 236 237 func BenchmarkDotIncN4Inc1(b *testing.B) { dotIncBenchmark(b, 4, 1) } 238 func BenchmarkDotIncN4Inc2(b *testing.B) { dotIncBenchmark(b, 4, 2) } 239 func BenchmarkDotIncN4Inc4(b *testing.B) { dotIncBenchmark(b, 4, 4) } 240 func BenchmarkDotIncN4Inc10(b *testing.B) { dotIncBenchmark(b, 4, 10) } 241 242 func BenchmarkDotIncN10Inc1(b *testing.B) { dotIncBenchmark(b, 10, 1) } 243 func BenchmarkDotIncN10Inc2(b *testing.B) { dotIncBenchmark(b, 10, 2) } 244 func BenchmarkDotIncN10Inc4(b *testing.B) { dotIncBenchmark(b, 10, 4) } 245 func BenchmarkDotIncN10Inc10(b *testing.B) { dotIncBenchmark(b, 10, 10) } 246 247 func BenchmarkDotIncN1000Inc1(b *testing.B) { dotIncBenchmark(b, 1000, 1) } 248 func BenchmarkDotIncN1000Inc2(b *testing.B) { dotIncBenchmark(b, 1000, 2) } 249 func BenchmarkDotIncN1000Inc4(b *testing.B) { dotIncBenchmark(b, 1000, 4) } 250 func BenchmarkDotIncN1000Inc10(b *testing.B) { dotIncBenchmark(b, 1000, 10) } 251 252 func BenchmarkDotIncN100000Inc1(b *testing.B) { dotIncBenchmark(b, 100000, 1) } 253 func BenchmarkDotIncN100000Inc2(b *testing.B) { dotIncBenchmark(b, 100000, 2) } 254 func BenchmarkDotIncN100000Inc4(b *testing.B) { dotIncBenchmark(b, 100000, 4) } 255 func BenchmarkDotIncN100000Inc10(b *testing.B) { dotIncBenchmark(b, 100000, 10) } 256 257 func BenchmarkDotIncN100000IncM1(b *testing.B) { dotIncBenchmark(b, 100000, -1) } 258 func BenchmarkDotIncN100000IncM2(b *testing.B) { dotIncBenchmark(b, 100000, -2) } 259 func BenchmarkDotIncN100000IncM4(b *testing.B) { dotIncBenchmark(b, 100000, -4) } 260 func BenchmarkDotIncN100000IncM10(b *testing.B) { dotIncBenchmark(b, 100000, -10) } 261 262 func dotIncBenchmark(b *testing.B, n, inc int) { 263 absInc := inc 264 if inc < 0 { 265 absInc = -inc 266 } 267 x := make([]float64, (n-1)*absInc+1) 268 for i := range x { 269 x[i] = rand.Float64() 270 } 271 y := make([]float64, (n-1)*absInc+1) 272 for i := range y { 273 y[i] = rand.Float64() 274 } 275 var ini int 276 if inc < 0 { 277 ini = (-n + 1) * inc 278 } 279 b.ResetTimer() 280 for i := 0; i < b.N; i++ { 281 r = DotInc(x, y, uintptr(n), uintptr(inc), uintptr(inc), uintptr(ini), uintptr(ini)) 282 } 283 }