blob: c7cade8421d892477cc9698f9e7fa72f3c70c449 [file] [log] [blame]
// 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)
}
}
}