// Copyright ©2016 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. // This program generates test data for Dlaqr5. Test cases are stored in // gzip-compressed JSON file testlapack/testdata/dlaqr5data.json.gz which is // read during testing by testlapack/dlaqr5.go. // // This program uses cgo to call Fortran version of DLAQR5. Therefore, matrices // passed to the Fortran routine are in column-major format but are written into // the output file in row-major format. package main import ( "compress/gzip" "encoding/json" "log" "os" "path/filepath" "golang.org/x/exp/rand" "gonum.org/v1/gonum/lapack/internal/testdata/netlib" ) type Dlaqr5Test struct { WantT bool N int NShifts int KTop, KBot int ShiftR, ShiftI []float64 H []float64 HWant []float64 ZWant []float64 } func main() { file, err := os.Create(filepath.FromSlash("../../../testlapack/testdata/dlaqr5data.json.gz")) if err != nil { log.Fatal(err) } defer file.Close() w := gzip.NewWriter(file) rnd := rand.New(rand.NewSource(1)) var tests []Dlaqr5Test for _, wantt := range []bool{true, false} { for _, n := range []int{2, 3, 4, 5, 6, 7, 11} { for k := 0; k <= min(5, n); k++ { npairs := k if npairs == 0 { npairs = 2 * n } for ktop := 0; ktop < n-1; ktop++ { for kbot := ktop + 1; kbot < n; kbot++ { sr, si := shiftpairs(npairs, rnd) nshfts := len(sr) v := genrand(nshfts/2, 3, rnd) u := genrand(3*nshfts-3, 3*nshfts-3, rnd) wh := genrand(3*nshfts-3, n, rnd) nh := n wv := genrand(n, 3*nshfts-3, rnd) nv := n h := hessrand(n, rnd) if ktop > 0 { h[ktop+(ktop-1)*n] = 0 } if kbot < n-1 { h[kbot+1+kbot*n] = 0 } hin := make([]float64, len(h)) copy(hin, h) z := eye(n) netlib.Dlaqr5(wantt, true, 2, n, ktop+1, kbot+1, nshfts, sr, si, h, n, 1, n, z, n, v, 3, u, 3*nshfts-3, nh, wh, nh, nv, wv, 3*nshfts-3) tests = append(tests, Dlaqr5Test{ WantT: wantt, N: n, NShifts: nshfts, KTop: ktop, KBot: kbot, ShiftR: sr, ShiftI: si, H: rowMajor(n, n, hin), HWant: rowMajor(n, n, h), ZWant: rowMajor(n, n, z), }) } } } } } json.NewEncoder(w).Encode(tests) err = w.Close() if err != nil { log.Fatal(err) } } // genrand returns a general r×c matrix with random entries. func genrand(r, c int, rnd *rand.Rand) []float64 { m := make([]float64, r*c) for i := range m { m[i] = rnd.NormFloat64() } return m } // eye returns an identity matrix of order n. func eye(n int) []float64 { m := make([]float64, n*n) for i := 0; i < n*n; i += n + 1 { m[i] = 1 } return m } // hessrand returns a Hessenberg matrix of order n with random non-zero entries // in column-major format. func hessrand(n int, rnd *rand.Rand) []float64 { h := make([]float64, n*n) for j := 0; j < n; j++ { for i := 0; i <= min(j+1, n-1); i++ { h[i+j*n] = rnd.NormFloat64() } } return h } // shiftpairs generates k real and complex conjugate shift pairs. That is, the // length of sr and si is 2*k. func shiftpairs(k int, rnd *rand.Rand) (sr, si []float64) { sr = make([]float64, 2*k) si = make([]float64, 2*k) for i := 0; i < len(sr); { if rnd.Float64() < 0.5 || i == len(sr)-1 { sr[i] = rnd.NormFloat64() i++ continue } // Generate a complex conjugate pair. r := rnd.NormFloat64() c := rnd.NormFloat64() sr[i] = r si[i] = c sr[i+1] = r si[i+1] = -c i += 2 } return sr, si } // rowMajor returns the given r×c column-major matrix a in row-major format. func rowMajor(r, c int, a []float64) []float64 { if len(a) != r*c { panic("testdata: slice length mismatch") } m := make([]float64, len(a)) for i := 0; i < r; i++ { for j := 0; j < c; j++ { m[i*c+j] = a[i+j*r] } } return m } func min(a, b int) int { if a < b { return a } return b }