mirror of
				https://github.com/gonum/gonum.git
				synced 2025-11-01 02:52:49 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			99 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			99 lines
		
	
	
		
			2.3 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 testlapack
 | |
| 
 | |
| import (
 | |
| 	"math"
 | |
| 	"math/rand"
 | |
| 	"testing"
 | |
| 
 | |
| 	"gonum.org/v1/gonum/floats"
 | |
| )
 | |
| 
 | |
| type Dlartger interface {
 | |
| 	Dlartg(f, g float64) (cs, sn, r float64)
 | |
| }
 | |
| 
 | |
| func DlartgTest(t *testing.T, impl Dlartger) {
 | |
| 	const tol = 1e-14
 | |
| 	// safmn2 and safmx2 are copied from native.Dlartg.
 | |
| 	safmn2 := math.Pow(dlamchB, math.Trunc(math.Log(dlamchS/dlamchE)/math.Log(dlamchB)/2))
 | |
| 	safmx2 := 1 / safmn2
 | |
| 	rnd := rand.New(rand.NewSource(1))
 | |
| 	for i := 0; i < 1000; i++ {
 | |
| 		var f float64
 | |
| 		var fHuge bool
 | |
| 		switch rnd.Intn(3) {
 | |
| 		case 0:
 | |
| 			// Huge f.
 | |
| 			fHuge = true
 | |
| 			f = math.Pow(10, 10-20*rnd.Float64()) * safmx2
 | |
| 		case 1:
 | |
| 			// Tiny f.
 | |
| 			f = math.Pow(10, 10-20*rnd.Float64()) * safmn2
 | |
| 		default:
 | |
| 			f = rnd.NormFloat64()
 | |
| 		}
 | |
| 		if rnd.Intn(2) == 0 {
 | |
| 			f *= -1
 | |
| 		}
 | |
| 
 | |
| 		var g float64
 | |
| 		var gHuge bool
 | |
| 		switch rnd.Intn(3) {
 | |
| 		case 0:
 | |
| 			// Huge g.
 | |
| 			gHuge = true
 | |
| 			g = math.Pow(10, 10-20*rnd.Float64()) * safmx2
 | |
| 		case 1:
 | |
| 			// Tiny g.
 | |
| 			g = math.Pow(10, 10-20*rnd.Float64()) * safmn2
 | |
| 		default:
 | |
| 			g = rnd.NormFloat64()
 | |
| 		}
 | |
| 		if rnd.Intn(2) == 0 {
 | |
| 			g *= -1
 | |
| 		}
 | |
| 
 | |
| 		cs, sn, r := impl.Dlartg(f, g)
 | |
| 
 | |
| 		rWant := cs*f + sn*g
 | |
| 		if !floats.EqualWithinAbsOrRel(math.Abs(rWant), math.Abs(r), tol, tol) {
 | |
| 			t.Errorf("Case f=%v,g=%v: unexpected r. Want %v, got %v", f, g, rWant, r)
 | |
| 		}
 | |
| 		oneTest := cs*cs + sn*sn
 | |
| 		if math.Abs(oneTest-1) > tol {
 | |
| 			t.Errorf("Case f=%v,g=%v: expected cs^2+sn^2==1, got %v", f, g, oneTest)
 | |
| 		}
 | |
| 		if !fHuge && !gHuge {
 | |
| 			zeroTest := -sn*f + cs*g
 | |
| 			if math.Abs(zeroTest) > tol {
 | |
| 				t.Errorf("Case f=%v,g=%v: expected zero, got %v", f, g, zeroTest)
 | |
| 			}
 | |
| 		}
 | |
| 		if math.Abs(f) > math.Abs(g) && cs < 0 {
 | |
| 			t.Errorf("Case f=%v,g=%v: unexpected negative cs %v", f, g, cs)
 | |
| 		}
 | |
| 	}
 | |
| 	for i := 0; i < 100; i++ {
 | |
| 		cs, sn, _ := impl.Dlartg(rnd.NormFloat64(), 0)
 | |
| 		if cs != 1 {
 | |
| 			t.Errorf("Unexpected cs for g=0. Want 1, got %v", cs)
 | |
| 		}
 | |
| 		if sn != 0 {
 | |
| 			t.Errorf("Unexpected sn for g=0. Want 0, got %v", sn)
 | |
| 		}
 | |
| 	}
 | |
| 	for i := 0; i < 100; i++ {
 | |
| 		cs, sn, _ := impl.Dlartg(0, rnd.NormFloat64())
 | |
| 		if cs != 0 {
 | |
| 			t.Errorf("Unexpected cs for f=0. Want 0, got %v", cs)
 | |
| 		}
 | |
| 		if sn != 1 {
 | |
| 			t.Errorf("Unexpected sn for f=0. Want 1, got %v", sn)
 | |
| 		}
 | |
| 	}
 | |
| }
 | 
