github.com/gonum/lapack@v0.0.0-20181123203213-e4cdc5a0bff9/internal/testdata/dlaqr5test/main.go (about)

     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  // This program generates test data for Dlaqr5. Test cases are stored in
     6  // gzip-compressed JSON file testlapack/testdata/dlaqr5data.json.gz which is
     7  // read during testing by testlapack/dlaqr5.go.
     8  //
     9  // This program uses cgo to call Fortran version of DLAQR5. Therefore, matrices
    10  // passed to the Fortran routine are in column-major format but are written into
    11  // the output file in row-major format.
    12  package main
    13  
    14  import (
    15  	"compress/gzip"
    16  	"encoding/json"
    17  	"log"
    18  	"math/rand"
    19  	"os"
    20  	"path/filepath"
    21  
    22  	"github.com/gonum/lapack/internal/testdata/netlib"
    23  )
    24  
    25  type Dlaqr5Test struct {
    26  	WantT          bool
    27  	N              int
    28  	NShifts        int
    29  	KTop, KBot     int
    30  	ShiftR, ShiftI []float64
    31  	H              []float64
    32  
    33  	HWant []float64
    34  	ZWant []float64
    35  }
    36  
    37  func main() {
    38  	file, err := os.Create(filepath.FromSlash("../../../testlapack/testdata/dlaqr5data.json.gz"))
    39  	if err != nil {
    40  		log.Fatal(err)
    41  	}
    42  	defer file.Close()
    43  	w := gzip.NewWriter(file)
    44  
    45  	rnd := rand.New(rand.NewSource(1))
    46  
    47  	var tests []Dlaqr5Test
    48  	for _, wantt := range []bool{true, false} {
    49  		for _, n := range []int{2, 3, 4, 5, 6, 7, 11} {
    50  			for k := 0; k <= min(5, n); k++ {
    51  				npairs := k
    52  				if npairs == 0 {
    53  					npairs = 2 * n
    54  				}
    55  				for ktop := 0; ktop < n-1; ktop++ {
    56  					for kbot := ktop + 1; kbot < n; kbot++ {
    57  						sr, si := shiftpairs(npairs, rnd)
    58  						nshfts := len(sr)
    59  
    60  						v := genrand(nshfts/2, 3, rnd)
    61  						u := genrand(3*nshfts-3, 3*nshfts-3, rnd)
    62  						wh := genrand(3*nshfts-3, n, rnd)
    63  						nh := n
    64  						wv := genrand(n, 3*nshfts-3, rnd)
    65  						nv := n
    66  
    67  						h := hessrand(n, rnd)
    68  						if ktop > 0 {
    69  							h[ktop+(ktop-1)*n] = 0
    70  						}
    71  						if kbot < n-1 {
    72  							h[kbot+1+kbot*n] = 0
    73  						}
    74  						hin := make([]float64, len(h))
    75  						copy(hin, h)
    76  						z := eye(n)
    77  
    78  						netlib.Dlaqr5(wantt, true, 2,
    79  							n, ktop+1, kbot+1,
    80  							nshfts, sr, si,
    81  							h, n,
    82  							1, n, z, n,
    83  							v, 3,
    84  							u, 3*nshfts-3,
    85  							nh, wh, nh,
    86  							nv, wv, 3*nshfts-3)
    87  
    88  						tests = append(tests, Dlaqr5Test{
    89  							WantT:   wantt,
    90  							N:       n,
    91  							NShifts: nshfts,
    92  							KTop:    ktop,
    93  							KBot:    kbot,
    94  							ShiftR:  sr,
    95  							ShiftI:  si,
    96  							H:       rowMajor(n, n, hin),
    97  							HWant:   rowMajor(n, n, h),
    98  							ZWant:   rowMajor(n, n, z),
    99  						})
   100  					}
   101  				}
   102  			}
   103  		}
   104  	}
   105  	json.NewEncoder(w).Encode(tests)
   106  
   107  	err = w.Close()
   108  	if err != nil {
   109  		log.Fatal(err)
   110  	}
   111  }
   112  
   113  // genrand returns a general r×c matrix with random entries.
   114  func genrand(r, c int, rnd *rand.Rand) []float64 {
   115  	m := make([]float64, r*c)
   116  	for i := range m {
   117  		m[i] = rnd.NormFloat64()
   118  	}
   119  	return m
   120  }
   121  
   122  // eye returns an identity matrix of order n.
   123  func eye(n int) []float64 {
   124  	m := make([]float64, n*n)
   125  	for i := 0; i < n*n; i += n + 1 {
   126  		m[i] = 1
   127  	}
   128  	return m
   129  }
   130  
   131  // hessrand returns a Hessenberg matrix of order n with random non-zero entries
   132  // in column-major format.
   133  func hessrand(n int, rnd *rand.Rand) []float64 {
   134  	h := make([]float64, n*n)
   135  	for j := 0; j < n; j++ {
   136  		for i := 0; i <= min(j+1, n-1); i++ {
   137  			h[i+j*n] = rnd.NormFloat64()
   138  		}
   139  	}
   140  	return h
   141  }
   142  
   143  // shiftpairs generates k real and complex conjugate shift pairs. That is, the
   144  // length of sr and si is 2*k.
   145  func shiftpairs(k int, rnd *rand.Rand) (sr, si []float64) {
   146  	sr = make([]float64, 2*k)
   147  	si = make([]float64, 2*k)
   148  	for i := 0; i < len(sr); {
   149  		if rnd.Float64() < 0.5 || i == len(sr)-1 {
   150  			sr[i] = rnd.NormFloat64()
   151  			i++
   152  			continue
   153  		}
   154  		// Generate a complex conjugate pair.
   155  		r := rnd.NormFloat64()
   156  		c := rnd.NormFloat64()
   157  		sr[i] = r
   158  		si[i] = c
   159  		sr[i+1] = r
   160  		si[i+1] = -c
   161  		i += 2
   162  	}
   163  	return sr, si
   164  }
   165  
   166  // rowMajor returns the given r×c column-major matrix a in row-major format.
   167  func rowMajor(r, c int, a []float64) []float64 {
   168  	if len(a) != r*c {
   169  		panic("testdata: slice length mismatch")
   170  	}
   171  	m := make([]float64, len(a))
   172  	for i := 0; i < r; i++ {
   173  		for j := 0; j < c; j++ {
   174  			m[i*c+j] = a[i+j*r]
   175  		}
   176  	}
   177  	return m
   178  }
   179  
   180  func min(a, b int) int {
   181  	if a < b {
   182  		return a
   183  	}
   184  	return b
   185  }