github.com/gopherd/gonum@v0.0.4/internal/asm/f64/ge_test.go (about) 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 5 package f64_test 6 7 import ( 8 "fmt" 9 "testing" 10 11 . "github.com/gopherd/gonum/internal/asm/f64" 12 ) 13 14 var gerTests = []struct { 15 x, y, a []float64 16 want []float64 17 }{ // m x n ( kernels executed ) 18 { // 1 x 1 (1x1) 19 x: []float64{2}, 20 y: []float64{4.4}, 21 a: []float64{10}, 22 want: []float64{18.8}, 23 }, 24 { // 3 x 2 ( 2x2, 1x2 ) 25 x: []float64{-2, -3, 0}, 26 y: []float64{-1.1, 5}, 27 a: []float64{ 28 1.3, 2.4, 29 2.6, 2.8, 30 -1.3, -4.3, 31 }, 32 want: []float64{3.5, -7.6, 5.9, -12.2, -1.3, -4.3}, 33 }, 34 { // 3 x 3 ( 2x2, 2x1, 1x2, 1x1 ) 35 x: []float64{-2, 7, 12}, 36 y: []float64{-1.1, 0, 6}, 37 a: []float64{ 38 1.3, 2.4, 3.5, 39 2.6, 2.8, 3.3, 40 -1.3, -4.3, -9.7, 41 }, 42 want: []float64{3.5, 2.4, -8.5, -5.1, 2.8, 45.3, -14.5, -4.3, 62.3}, 43 }, 44 { // 5 x 3 ( 4x2, 4x1, 1x2, 1x1 ) 45 x: []float64{-2, -3, 0, 1, 2}, 46 y: []float64{-1.1, 5, 0}, 47 a: []float64{ 48 1.3, 2.4, 3.5, 49 2.6, 2.8, 3.3, 50 -1.3, -4.3, -9.7, 51 8, 9, -10, 52 -12, -14, -6, 53 }, 54 want: []float64{3.5, -7.6, 3.5, 5.9, -12.2, 3.3, -1.3, -4.3, -9.7, 6.9, 14, -10, -14.2, -4, -6}, 55 }, 56 { // 3 x 6 ( 2x4, 2x2, 1x4, 1x2 ) 57 x: []float64{-2, -3, 0}, 58 y: []float64{-1.1, 5, 0, 9, 19, 22}, 59 a: []float64{ 60 1.3, 2.4, 3.5, 4.8, 1.11, -9, 61 2.6, 2.8, 3.3, -3.4, 6.2, -8.7, 62 -1.3, -4.3, -9.7, -3.1, 8.9, 8.9, 63 }, 64 want: []float64{3.5, -7.6, 3.5, -13.2, -36.89, -53, 5.9, -12.2, 3.3, -30.4, -50.8, -74.7, -1.3, -4.3, -9.7, -3.1, 8.9, 8.9}, 65 }, 66 { // 5 x 5 ( 4x4, 4x1, 1x4, 1x1) 67 x: []float64{-2, 0, 2, 0, 7}, 68 y: []float64{-1.1, 8, 7, 3, 5}, 69 a: []float64{ 70 1.3, 2.4, 3.5, 2.2, 8.3, 71 2.6, 2.8, 3.3, 4.4, -1.5, 72 -1.3, -4.3, -9.7, -8.8, 6.2, 73 8, 9, -10, -11, 12, 74 -12, -14, -6, -2, 4, 75 }, 76 want: []float64{ 77 3.5, -13.6, -10.5, -3.8, -1.7, 78 2.6, 2.8, 3.3, 4.4, -1.5, 79 -3.5, 11.7, 4.3, -2.8, 16.2, 80 8, 9, -10, -11, 12, 81 -19.700000000000003, 42, 43, 19, 39, 82 }, 83 }, 84 { // 7 x 7 ( 4x4, 4x2, 4x1, 2x4, 2x2, 2x1, 1x4, 1x2, 1x1 ) < nan test > 85 x: []float64{-2, 8, 9, -3, -1.2, 5, 4.5}, 86 y: []float64{-1.1, nan, 19, 11, -9.22, 7, 3.3}, 87 a: []float64{ 88 1.3, 2.4, 3.5, 4.8, 1.11, -9, 2.2, 89 2.6, 2.8, 3.3, -3.4, 6.2, -8.7, 5.1, 90 -1.3, -4.3, -9.7, -3.1, 8.9, 8.9, 8, 91 5, -2.5, 1.8, -3.6, 2.8, 4.9, 7, 92 -1.3, -4.3, -9.7, -3.1, 8.9, 8.9, 8, 93 2.6, 2.8, 3.3, -3.4, 6.2, -8.7, 5.1, 94 1.3, 2.4, 3.5, 4.8, 1.11, -9, 2.2, 95 }, 96 want: []float64{ 97 3.5, nan, -34.5, -17.2, 19.55, -23, -4.4, 98 -6.2, nan, 155.3, 84.6, -67.56, 47.3, 31.5, 99 -11.2, nan, 161.3, 95.9, -74.08, 71.9, 37.7, 100 8.3, nan, -55.2, -36.6, 30.46, -16.1, -2.9, 101 0.02, nan, -32.5, -16.3, 19.964, 0.5, 4.04, 102 -2.9, nan, 98.3, 51.6, -39.9, 26.3, 21.6, 103 -3.65, nan, 89, 54.3, -40.38, 22.5, 17.05, 104 }, 105 }, 106 } 107 108 func TestGer(t *testing.T) { 109 const ( 110 tol = 1e-15 111 112 xGdVal, yGdVal, aGdVal = -0.5, 1.5, 10 113 gdLn = 4 114 ) 115 for i, test := range gerTests { 116 m, n := len(test.x), len(test.y) 117 for _, align := range align2 { 118 prefix := fmt.Sprintf("Test %v (%vx%v) align(x:%v,y:%v,a:%v)", 119 i, m, n, align.x, align.y, align.x^align.y) 120 xgLn, ygLn, agLn := gdLn+align.x, gdLn+align.y, gdLn+align.x^align.y 121 xg, yg := guardVector(test.x, xGdVal, xgLn), guardVector(test.y, yGdVal, ygLn) 122 x, y := xg[xgLn:len(xg)-xgLn], yg[ygLn:len(yg)-ygLn] 123 ag := guardVector(test.a, aGdVal, agLn) 124 a := ag[agLn : len(ag)-agLn] 125 126 alpha := 1.0 127 Ger(uintptr(m), uintptr(n), alpha, x, 1, y, 1, a, uintptr(n)) 128 for i := range test.want { 129 if !sameApprox(a[i], test.want[i], tol) { 130 t.Errorf(msgVal, prefix, i, a[i], test.want[i]) 131 t.Error(a) 132 return 133 } 134 } 135 if !isValidGuard(xg, xGdVal, xgLn) { 136 t.Errorf(msgGuard, prefix, "x", xg[:xgLn], xg[len(xg)-xgLn:]) 137 } 138 if !isValidGuard(yg, yGdVal, ygLn) { 139 t.Errorf(msgGuard, prefix, "y", yg[:ygLn], yg[len(yg)-ygLn:]) 140 } 141 if !isValidGuard(ag, aGdVal, agLn) { 142 t.Errorf(msgGuard, prefix, "a", ag[:agLn], ag[len(ag)-agLn:]) 143 } 144 if !equalStrided(test.x, x, 1) { 145 t.Errorf(msgReadOnly, prefix, "x") 146 } 147 if !equalStrided(test.y, y, 1) { 148 t.Errorf(msgReadOnly, prefix, "y") 149 } 150 } 151 152 for _, inc := range newIncSet(1, 2) { 153 prefix := fmt.Sprintf("Test %v (%vx%v) inc(x:%v,y:%v)", i, m, n, inc.x, inc.y) 154 xg := guardIncVector(test.x, xGdVal, inc.x, gdLn) 155 yg := guardIncVector(test.y, yGdVal, inc.y, gdLn) 156 x, y := xg[gdLn:len(xg)-gdLn], yg[gdLn:len(yg)-gdLn] 157 ag := guardVector(test.a, aGdVal, gdLn) 158 a := ag[gdLn : len(ag)-gdLn] 159 160 alpha := 3.5 161 Ger(uintptr(m), uintptr(n), alpha, x, uintptr(inc.x), y, uintptr(inc.y), a, uintptr(n)) 162 for i := range test.want { 163 want := alpha*(test.want[i]-test.a[i]) + test.a[i] 164 if !sameApprox(a[i], want, tol) { 165 t.Errorf(msgVal, prefix, i, a[i], want) 166 } 167 } 168 checkValidIncGuard(t, xg, xGdVal, inc.x, gdLn) 169 checkValidIncGuard(t, yg, yGdVal, inc.y, gdLn) 170 if !isValidGuard(ag, aGdVal, gdLn) { 171 t.Errorf(msgGuard, prefix, "a", ag[:gdLn], ag[len(ag)-gdLn:]) 172 } 173 if !equalStrided(test.x, x, inc.x) { 174 t.Errorf(msgReadOnly, prefix, "x") 175 } 176 if !equalStrided(test.y, y, inc.y) { 177 t.Errorf(msgReadOnly, prefix, "y") 178 } 179 } 180 } 181 } 182 183 func BenchmarkGer(t *testing.B) { 184 const alpha = 3 185 for _, dims := range newIncSet(3, 10, 30, 100, 300, 1e3, 3e3, 1e4) { 186 m, n := dims.x, dims.y 187 if m/n >= 100 || n/m >= 100 { 188 continue 189 } 190 for _, inc := range newIncSet(1, 3, 4, 10) { 191 t.Run(fmt.Sprintf("Dger %dx%d (%d %d)", m, n, inc.x, inc.y), func(b *testing.B) { 192 x, y, a := gerData(m, n, inc.x, inc.y) 193 b.ResetTimer() 194 for i := 0; i < b.N; i++ { 195 Ger(uintptr(m), uintptr(n), alpha, x, uintptr(inc.x), y, uintptr(inc.y), a, uintptr(n)) 196 } 197 }) 198 199 } 200 } 201 } 202 203 func gerData(m, n, incX, incY int) (x, y, a []float64) { 204 x = make([]float64, m*incX) 205 y = make([]float64, n*incY) 206 a = make([]float64, m*n) 207 ln := len(x) 208 if len(y) > ln { 209 ln = len(y) 210 } 211 if len(a) > ln { 212 ln = len(a) 213 } 214 for i := 0; i < ln; i++ { 215 v := float64(i) 216 if i < len(a) { 217 a[i] = v 218 } 219 if i < len(x) { 220 x[i] = v 221 } 222 if i < len(y) { 223 y[i] = v 224 } 225 } 226 return x, y, a 227 }