mirror of
				https://github.com/gonum/gonum.git
				synced 2025-10-31 10:36:30 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			275 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			275 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright ©2015 The Gonum Authors. All rights reserved.
 | |
| // Use of this source code is governed by a BSD-style
 | |
| // license that can be found in the LICENSE file.
 | |
| 
 | |
| package f64
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"testing"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	msgVal   = "%v: unexpected value at %v Got: %v Expected: %v"
 | |
| 	msgGuard = "%v: Guard violated in %s vector %v %v"
 | |
| )
 | |
| 
 | |
| var axpyTests = []struct {
 | |
| 	alpha   float64
 | |
| 	x       []float64
 | |
| 	y       []float64
 | |
| 	want    []float64
 | |
| 	wantRev []float64 // Result when x is traversed in reverse direction.
 | |
| }{
 | |
| 	{
 | |
| 		alpha:   0,
 | |
| 		x:       []float64{},
 | |
| 		y:       []float64{},
 | |
| 		want:    []float64{},
 | |
| 		wantRev: []float64{},
 | |
| 	},
 | |
| 	{
 | |
| 		alpha:   0,
 | |
| 		x:       []float64{2},
 | |
| 		y:       []float64{-3},
 | |
| 		want:    []float64{-3},
 | |
| 		wantRev: []float64{-3},
 | |
| 	},
 | |
| 	{
 | |
| 		alpha:   1,
 | |
| 		x:       []float64{2},
 | |
| 		y:       []float64{-3},
 | |
| 		want:    []float64{-1},
 | |
| 		wantRev: []float64{-1},
 | |
| 	},
 | |
| 	{
 | |
| 		alpha:   3,
 | |
| 		x:       []float64{2},
 | |
| 		y:       []float64{-3},
 | |
| 		want:    []float64{3},
 | |
| 		wantRev: []float64{3},
 | |
| 	},
 | |
| 	{
 | |
| 		alpha:   -3,
 | |
| 		x:       []float64{2},
 | |
| 		y:       []float64{-3},
 | |
| 		want:    []float64{-9},
 | |
| 		wantRev: []float64{-9},
 | |
| 	},
 | |
| 	{
 | |
| 		alpha:   1,
 | |
| 		x:       []float64{1, 5},
 | |
| 		y:       []float64{2, -3},
 | |
| 		want:    []float64{3, 2},
 | |
| 		wantRev: []float64{7, -2},
 | |
| 	},
 | |
| 	{
 | |
| 		alpha:   1,
 | |
| 		x:       []float64{2, 3, 4},
 | |
| 		y:       []float64{-3, -2, -1},
 | |
| 		want:    []float64{-1, 1, 3},
 | |
| 		wantRev: []float64{1, 1, 1},
 | |
| 	},
 | |
| 	{
 | |
| 		alpha:   0,
 | |
| 		x:       []float64{0, 0, 1, 1, 2, -3, -4},
 | |
| 		y:       []float64{0, 1, 0, 3, -4, 5, -6},
 | |
| 		want:    []float64{0, 1, 0, 3, -4, 5, -6},
 | |
| 		wantRev: []float64{0, 1, 0, 3, -4, 5, -6},
 | |
| 	},
 | |
| 	{
 | |
| 		alpha:   1,
 | |
| 		x:       []float64{0, 0, 1, 1, 2, -3, -4},
 | |
| 		y:       []float64{0, 1, 0, 3, -4, 5, -6},
 | |
| 		want:    []float64{0, 1, 1, 4, -2, 2, -10},
 | |
| 		wantRev: []float64{-4, -2, 2, 4, -3, 5, -6},
 | |
| 	},
 | |
| 	{
 | |
| 		alpha:   3,
 | |
| 		x:       []float64{0, 0, 1, 1, 2, -3, -4},
 | |
| 		y:       []float64{0, 1, 0, 3, -4, 5, -6},
 | |
| 		want:    []float64{0, 1, 3, 6, 2, -4, -18},
 | |
| 		wantRev: []float64{-12, -8, 6, 6, -1, 5, -6},
 | |
| 	},
 | |
| 	{
 | |
| 		alpha:   -3,
 | |
| 		x:       []float64{0, 0, 1, 1, 2, -3, -4, 0, 0, 1, 1, 2, -3, -4},
 | |
| 		y:       []float64{0, 1, 0, 3, -4, 5, -6, 0, 1, 0, 3, -4, 5, -6},
 | |
| 		want:    []float64{0, 1, -3, 0, -10, 14, 6, 0, 1, -3, 0, -10, 14, 6},
 | |
| 		wantRev: []float64{12, 10, -6, 0, -7, 5, -6, 12, 10, -6, 0, -7, 5, -6},
 | |
| 	},
 | |
| 	{
 | |
| 		alpha:   -5,
 | |
| 		x:       []float64{0, 0, 1, 1, 2, -3, -4, 5, 1, 2, -3, -4, 5},
 | |
| 		y:       []float64{0, 1, 0, 3, -4, 5, -6, 7, 3, -4, 5, -6, 7},
 | |
| 		want:    []float64{0, 1, -5, -2, -14, 20, 14, -18, -2, -14, 20, 14, -18},
 | |
| 		wantRev: []float64{-25, 21, 15, -7, -9, -20, 14, 22, -7, -9, 0, -6, 7},
 | |
| 	},
 | |
| }
 | |
