gonum.org/v1/gonum@v0.14.0/internal/asm/f32/util_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 f32_test 6 7 import ( 8 "math" 9 "testing" 10 11 "gonum.org/v1/gonum/floats/scalar" 12 ) 13 14 const ( 15 msgRes = "%v: unexpected result Got: %v Expected: %v" 16 msgVal = "%v: unexpected value at %v Got: %v Expected: %v" 17 msgGuard = "%v: guard violated in %s vector %v %v" 18 msgReadOnly = "%v: modified read-only %v argument" 19 ) 20 21 var ( 22 nan = float32(math.NaN()) 23 inf = float32(math.Inf(1)) 24 ) 25 26 // sameApprox tests for nan-aware equality within tolerance. 27 func sameApprox(x, y, tol float32) bool { 28 a, b := float64(x), float64(y) 29 return same(x, y) || scalar.EqualWithinAbsOrRel(a, b, float64(tol), float64(tol)) 30 } 31 32 func same(x, y float32) bool { 33 return scalar.Same(float64(x), float64(y)) 34 } 35 36 // sameStrided returns true if the strided vector x contains elements of the 37 // dense vector ref at indices i*inc, false otherwise. 38 func sameStrided(ref, x []float32, inc int) bool { 39 if inc < 0 { 40 inc = -inc 41 } 42 for i, v := range ref { 43 if !same(x[i*inc], v) { 44 return false 45 } 46 } 47 return true 48 } 49 50 func guardVector(v []float32, g float32, gdLn int) (guarded []float32) { 51 guarded = make([]float32, len(v)+gdLn*2) 52 copy(guarded[gdLn:], v) 53 for i := 0; i < gdLn; i++ { 54 guarded[i] = g 55 guarded[len(guarded)-1-i] = g 56 } 57 return guarded 58 } 59 60 func isValidGuard(v []float32, g float32, gdLn int) bool { 61 for i := 0; i < gdLn; i++ { 62 if !same(v[i], g) || !same(v[len(v)-1-i], g) { 63 return false 64 } 65 } 66 return true 67 } 68 69 func guardIncVector(vec []float32, gdVal float32, inc, gdLen int) (guarded []float32) { 70 if inc < 0 { 71 inc = -inc 72 } 73 inrLen := len(vec) * inc 74 guarded = make([]float32, inrLen+gdLen*2) 75 for i := range guarded { 76 guarded[i] = gdVal 77 } 78 for i, v := range vec { 79 guarded[gdLen+i*inc] = v 80 } 81 return guarded 82 } 83 84 func checkValidIncGuard(t *testing.T, v []float32, g float32, inc, gdLn int) { 85 srcLn := len(v) - 2*gdLn 86 for i := range v { 87 switch { 88 case same(v[i], g): 89 // Correct value 90 case i < gdLn: 91 t.Error("Front guard violated at", i, v[:gdLn]) 92 case i > gdLn+srcLn: 93 t.Error("Back guard violated at", i-gdLn-srcLn, v[gdLn+srcLn:]) 94 case (i-gdLn)%inc == 0 && (i-gdLn)/inc < len(v): 95 default: 96 t.Error("Internal guard violated at", i-gdLn, v[gdLn:gdLn+srcLn]) 97 } 98 } 99 } 100 101 var ( // Offset sets for testing alignment handling in Unitary assembly functions. 102 align2 = newIncSet(0, 1, 2, 3) 103 align3 = newIncToSet(0, 1, 2, 3) 104 ) 105 106 type incSet struct { 107 x, y int 108 } 109 110 // genInc will generate all (x,y) combinations of the input increment set. 111 func newIncSet(inc ...int) []incSet { 112 n := len(inc) 113 is := make([]incSet, n*n) 114 for x := range inc { 115 for y := range inc { 116 is[x*n+y] = incSet{inc[x], inc[y]} 117 } 118 } 119 return is 120 } 121 122 type incToSet struct { 123 dst, x, y int 124 } 125 126 // genIncTo will generate all (dst,x,y) combinations of the input increment set. 127 func newIncToSet(inc ...int) []incToSet { 128 n := len(inc) 129 is := make([]incToSet, n*n*n) 130 for i, dst := range inc { 131 for x := range inc { 132 for y := range inc { 133 is[i*n*n+x*n+y] = incToSet{dst, inc[x], inc[y]} 134 } 135 } 136 } 137 return is 138 }