mirror of
https://github.com/gonum/gonum.git
synced 2025-10-04 23:02:42 +08:00
98 lines
2.0 KiB
Go
98 lines
2.0 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 (
|
|
"fmt"
|
|
"math"
|
|
"testing"
|
|
)
|
|
|
|
type Dlartger interface {
|
|
Dlartg(f, g float64) (cs, sn, r float64)
|
|
}
|
|
|
|
func DlartgTest(t *testing.T, impl Dlartger) {
|
|
const tol = 20 * ulp
|
|
|
|
values := []float64{
|
|
-safmax,
|
|
-1 / ulp,
|
|
-1,
|
|
-1.0 / 3,
|
|
-ulp,
|
|
-safmin,
|
|
0,
|
|
safmin,
|
|
ulp,
|
|
1.0 / 3,
|
|
1,
|
|
1 / ulp,
|
|
safmax,
|
|
math.Inf(-1),
|
|
math.Inf(1),
|
|
math.NaN(),
|
|
}
|
|
|
|
for _, f := range values {
|
|
for _, g := range values {
|
|
name := fmt.Sprintf("Case f=%v,g=%v", f, g)
|
|
|
|
// Generate a plane rotation so that
|
|
// [ cs sn] * [f] = [r]
|
|
// [-sn cs] [g] = [0]
|
|
// where cs*cs + sn*sn = 1.
|
|
cs, sn, r := impl.Dlartg(f, g)
|
|
|
|
switch {
|
|
case math.IsNaN(f) || math.IsNaN(g):
|
|
if !math.IsNaN(r) {
|
|
t.Errorf("%v: unexpected r=%v; want NaN", name, r)
|
|
}
|
|
case math.IsInf(f, 0) || math.IsInf(g, 0):
|
|
if !math.IsNaN(r) && !math.IsInf(r, 0) {
|
|
t.Errorf("%v: unexpected r=%v; want NaN or Inf", name, r)
|
|
}
|
|
default:
|
|
d := math.Max(math.Abs(f), math.Abs(g))
|
|
d = math.Min(math.Max(safmin, d), safmax)
|
|
fs := f / d
|
|
gs := g / d
|
|
rs := r / d
|
|
|
|
// Check that cs*f + sn*g = r.
|
|
rnorm := math.Abs(rs)
|
|
if rnorm == 0 {
|
|
rnorm = math.Max(math.Abs(fs), math.Abs(gs))
|
|
if rnorm == 0 {
|
|
rnorm = 1
|
|
}
|
|
}
|
|
resid := math.Abs(rs-(cs*fs+sn*gs)) / rnorm
|
|
if resid > tol {
|
|
t.Errorf("%v: cs*f + sn*g != r; resid=%v", name, resid)
|
|
}
|
|
|
|
// Check that -sn*f + cs*g = 0.
|
|
resid = math.Abs(-sn*fs + cs*gs)
|
|
if resid > tol {
|
|
t.Errorf("%v: -sn*f + cs*g != 0; resid=%v", name, resid)
|
|
}
|
|
|
|
// Check that cs*cs + sn*sn = 1.
|
|
resid = math.Abs(1 - (cs*cs + sn*sn))
|
|
if resid > tol {
|
|
t.Errorf("%v: cs*cs + sn*sn != 1; resid=%v", name, resid)
|
|
}
|
|
|
|
// Check that cs is non-negative.
|
|
if math.Abs(f) > math.Abs(g) && cs < 0 {
|
|
t.Errorf("%v: cs is negative; cs=%v", name, cs)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|