| 
 | |
| func TestAxpyUnitary(t *testing.T) {
 | |
| 	const xGdVal, yGdVal = -1, 0.5
 | |
| 	for i, test := range axpyTests {
 | |
| 		for _, align := range align2 {
 | |
| 			prefix := fmt.Sprintf("Test %v (x:%v y:%v)", i, align.x, align.y)
 | |
| 			xgLn, ygLn := 4+align.x, 4+align.y
 | |
| 			xg, yg := guardVector(test.x, xGdVal, xgLn), guardVector(test.y, yGdVal, ygLn)
 | |
| 			x, y := xg[xgLn:len(xg)-xgLn], yg[ygLn:len(yg)-ygLn]
 | |
| 			AxpyUnitary(test.alpha, x, y)
 | |
| 			for i := range test.want {
 | |
| 				if !same(y[i], test.want[i]) {
 | |
| 					t.Errorf(msgVal, prefix, i, y[i], test.want[i])
 | |
| 				}
 | |
| 			}
 | |
| 			if !isValidGuard(xg, xGdVal, xgLn) {
 | |
| 				t.Errorf(msgGuard, prefix, "x", xg[:xgLn], xg[len(xg)-xgLn:])
 | |
| 			}
 | |
| 			if !isValidGuard(yg, yGdVal, ygLn) {
 | |
| 				t.Errorf(msgGuard, prefix, "y", yg[:ygLn], yg[len(yg)-ygLn:])
 | |
| 			}
 | |
| 			if !equalStrided(test.x, x, 1) {
 | |
| 				t.Errorf("%v: modified read-only x argument", prefix)
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestAxpyUnitaryTo(t *testing.T) {
 | |
| 	const dstGdVal, xGdVal, yGdVal = 1, -1, 0.5
 | |
| 	for i, test := range axpyTests {
 | |
| 		for _, align := range align3 {
 | |
| 			prefix := fmt.Sprintf("Test %v (x:%v y:%v dst:%v)", i, align.x, align.y, align.dst)
 | |
| 
 | |
| 			dgLn, xgLn, ygLn := 4+align.dst, 4+align.x, 4+align.y
 | |
| 			dstOrig := make([]float64, len(test.x))
 | |
| 			xg, yg := guardVector(test.x, xGdVal, xgLn), guardVector(test.y, yGdVal, ygLn)
 | |
| 			dstg := guardVector(dstOrig, dstGdVal, dgLn)
 | |
| 			x, y := xg[xgLn:len(xg)-xgLn], yg[ygLn:len(yg)-ygLn]
 | |
| 			dst := dstg[dgLn : len(dstg)-dgLn]
 | |
| 
 | |
| 			AxpyUnitaryTo(dst, test.alpha, x, y)
 | |
| 			for i := range test.want {
 | |
| 				if !same(dst[i], test.want[i]) {
 | |
| 					t.Errorf(msgVal, prefix, i, dst[i], test.want[i])
 | |
| 				}
 | |
| 			}
 | |
| 			if !isValidGuard(xg, xGdVal, xgLn) {
 | |
| 				t.Errorf(msgGuard, prefix, "x", xg[:xgLn], xg[len(xg)-xgLn:])
 | |
| 			}
 | |
| 			if !isValidGuard(yg, yGdVal, ygLn) {
 | |
| 				t.Errorf(msgGuard, prefix, "y", yg[:ygLn], yg[len(yg)-ygLn:])
 | |
| 			}
 | |
| 			if !isValidGuard(dstg, dstGdVal, dgLn) {
 | |
| 				t.Errorf(msgGuard, prefix, "dst", dstg[:dgLn], dstg[len(dstg)-dgLn:])
 | |
| 			}
 | |
| 			if !equalStrided(test.x, x, 1) {
 | |
| 				t.Errorf("%v: modified read-only x argument", prefix)
 | |
| 			}
 | |
| 			if !equalStrided(test.y, y, 1) {
 | |
| 				t.Errorf("%v: modified read-only y argument", prefix)
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestAxpyInc(t *testing.T) {
 | |
| 	const xGdVal, yGdVal = -1, 0.5
 | |
| 	gdLn := 4
 | |
| 	for i, test := range axpyTests {
 | |
| 		n := len(test.x)
 | |
| 		for _, inc := range newIncSet(-7, -4, -3, -2, -1, 1, 2, 3, 4, 7) {
 | |
| 			var ix, iy int
 | |
| 			if inc.x < 0 {
 | |
| 				ix = (-n + 1) * inc.x
 | |
| 			}
 | |
| 			if inc.y < 0 {
 | |
| 				iy = (-n + 1) * inc.y
 | |
| 			}
 | |
| 			prefix := fmt.Sprintf("test %v, inc.x = %v, inc.y = %v", i, inc.x, inc.y)
 | |
| 			xg := guardIncVector(test.x, xGdVal, inc.x, gdLn)
 | |
| 			yg := guardIncVector(test.y, yGdVal, inc.y, gdLn)
 | |
| 			x, y := xg[gdLn:len(xg)-gdLn], yg[gdLn:len(yg)-gdLn]
 | |
| 
 | |
| 			AxpyInc(test.alpha, x, y, uintptr(n),
 | |
| 				uintptr(inc.x), uintptr(inc.y), uintptr(ix), uintptr(iy))
 | |
| 
 | |
| 			want := test.want
 | |
| 			if inc.x*inc.y < 0 {
 | |
| 				want = test.wantRev
 | |
| 			}
 | |
| 			if inc.y < 0 {
 | |
| 				inc.y = -inc.y
 | |
| 			}
 | |
| 			for i := range want {
 | |
| 				if !same(y[i*inc.y], want[i]) {
 | |
| 					t.Errorf(msgVal, prefix, i, y[iy+i*inc.y], want[i])
 | |
| 				}
 | |
| 			}
 | |
| 			if !equalStrided(test.x, x, inc.x) {
 | |
| 				t.Errorf("%v: modified read-only x argument", prefix)
 | |
| 			}
 | |
| 			checkValidIncGuard(t, xg, xGdVal, inc.x, gdLn)
 | |
| 			checkValidIncGuard(t, yg, yGdVal, inc.y, gdLn)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestAxpyIncTo(t *testing.T) {
 | |
| 	const dstGdVal, xGdVal, yGdVal = 1, -1, 0.5
 | |
| 	var want []float64
 | |
| 	gdLn := 4
 | |
| 	for i, test := range axpyTests {
 | |
| 		n := len(test.x)
 | |
| 		for _, inc := range newIncToSet(-7, -4, -3, -2, -1, 1, 2, 3, 4, 7) {
 | |
| 			var ix, iy, idst uintptr
 | |
| 			if inc.x < 0 {
 | |
| 				ix = uintptr((-n + 1) * inc.x)
 | |
| 			}
 | |
| 			if inc.y < 0 {
 | |
| 				iy = uintptr((-n + 1) * inc.y)
 | |
| 			}
 | |
| 			if inc.dst < 0 {
 | |
| 				idst = uintptr((-n + 1) * inc.dst)
 | |
| 			}
 | |
| 
 | |
| 			prefix := fmt.Sprintf("Test %v: (x: %v, y: %v, dst:%v)", i, inc.x, inc.y, inc.dst)
 | |
| 			dstOrig := make([]float64, len(test.want))
 | |
| 			xg := guardIncVector(test.x, xGdVal, inc.x, gdLn)
 | |
| 			yg := guardIncVector(test.y, yGdVal, inc.y, gdLn)
 | |
| 			dstg := guardIncVector(dstOrig, dstGdVal, inc.dst, gdLn)
 | |
| 			x, y := xg[gdLn:len(xg)-gdLn], yg[gdLn:len(yg)-gdLn]
 | |
| 			dst := dstg[gdLn : len(dstg)-gdLn]
 | |
| 
 | |
| 			AxpyIncTo(dst, uintptr(inc.dst), idst,
 | |
| 				test.alpha, x, y, uintptr(n),
 | |
| 				uintptr(inc.x), uintptr(inc.y), ix, iy)
 | |
| 			want = test.want
 | |
| 			if inc.x*inc.y < 0 {
 | |
| 				want = test.wantRev
 | |
| 			}
 | |
| 			var iW, incW int = 0, 1
 | |
| 			if inc.y*inc.dst < 0 {
 | |
| 				iW, incW = len(want)-1, -1
 | |
| 			}
 | |
| 			if inc.dst < 0 {
 | |
| 				inc.dst = -inc.dst
 | |
| 			}
 | |
| 			for i := range want {
 | |
| 				if !same(dst[i*inc.dst], want[iW+i*incW]) {
 | |
| 					t.Errorf(msgVal, prefix, i, dst[i*inc.dst], want[iW+i*incW])
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			checkValidIncGuard(t, xg, xGdVal, inc.x, gdLn)
 | |
| 			checkValidIncGuard(t, yg, yGdVal, inc.y, gdLn)
 | |
| 			checkValidIncGuard(t, dstg, dstGdVal, inc.dst, gdLn)
 | |
| 			if !equalStrided(test.x, x, inc.x) {
 | |
| 				t.Errorf("%v: modified read-only x argument", prefix)
 | |
| 			}
 | |
| 			if !equalStrided(test.y, y, inc.y) {
 | |
| 				t.Errorf("%v: modified read-only y argument", prefix)
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | 
