github.com/gonum/lapack@v0.0.0-20181123203213-e4cdc5a0bff9/testlapack/general.go (about)

     1  // Copyright ©2015 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 repository is no longer maintained.
     6  // Development has moved to https://github.com/gonum/gonum.
     7  package testlapack
     8  
     9  import (
    10  	"fmt"
    11  	"math"
    12  	"math/cmplx"
    13  	"math/rand"
    14  	"testing"
    15  
    16  	"github.com/gonum/blas"
    17  	"github.com/gonum/blas/blas64"
    18  	"github.com/gonum/floats"
    19  	"github.com/gonum/lapack"
    20  )
    21  
    22  const (
    23  	// dlamchE is the machine epsilon. For IEEE this is 2^{-53}.
    24  	dlamchE = 1.0 / (1 << 53)
    25  	dlamchB = 2
    26  	dlamchP = dlamchB * dlamchE
    27  	// dlamchS is the smallest normal number. For IEEE this is 2^{-1022}.
    28  	dlamchS = 1.0 / (1 << 256) / (1 << 256) / (1 << 256) / (1 << 254)
    29  )
    30  
    31  func max(a, b int) int {
    32  	if a > b {
    33  		return a
    34  	}
    35  	return b
    36  }
    37  
    38  func min(a, b int) int {
    39  	if a < b {
    40  		return a
    41  	}
    42  	return b
    43  }
    44  
    45  // worklen describes how much workspace a test should use.
    46  type worklen int
    47  
    48  const (
    49  	minimumWork worklen = iota
    50  	mediumWork
    51  	optimumWork
    52  )
    53  
    54  // nanSlice allocates a new slice of length n filled with NaN.
    55  func nanSlice(n int) []float64 {
    56  	s := make([]float64, n)
    57  	for i := range s {
    58  		s[i] = math.NaN()
    59  	}
    60  	return s
    61  }
    62  
    63  // randomSlice allocates a new slice of length n filled with random values.
    64  func randomSlice(n int, rnd *rand.Rand) []float64 {
    65  	s := make([]float64, n)
    66  	for i := range s {
    67  		s[i] = rnd.NormFloat64()
    68  	}
    69  	return s
    70  }
    71  
    72  // nanGeneral allocates a new r×c general matrix filled with NaN values.
    73  func nanGeneral(r, c, stride int) blas64.General {
    74  	if r < 0 || c < 0 {
    75  		panic("bad matrix size")
    76  	}
    77  	if r == 0 || c == 0 {
    78  		return blas64.General{Stride: max(1, stride)}
    79  	}
    80  	if stride < c {
    81  		panic("bad stride")
    82  	}
    83  	return blas64.General{
    84  		Rows:   r,
    85  		Cols:   c,
    86  		Stride: stride,
    87  		Data:   nanSlice((r-1)*stride + c),
    88  	}
    89  }
    90  
    91  // randomGeneral allocates a new r×c general matrix filled with random
    92  // numbers. Out-of-range elements are filled with NaN values.
    93  func randomGeneral(r, c, stride int, rnd *rand.Rand) blas64.General {
    94  	ans := nanGeneral(r, c, stride)
    95  	for i := 0; i < r; i++ {
    96  		for j := 0; j < c; j++ {
    97  			ans.Data[i*ans.Stride+j] = rnd.NormFloat64()
    98  		}
    99  	}
   100  	return ans
   101  }
   102  
   103  // randomHessenberg allocates a new n×n Hessenberg matrix filled with zeros
   104  // under the first subdiagonal and with random numbers elsewhere. Out-of-range
   105  // elements are filled with NaN values.
   106  func randomHessenberg(n, stride int, rnd *rand.Rand) blas64.General {
   107  	ans := nanGeneral(n, n, stride)
   108  	for i := 0; i < n; i++ {
   109  		for j := 0; j < i-1; j++ {
   110  			ans.Data[i*ans.Stride+j] = 0
   111  		}
   112  		for j := max(0, i-1); j < n; j++ {
   113  			ans.Data[i*ans.Stride+j] = rnd.NormFloat64()
   114  		}
   115  	}
   116  	return ans
   117  }
   118  
   119  // randomSchurCanonical returns a random, general matrix in Schur canonical
   120  // form, that is, block upper triangular with 1×1 and 2×2 diagonal blocks where
   121  // each 2×2 diagonal block has its diagonal elements equal and its off-diagonal
   122  // elements of opposite sign.
   123  func randomSchurCanonical(n, stride int, rnd *rand.Rand) blas64.General {
   124  	t := randomGeneral(n, n, stride, rnd)
   125  	// Zero out the lower triangle.
   126  	for i := 0; i < t.Rows; i++ {
   127  		for j := 0; j < i; j++ {
   128  			t.Data[i*t.Stride+j] = 0
   129  		}
   130  	}
   131  	// Randomly create 2×2 diagonal blocks.
   132  	for i := 0; i < t.Rows; {
   133  		if i == t.Rows-1 || rnd.Float64() < 0.5 {
   134  			// 1×1 block.
   135  			i++
   136  			continue
   137  		}
   138  		// 2×2 block.
   139  		// Diagonal elements equal.
   140  		t.Data[(i+1)*t.Stride+i+1] = t.Data[i*t.Stride+i]
   141  		// Off-diagonal elements of opposite sign.
   142  		c := rnd.NormFloat64()
   143  		if math.Signbit(c) == math.Signbit(t.Data[i*t.Stride+i+1]) {
   144  			c *= -1
   145  		}
   146  		t.Data[(i+1)*t.Stride+i] = c
   147  		i += 2
   148  	}
   149  	return t
   150  }
   151  
   152  // blockedUpperTriGeneral returns a normal random, general matrix in the form
   153  //
   154  //            c-k-l  k    l
   155  //  A =    k [  0   A12  A13 ] if r-k-l >= 0;
   156  //         l [  0    0   A23 ]
   157  //     r-k-l [  0    0    0  ]
   158  //
   159  //          c-k-l  k    l
   160  //  A =  k [  0   A12  A13 ] if r-k-l < 0;
   161  //     r-k [  0    0   A23 ]
   162  //
   163  // where the k×k matrix A12 and l×l matrix is non-singular
   164  // upper triangular. A23 is l×l upper triangular if r-k-l >= 0,
   165  // otherwise A23 is (r-k)×l upper trapezoidal.
   166  func blockedUpperTriGeneral(r, c, k, l, stride int, kblock bool, rnd *rand.Rand) blas64.General {
   167  	t := l
   168  	if kblock {
   169  		t += k
   170  	}
   171  	ans := zeros(r, c, stride)
   172  	for i := 0; i < min(r, t); i++ {
   173  		var v float64
   174  		for v == 0 {
   175  			v = rnd.NormFloat64()
   176  		}
   177  		ans.Data[i*ans.Stride+i+(c-t)] = v
   178  	}
   179  	for i := 0; i < min(r, t); i++ {
   180  		for j := i + (c - t) + 1; j < c; j++ {
   181  			ans.Data[i*ans.Stride+j] = rnd.NormFloat64()
   182  		}
   183  	}
   184  	return ans
   185  }
   186  
   187  // nanTriangular allocates a new r×c triangular matrix filled with NaN values.
   188  func nanTriangular(uplo blas.Uplo, n, stride int) blas64.Triangular {
   189  	if n < 0 {
   190  		panic("bad matrix size")
   191  	}
   192  	if n == 0 {
   193  		return blas64.Triangular{
   194  			Stride: max(1, stride),
   195  			Uplo:   uplo,
   196  			Diag:   blas.NonUnit,
   197  		}
   198  	}
   199  	if stride < n {
   200  		panic("bad stride")
   201  	}
   202  	return blas64.Triangular{
   203  		N:      n,
   204  		Stride: stride,
   205  		Data:   nanSlice((n-1)*stride + n),
   206  		Uplo:   uplo,
   207  		Diag:   blas.NonUnit,
   208  	}
   209  }
   210  
   211  // randomTriangular allocates a new r×c triangular matrix filled with random
   212  // numbers. Out-of-triangle elements are filled with NaN values.
   213  func randomTriangular(uplo blas.Uplo, n, stride int, rnd *rand.Rand) blas64.Triangular {
   214  	ans := nanTriangular(uplo, n, stride)
   215  	if uplo == blas.Upper {
   216  		for i := 0; i < n; i++ {
   217  			for j := i; j < n; j++ {
   218  				ans.Data[i*ans.Stride+j] = rnd.NormFloat64()
   219  			}
   220  		}
   221  		return ans
   222  	}
   223  	for i := 0; i < n; i++ {
   224  		for j := 0; j <= i; j++ {
   225  			ans.Data[i*ans.Stride+j] = rnd.NormFloat64()
   226  		}
   227  	}
   228  	return ans
   229  }
   230  
   231  // generalOutsideAllNaN returns whether all out-of-range elements have NaN
   232  // values.
   233  func generalOutsideAllNaN(a blas64.General) bool {
   234  	// Check after last column.
   235  	for i := 0; i < a.Rows-1; i++ {
   236  		for _, v := range a.Data[i*a.Stride+a.Cols : i*a.Stride+a.Stride] {
   237  			if !math.IsNaN(v) {
   238  				return false
   239  			}
   240  		}
   241  	}
   242  	// Check after last element.
   243  	last := (a.Rows-1)*a.Stride + a.Cols
   244  	if a.Rows == 0 || a.Cols == 0 {
   245  		last = 0
   246  	}
   247  	for _, v := range a.Data[last:] {
   248  		if !math.IsNaN(v) {
   249  			return false
   250  		}
   251  	}
   252  	return true
   253  }
   254  
   255  // triangularOutsideAllNaN returns whether all out-of-triangle elements have NaN
   256  // values.
   257  func triangularOutsideAllNaN(a blas64.Triangular) bool {
   258  	if a.Uplo == blas.Upper {
   259  		// Check below diagonal.
   260  		for i := 0; i < a.N; i++ {
   261  			for _, v := range a.Data[i*a.Stride : i*a.Stride+i] {
   262  				if !math.IsNaN(v) {
   263  					return false
   264  				}
   265  			}
   266  		}
   267  		// Check after last column.
   268  		for i := 0; i < a.N-1; i++ {
   269  			for _, v := range a.Data[i*a.Stride+a.N : i*a.Stride+a.Stride] {
   270  				if !math.IsNaN(v) {
   271  					return false
   272  				}
   273  			}
   274  		}
   275  	} else {
   276  		// Check above diagonal.
   277  		for i := 0; i < a.N-1; i++ {
   278  			for _, v := range a.Data[i*a.Stride+i+1 : i*a.Stride+a.Stride] {
   279  				if !math.IsNaN(v) {
   280  					return false
   281  				}
   282  			}
   283  		}
   284  	}
   285  	// Check after last element.
   286  	for _, v := range a.Data[max(0, a.N-1)*a.Stride+a.N:] {
   287  		if !math.IsNaN(v) {
   288  			return false
   289  		}
   290  	}
   291  	return true
   292  }
   293  
   294  // transposeGeneral returns a new general matrix that is the transpose of the
   295  // input. Nothing is done with data outside the {rows, cols} limit of the general.
   296  func transposeGeneral(a blas64.General) blas64.General {
   297  	ans := blas64.General{
   298  		Rows:   a.Cols,
   299  		Cols:   a.Rows,
   300  		Stride: a.Rows,
   301  		Data:   make([]float64, a.Cols*a.Rows),
   302  	}
   303  	for i := 0; i < a.Rows; i++ {
   304  		for j := 0; j < a.Cols; j++ {
   305  			ans.Data[j*ans.Stride+i] = a.Data[i*a.Stride+j]
   306  		}
   307  	}
   308  	return ans
   309  }
   310  
   311  // columnNorms returns the column norms of a.
   312  func columnNorms(m, n int, a []float64, lda int) []float64 {
   313  	bi := blas64.Implementation()
   314  	norms := make([]float64, n)
   315  	for j := 0; j < n; j++ {
   316  		norms[j] = bi.Dnrm2(m, a[j:], lda)
   317  	}
   318  	return norms
   319  }
   320  
   321  // extractVMat collects the single reflectors from a into a matrix.
   322  func extractVMat(m, n int, a []float64, lda int, direct lapack.Direct, store lapack.StoreV) blas64.General {
   323  	k := min(m, n)
   324  	switch {
   325  	default:
   326  		panic("not implemented")
   327  	case direct == lapack.Forward && store == lapack.ColumnWise:
   328  		v := blas64.General{
   329  			Rows:   m,
   330  			Cols:   k,
   331  			Stride: k,
   332  			Data:   make([]float64, m*k),
   333  		}
   334  		for i := 0; i < k; i++ {
   335  			for j := 0; j < i; j++ {
   336  				v.Data[j*v.Stride+i] = 0
   337  			}
   338  			v.Data[i*v.Stride+i] = 1
   339  			for j := i + 1; j < m; j++ {
   340  				v.Data[j*v.Stride+i] = a[j*lda+i]
   341  			}
   342  		}
   343  		return v
   344  	case direct == lapack.Forward && store == lapack.RowWise:
   345  		v := blas64.General{
   346  			Rows:   k,
   347  			Cols:   n,
   348  			Stride: n,
   349  			Data:   make([]float64, k*n),
   350  		}
   351  		for i := 0; i < k; i++ {
   352  			for j := 0; j < i; j++ {
   353  				v.Data[i*v.Stride+j] = 0
   354  			}
   355  			v.Data[i*v.Stride+i] = 1
   356  			for j := i + 1; j < n; j++ {
   357  				v.Data[i*v.Stride+j] = a[i*lda+j]
   358  			}
   359  		}
   360  		return v
   361  	}
   362  }
   363  
   364  // constructBidiagonal constructs a bidiagonal matrix with the given diagonal
   365  // and off-diagonal elements.
   366  func constructBidiagonal(uplo blas.Uplo, n int, d, e []float64) blas64.General {
   367  	bMat := blas64.General{
   368  		Rows:   n,
   369  		Cols:   n,
   370  		Stride: n,
   371  		Data:   make([]float64, n*n),
   372  	}
   373  
   374  	for i := 0; i < n-1; i++ {
   375  		bMat.Data[i*bMat.Stride+i] = d[i]
   376  		if uplo == blas.Upper {
   377  			bMat.Data[i*bMat.Stride+i+1] = e[i]
   378  		} else {
   379  			bMat.Data[(i+1)*bMat.Stride+i] = e[i]
   380  		}
   381  	}
   382  	bMat.Data[(n-1)*bMat.Stride+n-1] = d[n-1]
   383  	return bMat
   384  }
   385  
   386  // constructVMat transforms the v matrix based on the storage.
   387  func constructVMat(vMat blas64.General, store lapack.StoreV, direct lapack.Direct) blas64.General {
   388  	m := vMat.Rows
   389  	k := vMat.Cols
   390  	switch {
   391  	default:
   392  		panic("not implemented")
   393  	case store == lapack.ColumnWise && direct == lapack.Forward:
   394  		ldv := k
   395  		v := make([]float64, m*k)
   396  		for i := 0; i < m; i++ {
   397  			for j := 0; j < k; j++ {
   398  				if j > i {
   399  					v[i*ldv+j] = 0
   400  				} else if j == i {
   401  					v[i*ldv+i] = 1
   402  				} else {
   403  					v[i*ldv+j] = vMat.Data[i*vMat.Stride+j]
   404  				}
   405  			}
   406  		}
   407  		return blas64.General{
   408  			Rows:   m,
   409  			Cols:   k,
   410  			Stride: k,
   411  			Data:   v,
   412  		}
   413  	case store == lapack.RowWise && direct == lapack.Forward:
   414  		ldv := m
   415  		v := make([]float64, m*k)
   416  		for i := 0; i < m; i++ {
   417  			for j := 0; j < k; j++ {
   418  				if j > i {
   419  					v[j*ldv+i] = 0
   420  				} else if j == i {
   421  					v[j*ldv+i] = 1
   422  				} else {
   423  					v[j*ldv+i] = vMat.Data[i*vMat.Stride+j]
   424  				}
   425  			}
   426  		}
   427  		return blas64.General{
   428  			Rows:   k,
   429  			Cols:   m,
   430  			Stride: m,
   431  			Data:   v,
   432  		}
   433  	case store == lapack.ColumnWise && direct == lapack.Backward:
   434  		rowsv := m
   435  		ldv := k
   436  		v := make([]float64, m*k)
   437  		for i := 0; i < m; i++ {
   438  			for j := 0; j < k; j++ {
   439  				vrow := rowsv - i - 1
   440  				vcol := k - j - 1
   441  				if j > i {
   442  					v[vrow*ldv+vcol] = 0
   443  				} else if j == i {
   444  					v[vrow*ldv+vcol] = 1
   445  				} else {
   446  					v[vrow*ldv+vcol] = vMat.Data[i*vMat.Stride+j]
   447  				}
   448  			}
   449  		}
   450  		return blas64.General{
   451  			Rows:   rowsv,
   452  			Cols:   ldv,
   453  			Stride: ldv,
   454  			Data:   v,
   455  		}
   456  	case store == lapack.RowWise && direct == lapack.Backward:
   457  		rowsv := k
   458  		ldv := m
   459  		v := make([]float64, m*k)
   460  		for i := 0; i < m; i++ {
   461  			for j := 0; j < k; j++ {
   462  				vcol := ldv - i - 1
   463  				vrow := k - j - 1
   464  				if j > i {
   465  					v[vrow*ldv+vcol] = 0
   466  				} else if j == i {
   467  					v[vrow*ldv+vcol] = 1
   468  				} else {
   469  					v[vrow*ldv+vcol] = vMat.Data[i*vMat.Stride+j]
   470  				}
   471  			}
   472  		}
   473  		return blas64.General{
   474  			Rows:   rowsv,
   475  			Cols:   ldv,
   476  			Stride: ldv,
   477  			Data:   v,
   478  		}
   479  	}
   480  }
   481  
   482  func constructH(tau []float64, v blas64.General, store lapack.StoreV, direct lapack.Direct) blas64.General {
   483  	m := v.Rows
   484  	k := v.Cols
   485  	if store == lapack.RowWise {
   486  		m, k = k, m
   487  	}
   488  	h := blas64.General{
   489  		Rows:   m,
   490  		Cols:   m,
   491  		Stride: m,
   492  		Data:   make([]float64, m*m),
   493  	}
   494  	for i := 0; i < m; i++ {
   495  		h.Data[i*m+i] = 1
   496  	}
   497  	for i := 0; i < k; i++ {
   498  		vecData := make([]float64, m)
   499  		if store == lapack.ColumnWise {
   500  			for j := 0; j < m; j++ {
   501  				vecData[j] = v.Data[j*v.Cols+i]
   502  			}
   503  		} else {
   504  			for j := 0; j < m; j++ {
   505  				vecData[j] = v.Data[i*v.Cols+j]
   506  			}
   507  		}
   508  		vec := blas64.Vector{
   509  			Inc:  1,
   510  			Data: vecData,
   511  		}
   512  
   513  		hi := blas64.General{
   514  			Rows:   m,
   515  			Cols:   m,
   516  			Stride: m,
   517  			Data:   make([]float64, m*m),
   518  		}
   519  		for i := 0; i < m; i++ {
   520  			hi.Data[i*m+i] = 1
   521  		}
   522  		// hi = I - tau * v * v^T
   523  		blas64.Ger(-tau[i], vec, vec, hi)
   524  
   525  		hcopy := blas64.General{
   526  			Rows:   m,
   527  			Cols:   m,
   528  			Stride: m,
   529  			Data:   make([]float64, m*m),
   530  		}
   531  		copy(hcopy.Data, h.Data)
   532  		if direct == lapack.Forward {
   533  			// H = H * H_I in forward mode
   534  			blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, hcopy, hi, 0, h)
   535  		} else {
   536  			// H = H_I * H in backward mode
   537  			blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, hi, hcopy, 0, h)
   538  		}
   539  	}
   540  	return h
   541  }
   542  
   543  // constructQ constructs the Q matrix from the result of dgeqrf and dgeqr2.
   544  func constructQ(kind string, m, n int, a []float64, lda int, tau []float64) blas64.General {
   545  	k := min(m, n)
   546  	return constructQK(kind, m, n, k, a, lda, tau)
   547  }
   548  
   549  // constructQK constructs the Q matrix from the result of dgeqrf and dgeqr2 using
   550  // the first k reflectors.
   551  func constructQK(kind string, m, n, k int, a []float64, lda int, tau []float64) blas64.General {
   552  	var sz int
   553  	switch kind {
   554  	case "QR":
   555  		sz = m
   556  	case "LQ", "RQ":
   557  		sz = n
   558  	}
   559  
   560  	q := blas64.General{
   561  		Rows:   sz,
   562  		Cols:   sz,
   563  		Stride: sz,
   564  		Data:   make([]float64, sz*sz),
   565  	}
   566  	for i := 0; i < sz; i++ {
   567  		q.Data[i*sz+i] = 1
   568  	}
   569  	qCopy := blas64.General{
   570  		Rows:   q.Rows,
   571  		Cols:   q.Cols,
   572  		Stride: q.Stride,
   573  		Data:   make([]float64, len(q.Data)),
   574  	}
   575  	for i := 0; i < k; i++ {
   576  		h := blas64.General{
   577  			Rows:   sz,
   578  			Cols:   sz,
   579  			Stride: sz,
   580  			Data:   make([]float64, sz*sz),
   581  		}
   582  		for j := 0; j < sz; j++ {
   583  			h.Data[j*sz+j] = 1
   584  		}
   585  		vVec := blas64.Vector{
   586  			Inc:  1,
   587  			Data: make([]float64, sz),
   588  		}
   589  		switch kind {
   590  		case "QR":
   591  			vVec.Data[i] = 1
   592  			for j := i + 1; j < sz; j++ {
   593  				vVec.Data[j] = a[lda*j+i]
   594  			}
   595  		case "LQ":
   596  			vVec.Data[i] = 1
   597  			for j := i + 1; j < sz; j++ {
   598  				vVec.Data[j] = a[i*lda+j]
   599  			}
   600  		case "RQ":
   601  			for j := 0; j < n-k+i; j++ {
   602  				vVec.Data[j] = a[(m-k+i)*lda+j]
   603  			}
   604  			vVec.Data[n-k+i] = 1
   605  		}
   606  		blas64.Ger(-tau[i], vVec, vVec, h)
   607  		copy(qCopy.Data, q.Data)
   608  		// Mulitply q by the new h
   609  		switch kind {
   610  		case "QR", "RQ":
   611  			blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, qCopy, h, 0, q)
   612  		case "LQ":
   613  			blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, h, qCopy, 0, q)
   614  		}
   615  	}
   616  	return q
   617  }
   618  
   619  // checkBidiagonal checks the bidiagonal decomposition from dlabrd and dgebd2.
   620  // The input to this function is the answer returned from the routines, stored
   621  // in a, d, e, tauP, and tauQ. The data of original A matrix (before
   622  // decomposition) is input in aCopy.
   623  //
   624  // checkBidiagonal constructs the V and U matrices, and from them constructs Q
   625  // and P. Using these constructions, it checks that Q^T * A * P and checks that
   626  // the result is bidiagonal.
   627  func checkBidiagonal(t *testing.T, m, n, nb int, a []float64, lda int, d, e, tauP, tauQ, aCopy []float64) {
   628  	// Check the answer.
   629  	// Construct V and U.
   630  	qMat := constructQPBidiagonal(lapack.ApplyQ, m, n, nb, a, lda, tauQ)
   631  	pMat := constructQPBidiagonal(lapack.ApplyP, m, n, nb, a, lda, tauP)
   632  
   633  	// Compute Q^T * A * P
   634  	aMat := blas64.General{
   635  		Rows:   m,
   636  		Cols:   n,
   637  		Stride: lda,
   638  		Data:   make([]float64, len(aCopy)),
   639  	}
   640  	copy(aMat.Data, aCopy)
   641  
   642  	tmp1 := blas64.General{
   643  		Rows:   m,
   644  		Cols:   n,
   645  		Stride: n,
   646  		Data:   make([]float64, m*n),
   647  	}
   648  	blas64.Gemm(blas.Trans, blas.NoTrans, 1, qMat, aMat, 0, tmp1)
   649  	tmp2 := blas64.General{
   650  		Rows:   m,
   651  		Cols:   n,
   652  		Stride: n,
   653  		Data:   make([]float64, m*n),
   654  	}
   655  	blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tmp1, pMat, 0, tmp2)
   656  
   657  	// Check that the first nb rows and cols of tm2 are upper bidiagonal
   658  	// if m >= n, and lower bidiagonal otherwise.
   659  	correctDiag := true
   660  	matchD := true
   661  	matchE := true
   662  	for i := 0; i < m; i++ {
   663  		for j := 0; j < n; j++ {
   664  			if i >= nb && j >= nb {
   665  				continue
   666  			}
   667  			v := tmp2.Data[i*tmp2.Stride+j]
   668  			if i == j {
   669  				if math.Abs(d[i]-v) > 1e-12 {
   670  					matchD = false
   671  				}
   672  				continue
   673  			}
   674  			if m >= n && i == j-1 {
   675  				if math.Abs(e[j-1]-v) > 1e-12 {
   676  					matchE = false
   677  				}
   678  				continue
   679  			}
   680  			if m < n && i-1 == j {
   681  				if math.Abs(e[i-1]-v) > 1e-12 {
   682  					matchE = false
   683  				}
   684  				continue
   685  			}
   686  			if math.Abs(v) > 1e-12 {
   687  				correctDiag = false
   688  			}
   689  		}
   690  	}
   691  	if !correctDiag {
   692  		t.Errorf("Updated A not bi-diagonal")
   693  	}
   694  	if !matchD {
   695  		fmt.Println("d = ", d)
   696  		t.Errorf("D Mismatch")
   697  	}
   698  	if !matchE {
   699  		t.Errorf("E mismatch")
   700  	}
   701  }
   702  
   703  // constructQPBidiagonal constructs Q or P from the Bidiagonal decomposition
   704  // computed by dlabrd and bgebd2.
   705  func constructQPBidiagonal(vect lapack.DecompUpdate, m, n, nb int, a []float64, lda int, tau []float64) blas64.General {
   706  	sz := n
   707  	if vect == lapack.ApplyQ {
   708  		sz = m
   709  	}
   710  
   711  	var ldv int
   712  	var v blas64.General
   713  	if vect == lapack.ApplyQ {
   714  		ldv = nb
   715  		v = blas64.General{
   716  			Rows:   m,
   717  			Cols:   nb,
   718  			Stride: ldv,
   719  			Data:   make([]float64, m*ldv),
   720  		}
   721  	} else {
   722  		ldv = n
   723  		v = blas64.General{
   724  			Rows:   nb,
   725  			Cols:   n,
   726  			Stride: ldv,
   727  			Data:   make([]float64, m*ldv),
   728  		}
   729  	}
   730  
   731  	if vect == lapack.ApplyQ {
   732  		if m >= n {
   733  			for i := 0; i < m; i++ {
   734  				for j := 0; j <= min(nb-1, i); j++ {
   735  					if i == j {
   736  						v.Data[i*ldv+j] = 1
   737  						continue
   738  					}
   739  					v.Data[i*ldv+j] = a[i*lda+j]
   740  				}
   741  			}
   742  		} else {
   743  			for i := 1; i < m; i++ {
   744  				for j := 0; j <= min(nb-1, i-1); j++ {
   745  					if i-1 == j {
   746  						v.Data[i*ldv+j] = 1
   747  						continue
   748  					}
   749  					v.Data[i*ldv+j] = a[i*lda+j]
   750  				}
   751  			}
   752  		}
   753  	} else {
   754  		if m < n {
   755  			for i := 0; i < nb; i++ {
   756  				for j := i; j < n; j++ {
   757  					if i == j {
   758  						v.Data[i*ldv+j] = 1
   759  						continue
   760  					}
   761  					v.Data[i*ldv+j] = a[i*lda+j]
   762  				}
   763  			}
   764  		} else {
   765  			for i := 0; i < nb; i++ {
   766  				for j := i + 1; j < n; j++ {
   767  					if j-1 == i {
   768  						v.Data[i*ldv+j] = 1
   769  						continue
   770  					}
   771  					v.Data[i*ldv+j] = a[i*lda+j]
   772  				}
   773  			}
   774  		}
   775  	}
   776  
   777  	// The variable name is a computation of Q, but the algorithm is mostly the
   778  	// same for computing P (just with different data).
   779  	qMat := blas64.General{
   780  		Rows:   sz,
   781  		Cols:   sz,
   782  		Stride: sz,
   783  		Data:   make([]float64, sz*sz),
   784  	}
   785  	hMat := blas64.General{
   786  		Rows:   sz,
   787  		Cols:   sz,
   788  		Stride: sz,
   789  		Data:   make([]float64, sz*sz),
   790  	}
   791  	// set Q to I
   792  	for i := 0; i < sz; i++ {
   793  		qMat.Data[i*qMat.Stride+i] = 1
   794  	}
   795  	for i := 0; i < nb; i++ {
   796  		qCopy := blas64.General{Rows: qMat.Rows, Cols: qMat.Cols, Stride: qMat.Stride, Data: make([]float64, len(qMat.Data))}
   797  		copy(qCopy.Data, qMat.Data)
   798  
   799  		// Set g and h to I
   800  		for i := 0; i < sz; i++ {
   801  			for j := 0; j < sz; j++ {
   802  				if i == j {
   803  					hMat.Data[i*sz+j] = 1
   804  				} else {
   805  					hMat.Data[i*sz+j] = 0
   806  				}
   807  			}
   808  		}
   809  		var vi blas64.Vector
   810  		// H -= tauQ[i] * v[i] * v[i]^t
   811  		if vect == lapack.ApplyQ {
   812  			vi = blas64.Vector{
   813  				Inc:  v.Stride,
   814  				Data: v.Data[i:],
   815  			}
   816  		} else {
   817  			vi = blas64.Vector{
   818  				Inc:  1,
   819  				Data: v.Data[i*v.Stride:],
   820  			}
   821  		}
   822  		blas64.Ger(-tau[i], vi, vi, hMat)
   823  		// Q = Q * G[1]
   824  		blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, qCopy, hMat, 0, qMat)
   825  	}
   826  	return qMat
   827  }
   828  
   829  // printRowise prints the matrix with one row per line. This is useful for debugging.
   830  // If beyond is true, it prints beyond the final column to lda. If false, only
   831  // the columns are printed.
   832  func printRowise(a []float64, m, n, lda int, beyond bool) {
   833  	for i := 0; i < m; i++ {
   834  		end := n
   835  		if beyond {
   836  			end = lda
   837  		}
   838  		fmt.Println(a[i*lda : i*lda+end])
   839  	}
   840  }
   841  
   842  // isOrthonormal checks that a general matrix is orthonormal.
   843  func isOrthonormal(q blas64.General) bool {
   844  	n := q.Rows
   845  	for i := 0; i < n; i++ {
   846  		for j := i; j < n; j++ {
   847  			dot := blas64.Dot(n,
   848  				blas64.Vector{Inc: 1, Data: q.Data[i*q.Stride:]},
   849  				blas64.Vector{Inc: 1, Data: q.Data[j*q.Stride:]},
   850  			)
   851  			if math.IsNaN(dot) {
   852  				return false
   853  			}
   854  			if i == j {
   855  				if math.Abs(dot-1) > 1e-10 {
   856  					return false
   857  				}
   858  			} else {
   859  				if math.Abs(dot) > 1e-10 {
   860  					return false
   861  				}
   862  			}
   863  		}
   864  	}
   865  	return true
   866  }
   867  
   868  // copyMatrix copies an m×n matrix src of stride n into an m×n matrix dst of stride ld.
   869  func copyMatrix(m, n int, dst []float64, ld int, src []float64) {
   870  	for i := 0; i < m; i++ {
   871  		copy(dst[i*ld:i*ld+n], src[i*n:i*n+n])
   872  	}
   873  }
   874  
   875  func copyGeneral(dst, src blas64.General) {
   876  	r := min(dst.Rows, src.Rows)
   877  	c := min(dst.Cols, src.Cols)
   878  	for i := 0; i < r; i++ {
   879  		copy(dst.Data[i*dst.Stride:i*dst.Stride+c], src.Data[i*src.Stride:i*src.Stride+c])
   880  	}
   881  }
   882  
   883  // cloneGeneral allocates and returns an exact copy of the given general matrix.
   884  func cloneGeneral(a blas64.General) blas64.General {
   885  	c := a
   886  	c.Data = make([]float64, len(a.Data))
   887  	copy(c.Data, a.Data)
   888  	return c
   889  }
   890  
   891  // equalApprox returns whether the matrices A and B of order n are approximately
   892  // equal within given tolerance.
   893  func equalApprox(m, n int, a []float64, lda int, b []float64, tol float64) bool {
   894  	for i := 0; i < m; i++ {
   895  		for j := 0; j < n; j++ {
   896  			diff := a[i*lda+j] - b[i*n+j]
   897  			if math.IsNaN(diff) || math.Abs(diff) > tol {
   898  				return false
   899  			}
   900  		}
   901  	}
   902  	return true
   903  }
   904  
   905  // equalApproxGeneral returns whether the general matrices a and b are
   906  // approximately equal within given tolerance.
   907  func equalApproxGeneral(a, b blas64.General, tol float64) bool {
   908  	if a.Rows != b.Rows || a.Cols != b.Cols {
   909  		panic("bad input")
   910  	}
   911  	for i := 0; i < a.Rows; i++ {
   912  		for j := 0; j < a.Cols; j++ {
   913  			diff := a.Data[i*a.Stride+j] - b.Data[i*b.Stride+j]
   914  			if math.IsNaN(diff) || math.Abs(diff) > tol {
   915  				return false
   916  			}
   917  		}
   918  	}
   919  	return true
   920  }
   921  
   922  // equalApproxTriangular returns whether the triangular matrices A and B of
   923  // order n are approximately equal within given tolerance.
   924  func equalApproxTriangular(upper bool, n int, a []float64, lda int, b []float64, tol float64) bool {
   925  	if upper {
   926  		for i := 0; i < n; i++ {
   927  			for j := i; j < n; j++ {
   928  				diff := a[i*lda+j] - b[i*n+j]
   929  				if math.IsNaN(diff) || math.Abs(diff) > tol {
   930  					return false
   931  				}
   932  			}
   933  		}
   934  		return true
   935  	}
   936  	for i := 0; i < n; i++ {
   937  		for j := 0; j <= i; j++ {
   938  			diff := a[i*lda+j] - b[i*n+j]
   939  			if math.IsNaN(diff) || math.Abs(diff) > tol {
   940  				return false
   941  			}
   942  		}
   943  	}
   944  	return true
   945  }
   946  
   947  // eye returns an identity matrix of given order and stride.
   948  func eye(n, stride int) blas64.General {
   949  	ans := nanGeneral(n, n, stride)
   950  	for i := 0; i < n; i++ {
   951  		for j := 0; j < n; j++ {
   952  			ans.Data[i*ans.Stride+j] = 0
   953  		}
   954  		ans.Data[i*ans.Stride+i] = 1
   955  	}
   956  	return ans
   957  }
   958  
   959  // zeros returns an m×n matrix with given stride filled with zeros.
   960  func zeros(m, n, stride int) blas64.General {
   961  	a := nanGeneral(m, n, stride)
   962  	for i := 0; i < m; i++ {
   963  		for j := 0; j < n; j++ {
   964  			a.Data[i*a.Stride+j] = 0
   965  		}
   966  	}
   967  	return a
   968  }
   969  
   970  // extract2x2Block returns the elements of T at [0,0], [0,1], [1,0], and [1,1].
   971  func extract2x2Block(t []float64, ldt int) (a, b, c, d float64) {
   972  	return t[0], t[1], t[ldt], t[ldt+1]
   973  }
   974  
   975  // isSchurCanonical returns whether the 2×2 matrix [a b; c d] is in Schur
   976  // canonical form.
   977  func isSchurCanonical(a, b, c, d float64) bool {
   978  	return c == 0 || (a == d && math.Signbit(b) != math.Signbit(c))
   979  }
   980  
   981  // isSchurCanonicalGeneral returns whether T is block upper triangular with 1×1
   982  // and 2×2 diagonal blocks, each 2×2 block in Schur canonical form. The function
   983  // checks only along the diagonal and the first subdiagonal, otherwise the lower
   984  // triangle is not accessed.
   985  func isSchurCanonicalGeneral(t blas64.General) bool {
   986  	if t.Rows != t.Cols {
   987  		panic("invalid matrix")
   988  	}
   989  	for i := 0; i < t.Rows-1; {
   990  		if t.Data[(i+1)*t.Stride+i] == 0 {
   991  			// 1×1 block.
   992  			i++
   993  			continue
   994  		}
   995  		// 2×2 block.
   996  		a, b, c, d := extract2x2Block(t.Data[i*t.Stride+i:], t.Stride)
   997  		if !isSchurCanonical(a, b, c, d) {
   998  			return false
   999  		}
  1000  		i += 2
  1001  	}
  1002  	return true
  1003  }
  1004  
  1005  // schurBlockEigenvalues returns the two eigenvalues of the 2×2 matrix [a b; c d]
  1006  // that must be in Schur canonical form.
  1007  func schurBlockEigenvalues(a, b, c, d float64) (ev1, ev2 complex128) {
  1008  	if !isSchurCanonical(a, b, c, d) {
  1009  		panic("block not in Schur canonical form")
  1010  	}
  1011  	if c == 0 {
  1012  		return complex(a, 0), complex(d, 0)
  1013  	}
  1014  	im := math.Sqrt(-b * c)
  1015  	return complex(a, im), complex(a, -im)
  1016  }
  1017  
  1018  // schurBlockSize returns the size of the diagonal block at i-th row in the
  1019  // upper quasi-triangular matrix t in Schur canonical form, and whether i points
  1020  // to the first row of the block. For zero-sized matrices the function returns 0
  1021  // and true.
  1022  func schurBlockSize(t blas64.General, i int) (size int, first bool) {
  1023  	if t.Rows != t.Cols {
  1024  		panic("matrix not square")
  1025  	}
  1026  	if t.Rows == 0 {
  1027  		return 0, true
  1028  	}
  1029  	if i < 0 || t.Rows <= i {
  1030  		panic("index out of range")
  1031  	}
  1032  
  1033  	first = true
  1034  	if i > 0 && t.Data[i*t.Stride+i-1] != 0 {
  1035  		// There is a non-zero element to the left, therefore i must
  1036  		// point to the second row in a 2×2 diagonal block.
  1037  		first = false
  1038  		i--
  1039  	}
  1040  	size = 1
  1041  	if i+1 < t.Rows && t.Data[(i+1)*t.Stride+i] != 0 {
  1042  		// There is a non-zero element below, this must be a 2×2
  1043  		// diagonal block.
  1044  		size = 2
  1045  	}
  1046  	return size, first
  1047  }
  1048  
  1049  // containsComplex returns whether z is approximately equal to one of the complex
  1050  // numbers in v. If z is found, its index in v will be also returned.
  1051  func containsComplex(v []complex128, z complex128, tol float64) (found bool, index int) {
  1052  	for i := range v {
  1053  		if cmplx.Abs(v[i]-z) < tol {
  1054  			return true, i
  1055  		}
  1056  	}
  1057  	return false, -1
  1058  }
  1059  
  1060  // isAllNaN returns whether x contains only NaN values.
  1061  func isAllNaN(x []float64) bool {
  1062  	for _, v := range x {
  1063  		if !math.IsNaN(v) {
  1064  			return false
  1065  		}
  1066  	}
  1067  	return true
  1068  }
  1069  
  1070  // isUpperHessenberg returns whether h contains only zeros below the
  1071  // subdiagonal.
  1072  func isUpperHessenberg(h blas64.General) bool {
  1073  	if h.Rows != h.Cols {
  1074  		panic("matrix not square")
  1075  	}
  1076  	n := h.Rows
  1077  	for i := 0; i < n; i++ {
  1078  		for j := 0; j < n; j++ {
  1079  			if i > j+1 && h.Data[i*h.Stride+j] != 0 {
  1080  				return false
  1081  			}
  1082  		}
  1083  	}
  1084  	return true
  1085  }
  1086  
  1087  // isUpperTriangular returns whether a contains only zeros below the diagonal.
  1088  func isUpperTriangular(a blas64.General) bool {
  1089  	n := a.Rows
  1090  	for i := 1; i < n; i++ {
  1091  		for j := 0; j < i; j++ {
  1092  			if a.Data[i*a.Stride+j] != 0 {
  1093  				return false
  1094  			}
  1095  		}
  1096  	}
  1097  	return true
  1098  }
  1099  
  1100  // unbalancedSparseGeneral returns an m×n dense matrix with a random sparse
  1101  // structure consisting of nz nonzero elements. The matrix will be unbalanced by
  1102  // multiplying each element randomly by its row or column index.
  1103  func unbalancedSparseGeneral(m, n, stride int, nonzeros int, rnd *rand.Rand) blas64.General {
  1104  	a := zeros(m, n, stride)
  1105  	for k := 0; k < nonzeros; k++ {
  1106  		i := rnd.Intn(n)
  1107  		j := rnd.Intn(n)
  1108  		if rnd.Float64() < 0.5 {
  1109  			a.Data[i*stride+j] = float64(i+1) * rnd.NormFloat64()
  1110  		} else {
  1111  			a.Data[i*stride+j] = float64(j+1) * rnd.NormFloat64()
  1112  		}
  1113  	}
  1114  	return a
  1115  }
  1116  
  1117  // columnOf returns a copy of the j-th column of a.
  1118  func columnOf(a blas64.General, j int) []float64 {
  1119  	if j < 0 || a.Cols <= j {
  1120  		panic("bad column index")
  1121  	}
  1122  	col := make([]float64, a.Rows)
  1123  	for i := range col {
  1124  		col[i] = a.Data[i*a.Stride+j]
  1125  	}
  1126  	return col
  1127  }
  1128  
  1129  // isRightEigenvectorOf returns whether the vector xRe+i*xIm, where i is the
  1130  // imaginary unit, is the right eigenvector of A corresponding to the eigenvalue
  1131  // lambda.
  1132  //
  1133  // A right eigenvector corresponding to a complex eigenvalue λ is a complex
  1134  // non-zero vector x such that
  1135  //  A x = λ x.
  1136  func isRightEigenvectorOf(a blas64.General, xRe, xIm []float64, lambda complex128, tol float64) bool {
  1137  	if a.Rows != a.Cols {
  1138  		panic("matrix not square")
  1139  	}
  1140  
  1141  	if imag(lambda) != 0 && xIm == nil {
  1142  		// Complex eigenvalue of a real matrix cannot have a real
  1143  		// eigenvector.
  1144  		return false
  1145  	}
  1146  
  1147  	n := a.Rows
  1148  
  1149  	// Compute A real(x) and store the result into xReAns.
  1150  	xReAns := make([]float64, n)
  1151  	blas64.Gemv(blas.NoTrans, 1, a, blas64.Vector{1, xRe}, 0, blas64.Vector{1, xReAns})
  1152  
  1153  	if imag(lambda) == 0 && xIm == nil {
  1154  		// Real eigenvalue and eigenvector.
  1155  
  1156  		// Compute λx and store the result into lambdax.
  1157  		lambdax := make([]float64, n)
  1158  		floats.AddScaled(lambdax, real(lambda), xRe)
  1159  
  1160  		if floats.Distance(xReAns, lambdax, math.Inf(1)) > tol {
  1161  			return false
  1162  		}
  1163  		return true
  1164  	}
  1165  
  1166  	// Complex eigenvector, and real or complex eigenvalue.
  1167  
  1168  	// Compute A imag(x) and store the result into xImAns.
  1169  	xImAns := make([]float64, n)
  1170  	blas64.Gemv(blas.NoTrans, 1, a, blas64.Vector{1, xIm}, 0, blas64.Vector{1, xImAns})
  1171  
  1172  	// Compute λx and store the result into lambdax.
  1173  	lambdax := make([]complex128, n)
  1174  	for i := range lambdax {
  1175  		lambdax[i] = lambda * complex(xRe[i], xIm[i])
  1176  	}
  1177  
  1178  	for i, v := range lambdax {
  1179  		ax := complex(xReAns[i], xImAns[i])
  1180  		if cmplx.Abs(v-ax) > tol {
  1181  			return false
  1182  		}
  1183  	}
  1184  	return true
  1185  }
  1186  
  1187  // isLeftEigenvectorOf returns whether the vector yRe+i*yIm, where i is the
  1188  // imaginary unit, is the left eigenvector of A corresponding to the eigenvalue
  1189  // lambda.
  1190  //
  1191  // A left eigenvector corresponding to a complex eigenvalue λ is a complex
  1192  // non-zero vector y such that
  1193  //  y^H A = λ y^H,
  1194  // which is equivalent for real A to
  1195  //  A^T y = conj(λ) y,
  1196  func isLeftEigenvectorOf(a blas64.General, yRe, yIm []float64, lambda complex128, tol float64) bool {
  1197  	if a.Rows != a.Cols {
  1198  		panic("matrix not square")
  1199  	}
  1200  
  1201  	if imag(lambda) != 0 && yIm == nil {
  1202  		// Complex eigenvalue of a real matrix cannot have a real
  1203  		// eigenvector.
  1204  		return false
  1205  	}
  1206  
  1207  	n := a.Rows
  1208  
  1209  	// Compute A^T real(y) and store the result into yReAns.
  1210  	yReAns := make([]float64, n)
  1211  	blas64.Gemv(blas.Trans, 1, a, blas64.Vector{1, yRe}, 0, blas64.Vector{1, yReAns})
  1212  
  1213  	if imag(lambda) == 0 && yIm == nil {
  1214  		// Real eigenvalue and eigenvector.
  1215  
  1216  		// Compute λy and store the result into lambday.
  1217  		lambday := make([]float64, n)
  1218  		floats.AddScaled(lambday, real(lambda), yRe)
  1219  
  1220  		if floats.Distance(yReAns, lambday, math.Inf(1)) > tol {
  1221  			return false
  1222  		}
  1223  		return true
  1224  	}
  1225  
  1226  	// Complex eigenvector, and real or complex eigenvalue.
  1227  
  1228  	// Compute A^T imag(y) and store the result into yImAns.
  1229  	yImAns := make([]float64, n)
  1230  	blas64.Gemv(blas.Trans, 1, a, blas64.Vector{1, yIm}, 0, blas64.Vector{1, yImAns})
  1231  
  1232  	// Compute conj(λ)y and store the result into lambday.
  1233  	lambda = cmplx.Conj(lambda)
  1234  	lambday := make([]complex128, n)
  1235  	for i := range lambday {
  1236  		lambday[i] = lambda * complex(yRe[i], yIm[i])
  1237  	}
  1238  
  1239  	for i, v := range lambday {
  1240  		ay := complex(yReAns[i], yImAns[i])
  1241  		if cmplx.Abs(v-ay) > tol {
  1242  			return false
  1243  		}
  1244  	}
  1245  	return true
  1246  }
  1247  
  1248  // rootsOfUnity returns the n complex numbers whose n-th power is equal to 1.
  1249  func rootsOfUnity(n int) []complex128 {
  1250  	w := make([]complex128, n)
  1251  	for i := 0; i < n; i++ {
  1252  		angle := math.Pi * float64(2*i) / float64(n)
  1253  		w[i] = complex(math.Cos(angle), math.Sin(angle))
  1254  	}
  1255  	return w
  1256  }
  1257  
  1258  // randomOrthogonal returns an n×n random orthogonal matrix.
  1259  func randomOrthogonal(n int, rnd *rand.Rand) blas64.General {
  1260  	q := eye(n, n)
  1261  	x := make([]float64, n)
  1262  	v := make([]float64, n)
  1263  	for j := 0; j < n-1; j++ {
  1264  		// x represents the j-th column of a random matrix.
  1265  		for i := 0; i < j; i++ {
  1266  			x[i] = 0
  1267  		}
  1268  		for i := j; i < n; i++ {
  1269  			x[i] = rnd.NormFloat64()
  1270  		}
  1271  		// Compute v that represents the elementary reflector that
  1272  		// annihilates the subdiagonal elements of x.
  1273  		reflector(v, x, j)
  1274  		// Compute Q * H_j and store the result into Q.
  1275  		applyReflector(q, q, v)
  1276  	}
  1277  	if !isOrthonormal(q) {
  1278  		panic("Q not orthogonal")
  1279  	}
  1280  	return q
  1281  }
  1282  
  1283  // reflector generates a Householder reflector v that zeros out subdiagonal
  1284  // entries in the j-th column of a matrix.
  1285  func reflector(v, col []float64, j int) {
  1286  	n := len(col)
  1287  	if len(v) != n {
  1288  		panic("slice length mismatch")
  1289  	}
  1290  	if j < 0 || n <= j {
  1291  		panic("invalid column index")
  1292  	}
  1293  
  1294  	for i := range v {
  1295  		v[i] = 0
  1296  	}
  1297  	if j == n-1 {
  1298  		return
  1299  	}
  1300  	s := floats.Norm(col[j:], 2)
  1301  	if s == 0 {
  1302  		return
  1303  	}
  1304  	v[j] = col[j] + math.Copysign(s, col[j])
  1305  	copy(v[j+1:], col[j+1:])
  1306  	s = floats.Norm(v[j:], 2)
  1307  	floats.Scale(1/s, v[j:])
  1308  }
  1309  
  1310  // applyReflector computes Q*H where H is a Householder matrix represented by
  1311  // the Householder reflector v.
  1312  func applyReflector(qh blas64.General, q blas64.General, v []float64) {
  1313  	n := len(v)
  1314  	if qh.Rows != n || qh.Cols != n {
  1315  		panic("bad size of qh")
  1316  	}
  1317  	if q.Rows != n || q.Cols != n {
  1318  		panic("bad size of q")
  1319  	}
  1320  	qv := make([]float64, n)
  1321  	blas64.Gemv(blas.NoTrans, 1, q, blas64.Vector{1, v}, 0, blas64.Vector{1, qv})
  1322  	for i := 0; i < n; i++ {
  1323  		for j := 0; j < n; j++ {
  1324  			qh.Data[i*qh.Stride+j] = q.Data[i*q.Stride+j]
  1325  		}
  1326  	}
  1327  	for i := 0; i < n; i++ {
  1328  		for j := 0; j < n; j++ {
  1329  			qh.Data[i*qh.Stride+j] -= 2 * qv[i] * v[j]
  1330  		}
  1331  	}
  1332  	var norm2 float64
  1333  	for _, vi := range v {
  1334  		norm2 += vi * vi
  1335  	}
  1336  	norm2inv := 1 / norm2
  1337  	for i := 0; i < n; i++ {
  1338  		for j := 0; j < n; j++ {
  1339  			qh.Data[i*qh.Stride+j] *= norm2inv
  1340  		}
  1341  	}
  1342  }
  1343  
  1344  // constructGSVDresults returns the matrices [ 0 R ], D1 and D2 described
  1345  // in the documentation of Dtgsja and Dggsvd3, and the result matrix in
  1346  // the documentation for Dggsvp3.
  1347  func constructGSVDresults(n, p, m, k, l int, a, b blas64.General, alpha, beta []float64) (zeroR, d1, d2 blas64.General) {
  1348  	// [ 0 R ]
  1349  	zeroR = zeros(k+l, n, n)
  1350  	dst := zeroR
  1351  	dst.Rows = min(m, k+l)
  1352  	dst.Cols = k + l
  1353  	dst.Data = zeroR.Data[n-k-l:]
  1354  	src := a
  1355  	src.Rows = min(m, k+l)
  1356  	src.Cols = k + l
  1357  	src.Data = a.Data[n-k-l:]
  1358  	copyGeneral(dst, src)
  1359  	if m < k+l {
  1360  		// [ 0 R ]
  1361  		dst.Rows = k + l - m
  1362  		dst.Cols = k + l - m
  1363  		dst.Data = zeroR.Data[m*zeroR.Stride+n-(k+l-m):]
  1364  		src = b
  1365  		src.Rows = k + l - m
  1366  		src.Cols = k + l - m
  1367  		src.Data = b.Data[(m-k)*b.Stride+n+m-k-l:]
  1368  		copyGeneral(dst, src)
  1369  	}
  1370  
  1371  	// D1
  1372  	d1 = zeros(m, k+l, k+l)
  1373  	for i := 0; i < k; i++ {
  1374  		d1.Data[i*d1.Stride+i] = 1
  1375  	}
  1376  	for i := k; i < min(m, k+l); i++ {
  1377  		d1.Data[i*d1.Stride+i] = alpha[i]
  1378  	}
  1379  
  1380  	// D2
  1381  	d2 = zeros(p, k+l, k+l)
  1382  	for i := 0; i < min(l, m-k); i++ {
  1383  		d2.Data[i*d2.Stride+i+k] = beta[k+i]
  1384  	}
  1385  	for i := m - k; i < l; i++ {
  1386  		d2.Data[i*d2.Stride+i+k] = 1
  1387  	}
  1388  
  1389  	return zeroR, d1, d2
  1390  }
  1391  
  1392  func constructGSVPresults(n, p, m, k, l int, a, b blas64.General) (zeroA, zeroB blas64.General) {
  1393  	zeroA = zeros(m, n, n)
  1394  	dst := zeroA
  1395  	dst.Rows = min(m, k+l)
  1396  	dst.Cols = k + l
  1397  	dst.Data = zeroA.Data[n-k-l:]
  1398  	src := a
  1399  	dst.Rows = min(m, k+l)
  1400  	src.Cols = k + l
  1401  	src.Data = a.Data[n-k-l:]
  1402  	copyGeneral(dst, src)
  1403  
  1404  	zeroB = zeros(p, n, n)
  1405  	dst = zeroB
  1406  	dst.Rows = l
  1407  	dst.Cols = l
  1408  	dst.Data = zeroB.Data[n-l:]
  1409  	src = b
  1410  	dst.Rows = l
  1411  	src.Cols = l
  1412  	src.Data = b.Data[n-l:]
  1413  	copyGeneral(dst, src)
  1414  
  1415  	return zeroA, zeroB
  1416  }