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.
13 "golang.org/x/exp/rand"
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)
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)
35 func testDlaln2(t *testing.T, impl Dlaln2er, trans bool, na, nw, extra int, rnd *rand.Rand) {
37 const dlamchE = 1.0 / (1 << 53)
38 const dlamchP = 2 * dlamchE
40 ca := rnd.NormFloat64()
41 d1 := rnd.NormFloat64()
42 d2 := rnd.NormFloat64()
46 w = complex(rand.NormFloat64(), 0)
48 w = complex(rand.NormFloat64(), rand.NormFloat64())
50 smin := dlamchP * (math.Abs(real(w)) + math.Abs(imag(w)))
52 a := randomGeneral(na, na, na+extra, rnd)
53 b := randomGeneral(na, nw, nw+extra, rnd)
54 x := randomGeneral(na, nw, nw+extra, rnd)
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)
58 prefix := fmt.Sprintf("Case trans=%v, na=%v, nw=%v, extra=%v", trans, na, nw, extra)
60 if !generalOutsideAllNaN(a) {
61 t.Errorf("%v: out-of-range write to A\n%v", prefix, a.Data)
63 if !generalOutsideAllNaN(b) {
64 t.Errorf("%v: out-of-range write to B\n%v", prefix, b.Data)
66 if !generalOutsideAllNaN(x) {
67 t.Errorf("%v: out-of-range write to X\n%v", prefix, x.Data)
70 if scale <= 0 || 1 < scale {
71 t.Errorf("%v: invalid value of scale=%v", prefix, scale)
75 for i := 0; i < na; i++ {
77 for j := 0; j < nw; j++ {
78 rowsum += math.Abs(x.Data[i*x.Stride+j])
80 if rowsum > xnormWant {
84 if xnormWant != xnormGot {
85 t.Errorf("Case %v: unexpected xnorm with scale=%v. Want %v, got %v", prefix, scale, xnormWant, xnormGot)
89 // If ok is false, the matrix has been perturbed but we don't
90 // know how. Return without comparing both sides of the
95 m := make([]complex128, na*na)
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)
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)
109 m[0] -= w * complex(d1, 0)
111 m[3] -= w * complex(d2, 0)
114 cx := make([]complex128, na)
115 cb := make([]complex128, na)
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)
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])
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]
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])