OSDN Git Service

new repo
[bytom/vapor.git] / vendor / gonum.org / v1 / gonum / lapack / testlapack / dlaln2.go
1 // Copyright ©2016 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 testlapack
6
7 import (
8         "fmt"
9         "math"
10         "math/cmplx"
11         "testing"
12
13         "golang.org/x/exp/rand"
14 )
15
16 type Dlaln2er interface {
17         Dlaln2(trans bool, na, nw int, smin, ca float64, a []float64, lda int, d1, d2 float64, b []float64, ldb int, wr, wi float64, x []float64, ldx int) (scale, xnorm float64, ok bool)
18 }
19
20 func Dlaln2Test(t *testing.T, impl Dlaln2er) {
21         rnd := rand.New(rand.NewSource(1))
22         for _, trans := range []bool{true, false} {
23                 for _, na := range []int{1, 2} {
24                         for _, nw := range []int{1, 2} {
25                                 for _, extra := range []int{0, 1, 2, 13} {
26                                         for cas := 0; cas < 1000; cas++ {
27                                                 testDlaln2(t, impl, trans, na, nw, extra, rnd)
28                                         }
29                                 }
30                         }
31                 }
32         }
33 }
34
35 func testDlaln2(t *testing.T, impl Dlaln2er, trans bool, na, nw, extra int, rnd *rand.Rand) {
36         const tol = 1e-12
37         const dlamchE = 1.0 / (1 << 53)
38         const dlamchP = 2 * dlamchE
39
40         ca := rnd.NormFloat64()
41         d1 := rnd.NormFloat64()
42         d2 := rnd.NormFloat64()
43
44         var w complex128
45         if nw == 1 {
46                 w = complex(rand.NormFloat64(), 0)
47         } else {
48                 w = complex(rand.NormFloat64(), rand.NormFloat64())
49         }
50         smin := dlamchP * (math.Abs(real(w)) + math.Abs(imag(w)))
51
52         a := randomGeneral(na, na, na+extra, rnd)
53         b := randomGeneral(na, nw, nw+extra, rnd)
54         x := randomGeneral(na, nw, nw+extra, rnd)
55
56         scale, xnormGot, ok := impl.Dlaln2(trans, na, nw, smin, ca, a.Data, a.Stride, d1, d2, b.Data, b.Stride, real(w), imag(w), x.Data, x.Stride)
57
58         prefix := fmt.Sprintf("Case trans=%v, na=%v, nw=%v, extra=%v", trans, na, nw, extra)
59
60         if !generalOutsideAllNaN(a) {
61                 t.Errorf("%v: out-of-range write to A\n%v", prefix, a.Data)
62         }
63         if !generalOutsideAllNaN(b) {
64                 t.Errorf("%v: out-of-range write to B\n%v", prefix, b.Data)
65         }
66         if !generalOutsideAllNaN(x) {
67                 t.Errorf("%v: out-of-range write to X\n%v", prefix, x.Data)
68         }
69
70         if scale <= 0 || 1 < scale {
71                 t.Errorf("%v: invalid value of scale=%v", prefix, scale)
72         }
73
74         var xnormWant float64
75         for i := 0; i < na; i++ {
76                 var rowsum float64
77                 for j := 0; j < nw; j++ {
78                         rowsum += math.Abs(x.Data[i*x.Stride+j])
79                 }
80                 if rowsum > xnormWant {
81                         xnormWant = rowsum
82                 }
83         }
84         if xnormWant != xnormGot {
85                 t.Errorf("Case %v: unexpected xnorm with scale=%v. Want %v, got %v", prefix, scale, xnormWant, xnormGot)
86         }
87
88         if !ok {
89                 // If ok is false, the matrix has been perturbed but we don't
90                 // know how. Return without comparing both sides of the
91                 // equation.
92                 return
93         }
94
95         m := make([]complex128, na*na)
96         if trans {
97                 for i := 0; i < na; i++ {
98                         for j := 0; j < na; j++ {
99                                 m[i*na+j] = complex(ca*a.Data[j*a.Stride+i], 0)
100                         }
101                 }
102         } else {
103                 for i := 0; i < na; i++ {
104                         for j := 0; j < na; j++ {
105                                 m[i*na+j] = complex(ca*a.Data[i*a.Stride+j], 0)
106                         }
107                 }
108         }
109         m[0] -= w * complex(d1, 0)
110         if na == 2 {
111                 m[3] -= w * complex(d2, 0)
112         }
113
114         cx := make([]complex128, na)
115         cb := make([]complex128, na)
116         switch nw {
117         case 1:
118                 for i := 0; i < na; i++ {
119                         cx[i] = complex(x.Data[i*x.Stride], 0)
120                         cb[i] = complex(scale*b.Data[i*x.Stride], 0)
121                 }
122         case 2:
123                 for i := 0; i < na; i++ {
124                         cx[i] = complex(x.Data[i*x.Stride], x.Data[i*x.Stride+1])
125                         cb[i] = complex(scale*b.Data[i*b.Stride], scale*b.Data[i*b.Stride+1])
126                 }
127         }
128
129         mx := make([]complex128, na)
130         for i := 0; i < na; i++ {
131                 for j := 0; j < na; j++ {
132                         mx[i] += m[i*na+j] * cx[j]
133                 }
134         }
135         for i := 0; i < na; i++ {
136                 if cmplx.Abs(mx[i]-cb[i]) > tol {
137                         t.Errorf("Case %v: unexpected value of left-hand side at row %v with scale=%v. Want %v, got %v", prefix, i, scale, cb[i], mx[i])
138                 }
139         }
140 }