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  }