gonum.org/v1/gonum@v0.14.0/lapack/testlapack/matgen.go (about)

     1  // Copyright ©2017 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  	"math"
     9  
    10  	"golang.org/x/exp/rand"
    11  
    12  	"gonum.org/v1/gonum/blas"
    13  	"gonum.org/v1/gonum/blas/blas64"
    14  	"gonum.org/v1/gonum/floats"
    15  )
    16  
    17  // Dlatm1 computes the entries of dst as specified by mode, cond and rsign.
    18  //
    19  // mode describes how dst will be computed:
    20  //
    21  //	|mode| == 1: dst[0] = 1 and dst[1:n] = 1/cond
    22  //	|mode| == 2: dst[:n-1] = 1/cond and dst[n-1] = 1
    23  //	|mode| == 3: dst[i] = cond^{-i/(n-1)}, i=0,...,n-1
    24  //	|mode| == 4: dst[i] = 1 - i*(1-1/cond)/(n-1)
    25  //	|mode| == 5: dst[i] = random number in the range (1/cond, 1) such that
    26  //	                  their logarithms are uniformly distributed
    27  //	|mode| == 6: dst[i] = random number from the distribution given by dist
    28  //
    29  // If mode is negative, the order of the elements of dst will be reversed.
    30  // For other values of mode Dlatm1 will panic.
    31  //
    32  // If rsign is true and mode is not ±6, each entry of dst will be multiplied by 1
    33  // or -1 with probability 0.5
    34  //
    35  // dist specifies the type of distribution to be used when mode == ±6:
    36  //
    37  //	dist == 1: Uniform[0,1)
    38  //	dist == 2: Uniform[-1,1)
    39  //	dist == 3: Normal(0,1)
    40  //
    41  // For other values of dist Dlatm1 will panic.
    42  //
    43  // rnd is used as a source of random numbers.
    44  func Dlatm1(dst []float64, mode int, cond float64, rsign bool, dist int, rnd *rand.Rand) {
    45  	amode := mode
    46  	if amode < 0 {
    47  		amode = -amode
    48  	}
    49  	if amode < 1 || 6 < amode {
    50  		panic("testlapack: invalid mode")
    51  	}
    52  	if cond < 1 {
    53  		panic("testlapack: cond < 1")
    54  	}
    55  	if amode == 6 && (dist < 1 || 3 < dist) {
    56  		panic("testlapack: invalid dist")
    57  	}
    58  
    59  	n := len(dst)
    60  	if n == 0 {
    61  		return
    62  	}
    63  
    64  	switch amode {
    65  	case 1:
    66  		dst[0] = 1
    67  		for i := 1; i < n; i++ {
    68  			dst[i] = 1 / cond
    69  		}
    70  	case 2:
    71  		for i := 0; i < n-1; i++ {
    72  			dst[i] = 1
    73  		}
    74  		dst[n-1] = 1 / cond
    75  	case 3:
    76  		dst[0] = 1
    77  		if n > 1 {
    78  			alpha := math.Pow(cond, -1/float64(n-1))
    79  			for i := 1; i < n; i++ {
    80  				dst[i] = math.Pow(alpha, float64(i))
    81  			}
    82  		}
    83  	case 4:
    84  		dst[0] = 1
    85  		if n > 1 {
    86  			condInv := 1 / cond
    87  			alpha := (1 - condInv) / float64(n-1)
    88  			for i := 1; i < n; i++ {
    89  				dst[i] = float64(n-i-1)*alpha + condInv
    90  			}
    91  		}
    92  	case 5:
    93  		alpha := math.Log(1 / cond)
    94  		for i := range dst {
    95  			dst[i] = math.Exp(alpha * rnd.Float64())
    96  		}
    97  	case 6:
    98  		switch dist {
    99  		case 1:
   100  			for i := range dst {
   101  				dst[i] = rnd.Float64()
   102  			}
   103  		case 2:
   104  			for i := range dst {
   105  				dst[i] = 2*rnd.Float64() - 1
   106  			}
   107  		case 3:
   108  			for i := range dst {
   109  				dst[i] = rnd.NormFloat64()
   110  			}
   111  		}
   112  	}
   113  
   114  	if rsign && amode != 6 {
   115  		for i, v := range dst {
   116  			if rnd.Float64() < 0.5 {
   117  				dst[i] = -v
   118  			}
   119  		}
   120  	}
   121  
   122  	if mode < 0 {
   123  		for i := 0; i < n/2; i++ {
   124  			dst[i], dst[n-i-1] = dst[n-i-1], dst[i]
   125  		}
   126  	}
   127  }
   128  
   129  // Dlagsy generates an n×n symmetric matrix A, by pre- and post- multiplying a
   130  // real diagonal matrix D with a random orthogonal matrix:
   131  //
   132  //	A = U * D * Uᵀ.
   133  //
   134  // work must have length at least 2*n, otherwise Dlagsy will panic.
   135  //
   136  // The parameter k is unused but it must satisfy
   137  //
   138  //	0 <= k <= n-1.
   139  func Dlagsy(n, k int, d []float64, a []float64, lda int, rnd *rand.Rand, work []float64) {
   140  	checkMatrix(n, n, a, lda)
   141  	if k < 0 || max(0, n-1) < k {
   142  		panic("testlapack: invalid value of k")
   143  	}
   144  	if len(d) != n {
   145  		panic("testlapack: bad length of d")
   146  	}
   147  	if len(work) < 2*n {
   148  		panic("testlapack: insufficient work length")
   149  	}
   150  
   151  	// Initialize lower triangle of A to diagonal matrix.
   152  	for i := 1; i < n; i++ {
   153  		for j := 0; j < i; j++ {
   154  			a[i*lda+j] = 0
   155  		}
   156  	}
   157  	for i := 0; i < n; i++ {
   158  		a[i*lda+i] = d[i]
   159  	}
   160  
   161  	bi := blas64.Implementation()
   162  
   163  	// Generate lower triangle of symmetric matrix.
   164  	for i := n - 2; i >= 0; i-- {
   165  		for j := 0; j < n-i; j++ {
   166  			work[j] = rnd.NormFloat64()
   167  		}
   168  		wn := bi.Dnrm2(n-i, work[:n-i], 1)
   169  		wa := math.Copysign(wn, work[0])
   170  		var tau float64
   171  		if wn != 0 {
   172  			wb := work[0] + wa
   173  			bi.Dscal(n-i-1, 1/wb, work[1:n-i], 1)
   174  			work[0] = 1
   175  			tau = wb / wa
   176  		}
   177  
   178  		// Apply random reflection to A[i:n,i:n] from the left and the
   179  		// right.
   180  		//
   181  		// Compute y := tau * A * u.
   182  		bi.Dsymv(blas.Lower, n-i, tau, a[i*lda+i:], lda, work[:n-i], 1, 0, work[n:2*n-i], 1)
   183  
   184  		// Compute v := y - 1/2 * tau * ( y, u ) * u.
   185  		alpha := -0.5 * tau * bi.Ddot(n-i, work[n:2*n-i], 1, work[:n-i], 1)
   186  		bi.Daxpy(n-i, alpha, work[:n-i], 1, work[n:2*n-i], 1)
   187  
   188  		// Apply the transformation as a rank-2 update to A[i:n,i:n].
   189  		bi.Dsyr2(blas.Lower, n-i, -1, work[:n-i], 1, work[n:2*n-i], 1, a[i*lda+i:], lda)
   190  	}
   191  
   192  	// Store full symmetric matrix.
   193  	for i := 1; i < n; i++ {
   194  		for j := 0; j < i; j++ {
   195  			a[j*lda+i] = a[i*lda+j]
   196  		}
   197  	}
   198  }
   199  
   200  // Dlagge generates a real general m×n matrix A, by pre- and post-multiplying
   201  // a real diagonal matrix D with random orthogonal matrices:
   202  //
   203  //	A = U*D*V.
   204  //
   205  // d must have length min(m,n), and work must have length m+n, otherwise Dlagge
   206  // will panic.
   207  //
   208  // The parameters ku and kl are unused but they must satisfy
   209  //
   210  //	0 <= kl <= m-1,
   211  //	0 <= ku <= n-1.
   212  func Dlagge(m, n, kl, ku int, d []float64, a []float64, lda int, rnd *rand.Rand, work []float64) {
   213  	checkMatrix(m, n, a, lda)
   214  	if kl < 0 || max(0, m-1) < kl {
   215  		panic("testlapack: invalid value of kl")
   216  	}
   217  	if ku < 0 || max(0, n-1) < ku {
   218  		panic("testlapack: invalid value of ku")
   219  	}
   220  	if len(d) != min(m, n) {
   221  		panic("testlapack: bad length of d")
   222  	}
   223  	if len(work) < m+n {
   224  		panic("testlapack: insufficient work length")
   225  	}
   226  
   227  	// Initialize A to diagonal matrix.
   228  	for i := 0; i < m; i++ {
   229  		for j := 0; j < n; j++ {
   230  			a[i*lda+j] = 0
   231  		}
   232  	}
   233  	for i := 0; i < min(m, n); i++ {
   234  		a[i*lda+i] = d[i]
   235  	}
   236  
   237  	// Quick exit if the user wants a diagonal matrix.
   238  	// if kl == 0 && ku == 0 {
   239  	// 	return
   240  	// }
   241  
   242  	bi := blas64.Implementation()
   243  
   244  	// Pre- and post-multiply A by random orthogonal matrices.
   245  	for i := min(m, n) - 1; i >= 0; i-- {
   246  		if i < m-1 {
   247  			for j := 0; j < m-i; j++ {
   248  				work[j] = rnd.NormFloat64()
   249  			}
   250  			wn := bi.Dnrm2(m-i, work[:m-i], 1)
   251  			wa := math.Copysign(wn, work[0])
   252  			var tau float64
   253  			if wn != 0 {
   254  				wb := work[0] + wa
   255  				bi.Dscal(m-i-1, 1/wb, work[1:m-i], 1)
   256  				work[0] = 1
   257  				tau = wb / wa
   258  			}
   259  
   260  			// Multiply A[i:m,i:n] by random reflection from the left.
   261  			bi.Dgemv(blas.Trans, m-i, n-i,
   262  				1, a[i*lda+i:], lda, work[:m-i], 1,
   263  				0, work[m:m+n-i], 1)
   264  			bi.Dger(m-i, n-i,
   265  				-tau, work[:m-i], 1, work[m:m+n-i], 1,
   266  				a[i*lda+i:], lda)
   267  		}
   268  		if i < n-1 {
   269  			for j := 0; j < n-i; j++ {
   270  				work[j] = rnd.NormFloat64()
   271  			}
   272  			wn := bi.Dnrm2(n-i, work[:n-i], 1)
   273  			wa := math.Copysign(wn, work[0])
   274  			var tau float64
   275  			if wn != 0 {
   276  				wb := work[0] + wa
   277  				bi.Dscal(n-i-1, 1/wb, work[1:n-i], 1)
   278  				work[0] = 1
   279  				tau = wb / wa
   280  			}
   281  
   282  			// Multiply A[i:m,i:n] by random reflection from the right.
   283  			bi.Dgemv(blas.NoTrans, m-i, n-i,
   284  				1, a[i*lda+i:], lda, work[:n-i], 1,
   285  				0, work[n:n+m-i], 1)
   286  			bi.Dger(m-i, n-i,
   287  				-tau, work[n:n+m-i], 1, work[:n-i], 1,
   288  				a[i*lda+i:], lda)
   289  		}
   290  	}
   291  
   292  	// TODO(vladimir-ch): Reduce number of subdiagonals to kl and number of
   293  	// superdiagonals to ku.
   294  }
   295  
   296  // dlarnv fills dst with random numbers from a uniform or normal distribution
   297  // specified by dist:
   298  //
   299  //	dist=1: uniform(0,1),
   300  //	dist=2: uniform(-1,1),
   301  //	dist=3: normal(0,1).
   302  //
   303  // For other values of dist dlarnv will panic.
   304  func dlarnv(dst []float64, dist int, rnd *rand.Rand) {
   305  	switch dist {
   306  	default:
   307  		panic("testlapack: invalid dist")
   308  	case 1:
   309  		for i := range dst {
   310  			dst[i] = rnd.Float64()
   311  		}
   312  	case 2:
   313  		for i := range dst {
   314  			dst[i] = 2*rnd.Float64() - 1
   315  		}
   316  	case 3:
   317  		for i := range dst {
   318  			dst[i] = rnd.NormFloat64()
   319  		}
   320  	}
   321  }
   322  
   323  // dlattr generates an n×n triangular test matrix A with its properties uniquely
   324  // determined by imat and uplo, and returns whether A has unit diagonal. If diag
   325  // is blas.Unit, the diagonal elements are set so that A[k,k]=k.
   326  //
   327  // trans specifies whether the matrix A or its transpose will be used.
   328  //
   329  // If imat is greater than 10, dlattr also generates the right hand side of the
   330  // linear system A*x=b, or Aᵀ*x=b. Valid values of imat are 7, and all between 11
   331  // and 19, inclusive.
   332  //
   333  // b mush have length n, and work must have length 3*n, and dlattr will panic
   334  // otherwise.
   335  func dlattr(imat int, uplo blas.Uplo, trans blas.Transpose, n int, a []float64, lda int, b, work []float64, rnd *rand.Rand) (diag blas.Diag) {
   336  	checkMatrix(n, n, a, lda)
   337  	if len(b) != n {
   338  		panic("testlapack: bad length of b")
   339  	}
   340  	if len(work) < 3*n {
   341  		panic("testlapack: insufficient length of work")
   342  	}
   343  	if uplo != blas.Upper && uplo != blas.Lower {
   344  		panic("testlapack: bad uplo")
   345  	}
   346  	if trans != blas.Trans && trans != blas.NoTrans {
   347  		panic("testlapack: bad trans")
   348  	}
   349  
   350  	if n == 0 {
   351  		return blas.NonUnit
   352  	}
   353  
   354  	const (
   355  		tiny = safmin
   356  		huge = (1 - ulp) / tiny
   357  	)
   358  
   359  	bi := blas64.Implementation()
   360  
   361  	switch imat {
   362  	default:
   363  		// TODO(vladimir-ch): Implement the remaining cases.
   364  		panic("testlapack: invalid or unimplemented imat")
   365  	case 7:
   366  		// Identity matrix. The diagonal is set to NaN.
   367  		diag = blas.Unit
   368  		switch uplo {
   369  		case blas.Upper:
   370  			for i := 0; i < n; i++ {
   371  				a[i*lda+i] = math.NaN()
   372  				for j := i + 1; j < n; j++ {
   373  					a[i*lda+j] = 0
   374  				}
   375  			}
   376  		case blas.Lower:
   377  			for i := 0; i < n; i++ {
   378  				for j := 0; j < i; j++ {
   379  					a[i*lda+j] = 0
   380  				}
   381  				a[i*lda+i] = math.NaN()
   382  			}
   383  		}
   384  	case 11:
   385  		// Generate a triangular matrix with elements between -1 and 1,
   386  		// give the diagonal norm 2 to make it well-conditioned, and
   387  		// make the right hand side large so that it requires scaling.
   388  		diag = blas.NonUnit
   389  		switch uplo {
   390  		case blas.Upper:
   391  			for i := 0; i < n-1; i++ {
   392  				dlarnv(a[i*lda+i:i*lda+n], 2, rnd)
   393  			}
   394  		case blas.Lower:
   395  			for i := 1; i < n; i++ {
   396  				dlarnv(a[i*lda:i*lda+i+1], 2, rnd)
   397  			}
   398  		}
   399  		for i := 0; i < n; i++ {
   400  			a[i*lda+i] = math.Copysign(2, a[i*lda+i])
   401  		}
   402  		// Set the right hand side so that the largest value is huge.
   403  		dlarnv(b, 2, rnd)
   404  		imax := bi.Idamax(n, b, 1)
   405  		bscal := huge / math.Max(1, b[imax])
   406  		bi.Dscal(n, bscal, b, 1)
   407  	case 12:
   408  		// Make the first diagonal element in the solve small to cause
   409  		// immediate overflow when dividing by T[j,j]. The off-diagonal
   410  		// elements are small (cnorm[j] < 1).
   411  		diag = blas.NonUnit
   412  		tscal := 1 / math.Max(1, float64(n-1))
   413  		switch uplo {
   414  		case blas.Upper:
   415  			for i := 0; i < n; i++ {
   416  				dlarnv(a[i*lda+i:i*lda+n], 2, rnd)
   417  				bi.Dscal(n-i-1, tscal, a[i*lda+i+1:], 1)
   418  				a[i*lda+i] = math.Copysign(1, a[i*lda+i])
   419  			}
   420  			a[(n-1)*lda+n-1] *= tiny
   421  		case blas.Lower:
   422  			for i := 0; i < n; i++ {
   423  				dlarnv(a[i*lda:i*lda+i+1], 2, rnd)
   424  				bi.Dscal(i, tscal, a[i*lda:], 1)
   425  				a[i*lda+i] = math.Copysign(1, a[i*lda+i])
   426  			}
   427  			a[0] *= tiny
   428  		}
   429  		dlarnv(b, 2, rnd)
   430  	case 13:
   431  		// Make the first diagonal element in the solve small to cause
   432  		// immediate overflow when dividing by T[j,j]. The off-diagonal
   433  		// elements are O(1) (cnorm[j] > 1).
   434  		diag = blas.NonUnit
   435  		switch uplo {
   436  		case blas.Upper:
   437  			for i := 0; i < n; i++ {
   438  				dlarnv(a[i*lda+i:i*lda+n], 2, rnd)
   439  				a[i*lda+i] = math.Copysign(1, a[i*lda+i])
   440  			}
   441  			a[(n-1)*lda+n-1] *= tiny
   442  		case blas.Lower:
   443  			for i := 0; i < n; i++ {
   444  				dlarnv(a[i*lda:i*lda+i+1], 2, rnd)
   445  				a[i*lda+i] = math.Copysign(1, a[i*lda+i])
   446  			}
   447  			a[0] *= tiny
   448  		}
   449  		dlarnv(b, 2, rnd)
   450  	case 14:
   451  		// T is diagonal with small numbers on the diagonal to
   452  		// make the growth factor underflow, but a small right hand side
   453  		// chosen so that the solution does not overflow.
   454  		diag = blas.NonUnit
   455  		switch uplo {
   456  		case blas.Upper:
   457  			for i := 0; i < n; i++ {
   458  				for j := i + 1; j < n; j++ {
   459  					a[i*lda+j] = 0
   460  				}
   461  				if (n-1-i)&0x2 == 0 {
   462  					a[i*lda+i] = tiny
   463  				} else {
   464  					a[i*lda+i] = 1
   465  				}
   466  			}
   467  		case blas.Lower:
   468  			for i := 0; i < n; i++ {
   469  				for j := 0; j < i; j++ {
   470  					a[i*lda+j] = 0
   471  				}
   472  				if i&0x2 == 0 {
   473  					a[i*lda+i] = tiny
   474  				} else {
   475  					a[i*lda+i] = 1
   476  				}
   477  			}
   478  		}
   479  		// Set the right hand side alternately zero and small.
   480  		switch uplo {
   481  		case blas.Upper:
   482  			b[0] = 0
   483  			for i := n - 1; i > 0; i -= 2 {
   484  				b[i] = 0
   485  				b[i-1] = tiny
   486  			}
   487  		case blas.Lower:
   488  			for i := 0; i < n-1; i += 2 {
   489  				b[i] = 0
   490  				b[i+1] = tiny
   491  			}
   492  			b[n-1] = 0
   493  		}
   494  	case 15:
   495  		// Make the diagonal elements small to cause gradual overflow
   496  		// when dividing by T[j,j]. To control the amount of scaling
   497  		// needed, the matrix is bidiagonal.
   498  		diag = blas.NonUnit
   499  		texp := 1 / math.Max(1, float64(n-1))
   500  		tscal := math.Pow(tiny, texp)
   501  		switch uplo {
   502  		case blas.Upper:
   503  			for i := 0; i < n; i++ {
   504  				a[i*lda+i] = tscal
   505  				if i < n-1 {
   506  					a[i*lda+i+1] = -1
   507  				}
   508  				for j := i + 2; j < n; j++ {
   509  					a[i*lda+j] = 0
   510  				}
   511  			}
   512  		case blas.Lower:
   513  			for i := 0; i < n; i++ {
   514  				for j := 0; j < i-1; j++ {
   515  					a[i*lda+j] = 0
   516  				}
   517  				if i > 0 {
   518  					a[i*lda+i-1] = -1
   519  				}
   520  				a[i*lda+i] = tscal
   521  			}
   522  		}
   523  		dlarnv(b, 2, rnd)
   524  	case 16:
   525  		// One zero diagonal element.
   526  		diag = blas.NonUnit
   527  		switch uplo {
   528  		case blas.Upper:
   529  			for i := 0; i < n; i++ {
   530  				dlarnv(a[i*lda+i:i*lda+n], 2, rnd)
   531  				a[i*lda+i] = math.Copysign(2, a[i*lda+i])
   532  			}
   533  		case blas.Lower:
   534  			for i := 0; i < n; i++ {
   535  				dlarnv(a[i*lda:i*lda+i+1], 2, rnd)
   536  				a[i*lda+i] = math.Copysign(2, a[i*lda+i])
   537  			}
   538  		}
   539  		iy := n / 2
   540  		a[iy*lda+iy] = 0
   541  		dlarnv(b, 2, rnd)
   542  		bi.Dscal(n, 2, b, 1)
   543  	case 17:
   544  		// Make the offdiagonal elements large to cause overflow when
   545  		// adding a column of T. In the non-transposed case, the matrix
   546  		// is constructed to cause overflow when adding a column in
   547  		// every other step.
   548  		diag = blas.NonUnit
   549  		tscal := (1 - ulp) / tiny
   550  		texp := 1.0
   551  		switch uplo {
   552  		case blas.Upper:
   553  			for i := 0; i < n; i++ {
   554  				for j := i; j < n; j++ {
   555  					a[i*lda+j] = 0
   556  				}
   557  			}
   558  			for j := n - 1; j >= 1; j -= 2 {
   559  				a[j] = -tscal / float64(n+1)
   560  				a[j*lda+j] = 1
   561  				b[j] = texp * (1 - ulp)
   562  				a[j-1] = -tscal / float64(n+1) / float64(n+2)
   563  				a[(j-1)*lda+j-1] = 1
   564  				b[j-1] = texp * float64(n*n+n-1)
   565  				texp *= 2
   566  			}
   567  			b[0] = float64(n+1) / float64(n+2) * tscal
   568  		case blas.Lower:
   569  			for i := 0; i < n; i++ {
   570  				for j := 0; j <= i; j++ {
   571  					a[i*lda+j] = 0
   572  				}
   573  			}
   574  			for j := 0; j < n-1; j += 2 {
   575  				a[(n-1)*lda+j] = -tscal / float64(n+1)
   576  				a[j*lda+j] = 1
   577  				b[j] = texp * (1 - ulp)
   578  				a[(n-1)*lda+j+1] = -tscal / float64(n+1) / float64(n+2)
   579  				a[(j+1)*lda+j+1] = 1
   580  				b[j+1] = texp * float64(n*n+n-1)
   581  				texp *= 2
   582  			}
   583  			b[n-1] = float64(n+1) / float64(n+2) * tscal
   584  		}
   585  	case 18:
   586  		// Generate a unit triangular matrix with elements between -1
   587  		// and 1, and make the right hand side large so that it requires
   588  		// scaling. The diagonal is set to NaN.
   589  		diag = blas.Unit
   590  		switch uplo {
   591  		case blas.Upper:
   592  			for i := 0; i < n; i++ {
   593  				a[i*lda+i] = math.NaN()
   594  				dlarnv(a[i*lda+i+1:i*lda+n], 2, rnd)
   595  			}
   596  		case blas.Lower:
   597  			for i := 0; i < n; i++ {
   598  				dlarnv(a[i*lda:i*lda+i], 2, rnd)
   599  				a[i*lda+i] = math.NaN()
   600  			}
   601  		}
   602  		// Set the right hand side so that the largest value is huge.
   603  		dlarnv(b, 2, rnd)
   604  		iy := bi.Idamax(n, b, 1)
   605  		bnorm := math.Abs(b[iy])
   606  		bscal := huge / math.Max(1, bnorm)
   607  		bi.Dscal(n, bscal, b, 1)
   608  	case 19:
   609  		// Generate a triangular matrix with elements between
   610  		// huge/(n-1) and huge so that at least one of the column
   611  		// norms will exceed huge.
   612  		// Dlatrs cannot handle this case for (typically) n>5.
   613  		diag = blas.NonUnit
   614  		tleft := huge / math.Max(1, float64(n-1))
   615  		tscal := huge * (float64(n-1) / math.Max(1, float64(n)))
   616  		switch uplo {
   617  		case blas.Upper:
   618  			for i := 0; i < n; i++ {
   619  				dlarnv(a[i*lda+i:i*lda+n], 2, rnd)
   620  				for j := i; j < n; j++ {
   621  					aij := a[i*lda+j]
   622  					a[i*lda+j] = math.Copysign(tleft, aij) + tscal*aij
   623  				}
   624  			}
   625  		case blas.Lower:
   626  			for i := 0; i < n; i++ {
   627  				dlarnv(a[i*lda:i*lda+i+1], 2, rnd)
   628  				for j := 0; j <= i; j++ {
   629  					aij := a[i*lda+j]
   630  					a[i*lda+j] = math.Copysign(tleft, aij) + tscal*aij
   631  				}
   632  			}
   633  		}
   634  		dlarnv(b, 2, rnd)
   635  		bi.Dscal(n, 2, b, 1)
   636  	}
   637  
   638  	// Flip the matrix if the transpose will be used.
   639  	if trans == blas.Trans {
   640  		switch uplo {
   641  		case blas.Upper:
   642  			for j := 0; j < n/2; j++ {
   643  				bi.Dswap(n-2*j-1, a[j*lda+j:], 1, a[(j+1)*lda+n-j-1:], -lda)
   644  			}
   645  		case blas.Lower:
   646  			for j := 0; j < n/2; j++ {
   647  				bi.Dswap(n-2*j-1, a[j*lda+j:], lda, a[(n-j-1)*lda+j+1:], -1)
   648  			}
   649  		}
   650  	}
   651  
   652  	return diag
   653  }
   654  
   655  func checkMatrix(m, n int, a []float64, lda int) {
   656  	if m < 0 {
   657  		panic("testlapack: m < 0")
   658  	}
   659  	if n < 0 {
   660  		panic("testlapack: n < 0")
   661  	}
   662  	if lda < max(1, n) {
   663  		panic("testlapack: lda < max(1, n)")
   664  	}
   665  	if len(a) < (m-1)*lda+n {
   666  		panic("testlapack: insufficient matrix slice length")
   667  	}
   668  }
   669  
   670  // randomOrthogonal returns an n×n random orthogonal matrix.
   671  func randomOrthogonal(n int, rnd *rand.Rand) blas64.General {
   672  	q := eye(n, n)
   673  	x := make([]float64, n)
   674  	v := make([]float64, n)
   675  	for j := 0; j < n-1; j++ {
   676  		// x represents the j-th column of a random matrix.
   677  		for i := 0; i < j; i++ {
   678  			x[i] = 0
   679  		}
   680  		for i := j; i < n; i++ {
   681  			x[i] = rnd.NormFloat64()
   682  		}
   683  		// Compute v that represents the elementary reflector that
   684  		// annihilates the subdiagonal elements of x.
   685  		reflector(v, x, j)
   686  		// Compute Q * H_j and store the result into Q.
   687  		applyReflector(q, q, v)
   688  	}
   689  	return q
   690  }
   691  
   692  // reflector generates a Householder reflector v that zeros out subdiagonal
   693  // entries in the j-th column of a matrix.
   694  func reflector(v, col []float64, j int) {
   695  	n := len(col)
   696  	if len(v) != n {
   697  		panic("slice length mismatch")
   698  	}
   699  	if j < 0 || n <= j {
   700  		panic("invalid column index")
   701  	}
   702  
   703  	for i := range v {
   704  		v[i] = 0
   705  	}
   706  	if j == n-1 {
   707  		return
   708  	}
   709  	s := floats.Norm(col[j:], 2)
   710  	if s == 0 {
   711  		return
   712  	}
   713  	v[j] = col[j] + math.Copysign(s, col[j])
   714  	copy(v[j+1:], col[j+1:])
   715  	s = floats.Norm(v[j:], 2)
   716  	floats.Scale(1/s, v[j:])
   717  }
   718  
   719  // applyReflector computes Q*H where H is a Householder matrix represented by
   720  // the Householder reflector v.
   721  func applyReflector(qh blas64.General, q blas64.General, v []float64) {
   722  	n := len(v)
   723  	if qh.Rows != n || qh.Cols != n {
   724  		panic("bad size of qh")
   725  	}
   726  	if q.Rows != n || q.Cols != n {
   727  		panic("bad size of q")
   728  	}
   729  	qv := make([]float64, n)
   730  	blas64.Gemv(blas.NoTrans, 1, q, blas64.Vector{Data: v, Inc: 1}, 0, blas64.Vector{Data: qv, Inc: 1})
   731  	for i := 0; i < n; i++ {
   732  		for j := 0; j < n; j++ {
   733  			qh.Data[i*qh.Stride+j] = q.Data[i*q.Stride+j]
   734  		}
   735  	}
   736  	for i := 0; i < n; i++ {
   737  		for j := 0; j < n; j++ {
   738  			qh.Data[i*qh.Stride+j] -= 2 * qv[i] * v[j]
   739  		}
   740  	}
   741  	var norm2 float64
   742  	for _, vi := range v {
   743  		norm2 += vi * vi
   744  	}
   745  	norm2inv := 1 / norm2
   746  	for i := 0; i < n; i++ {
   747  		for j := 0; j < n; j++ {
   748  			qh.Data[i*qh.Stride+j] *= norm2inv
   749  		}
   750  	}
   751  }
   752  
   753  func dlattb(kind int, uplo blas.Uplo, trans blas.Transpose, n, kd int, ab []float64, ldab int, rnd *rand.Rand) (diag blas.Diag, b []float64) {
   754  	switch {
   755  	case kind < 1 || 18 < kind:
   756  		panic("bad matrix kind")
   757  	case (6 <= kind && kind <= 9) || kind == 17:
   758  		diag = blas.Unit
   759  	default:
   760  		diag = blas.NonUnit
   761  	}
   762  
   763  	if n == 0 {
   764  		return
   765  	}
   766  
   767  	const (
   768  		tiny = safmin
   769  		huge = (1 - ulp) / tiny
   770  
   771  		small = 0.25 * (safmin / ulp)
   772  		large = 1 / small
   773  		badc2 = 0.1 / ulp
   774  	)
   775  	badc1 := math.Sqrt(badc2)
   776  
   777  	var cndnum float64
   778  	switch {
   779  	case kind == 2 || kind == 8:
   780  		cndnum = badc1
   781  	case kind == 3 || kind == 9:
   782  		cndnum = badc2
   783  	default:
   784  		cndnum = 2
   785  	}
   786  
   787  	uniformM11 := func() float64 {
   788  		return 2*rnd.Float64() - 1
   789  	}
   790  
   791  	// Allocate the right-hand side and fill it with random numbers.
   792  	// The pathological matrix types below overwrite it with their
   793  	// custom vector.
   794  	b = make([]float64, n)
   795  	for i := range b {
   796  		b[i] = uniformM11()
   797  	}
   798  
   799  	bi := blas64.Implementation()
   800  	switch kind {
   801  	default:
   802  		panic("test matrix type not implemented")
   803  
   804  	case 1, 2, 3, 4, 5:
   805  		// Non-unit triangular matrix
   806  		// TODO(vladimir-ch)
   807  		var kl, ku int
   808  		switch uplo {
   809  		case blas.Upper:
   810  			ku = kd
   811  			kl = 0
   812  			// IOFF = 1 + MAX( 0, KD-N+1 )
   813  			// PACKIT = 'Q'
   814  			// 'Q' => store the upper triangle in band storage scheme
   815  			//        (only if matrix symmetric or upper triangular)
   816  		case blas.Lower:
   817  			ku = 0
   818  			kl = kd
   819  			// IOFF = 1
   820  			// PACKIT = 'B'
   821  			// 'B' => store the lower triangle in band storage scheme
   822  			//        (only if matrix symmetric or lower triangular)
   823  		}
   824  		anorm := 1.0
   825  		switch kind {
   826  		case 4:
   827  			anorm = small
   828  		case 5:
   829  			anorm = large
   830  		}
   831  		_, _, _ = kl, ku, anorm
   832  		// // DIST = 'S' // UNIFORM(-1, 1)
   833  		// // MODE = 3   // MODE = 3 sets D(I)=CNDNUM**(-(I-1)/(N-1))
   834  		// // TYPE = 'N' // If TYPE='N', the generated matrix is nonsymmetric
   835  		// CALL DLATMS( N, N, DIST, ISEED, TYPE, B, MODE, CNDNUM, ANORM,
   836  		// $            KL, KU, PACKIT, AB( IOFF, 1 ), LDAB, WORK, INFO )
   837  		panic("test matrix type not implemented")
   838  
   839  	case 6:
   840  		// Matrix is the identity.
   841  		if uplo == blas.Upper {
   842  			for i := 0; i < n; i++ {
   843  				// Fill the diagonal with non-unit numbers.
   844  				ab[i*ldab] = float64(i + 2)
   845  				for j := 1; j < min(n-i, kd+1); j++ {
   846  					ab[i*ldab+j] = 0
   847  				}
   848  			}
   849  		} else {
   850  			for i := 0; i < n; i++ {
   851  				for j := max(0, kd-i); j < kd; j++ {
   852  					ab[i*ldab+j] = 0
   853  				}
   854  				// Fill the diagonal with non-unit numbers.
   855  				ab[i*ldab+kd] = float64(i + 2)
   856  			}
   857  		}
   858  
   859  	case 7, 8, 9:
   860  		// Non-trivial unit triangular matrix
   861  		//
   862  		// A unit triangular matrix T with condition cndnum is formed.
   863  		// In this version, T only has bandwidth 2, the rest of it is
   864  		// zero.
   865  
   866  		tnorm := math.Sqrt(cndnum)
   867  
   868  		// Initialize AB to zero.
   869  		if uplo == blas.Upper {
   870  			for i := 0; i < n; i++ {
   871  				// Fill the diagonal with non-unit numbers.
   872  				ab[i*ldab] = float64(i + 2)
   873  				for j := 1; j < min(n-i, kd+1); j++ {
   874  					ab[i*ldab+j] = 0
   875  				}
   876  			}
   877  		} else {
   878  			for i := 0; i < n; i++ {
   879  				for j := max(0, kd-i); j < kd; j++ {
   880  					ab[i*ldab+j] = 0
   881  				}
   882  				// Fill the diagonal with non-unit numbers.
   883  				ab[i*ldab+kd] = float64(i + 2)
   884  			}
   885  		}
   886  
   887  		switch kd {
   888  		case 0:
   889  			// Unit diagonal matrix, nothing else to do.
   890  		case 1:
   891  			// Special case: T is tridiagonal. Set every other
   892  			// off-diagonal so that the matrix has norm tnorm+1.
   893  			if n > 1 {
   894  				if uplo == blas.Upper {
   895  					ab[1] = math.Copysign(tnorm, uniformM11())
   896  					for i := 2; i < n-1; i += 2 {
   897  						ab[i*ldab+1] = tnorm * uniformM11()
   898  					}
   899  				} else {
   900  					ab[ldab] = math.Copysign(tnorm, uniformM11())
   901  					for i := 3; i < n; i += 2 {
   902  						ab[i*ldab] = tnorm * uniformM11()
   903  					}
   904  				}
   905  			}
   906  		default:
   907  			// Form a unit triangular matrix T with condition cndnum. T is given
   908  			// by
   909  			//      | 1   +   *                      |
   910  			//      |     1   +                      |
   911  			//  T = |         1   +   *              |
   912  			//      |             1   +              |
   913  			//      |                 1   +   *      |
   914  			//      |                     1   +      |
   915  			//      |                          . . . |
   916  			// Each element marked with a '*' is formed by taking the product of
   917  			// the adjacent elements marked with '+'. The '*'s can be chosen
   918  			// freely, and the '+'s are chosen so that the inverse of T will
   919  			// have elements of the same magnitude as T.
   920  			work1 := make([]float64, n)
   921  			work2 := make([]float64, n)
   922  			star1 := math.Copysign(tnorm, uniformM11())
   923  			sfac := math.Sqrt(tnorm)
   924  			plus1 := math.Copysign(sfac, uniformM11())
   925  			for i := 0; i < n; i += 2 {
   926  				work1[i] = plus1
   927  				work2[i] = star1
   928  				if i+1 == n {
   929  					continue
   930  				}
   931  				plus2 := star1 / plus1
   932  				work1[i+1] = plus2
   933  				plus1 = star1 / plus2
   934  				// Generate a new *-value with norm between sqrt(tnorm)
   935  				// and tnorm.
   936  				rexp := uniformM11()
   937  				if rexp < 0 {
   938  					star1 = -math.Pow(sfac, 1-rexp)
   939  				} else {
   940  					star1 = math.Pow(sfac, 1+rexp)
   941  				}
   942  			}
   943  			// Copy the diagonal to AB.
   944  			if uplo == blas.Upper {
   945  				bi.Dcopy(n-1, work1, 1, ab[1:], ldab)
   946  				if n > 2 {
   947  					bi.Dcopy(n-2, work2, 1, ab[2:], ldab)
   948  				}
   949  			} else {
   950  				bi.Dcopy(n-1, work1, 1, ab[ldab+kd-1:], ldab)
   951  				if n > 2 {
   952  					bi.Dcopy(n-2, work2, 1, ab[2*ldab+kd-2:], ldab)
   953  				}
   954  			}
   955  		}
   956  
   957  	// Pathological test cases 10-18: these triangular matrices are badly
   958  	// scaled or badly conditioned, so when used in solving a triangular
   959  	// system they may cause overflow in the solution vector.
   960  
   961  	case 10:
   962  		// Generate a triangular matrix with elements between -1 and 1.
   963  		// Give the diagonal norm 2 to make it well-conditioned.
   964  		// Make the right hand side large so that it requires scaling.
   965  		if uplo == blas.Upper {
   966  			for i := 0; i < n; i++ {
   967  				for j := 0; j < min(n-j, kd+1); j++ {
   968  					ab[i*ldab+j] = uniformM11()
   969  				}
   970  				ab[i*ldab] = math.Copysign(2, ab[i*ldab])
   971  			}
   972  		} else {
   973  			for i := 0; i < n; i++ {
   974  				for j := max(0, kd-i); j < kd+1; j++ {
   975  					ab[i*ldab+j] = uniformM11()
   976  				}
   977  				ab[i*ldab+kd] = math.Copysign(2, ab[i*ldab+kd])
   978  			}
   979  		}
   980  		// Set the right hand side so that the largest value is huge.
   981  		bnorm := math.Abs(b[bi.Idamax(n, b, 1)])
   982  		bscal := huge / math.Max(1, bnorm)
   983  		bi.Dscal(n, bscal, b, 1)
   984  
   985  	case 11:
   986  		// Make the first diagonal element in the solve small to cause
   987  		// immediate overflow when dividing by T[j,j].
   988  		// The offdiagonal elements are small (cnorm[j] < 1).
   989  		tscal := 1 / float64(kd+1)
   990  		if uplo == blas.Upper {
   991  			for i := 0; i < n; i++ {
   992  				jlen := min(n-i, kd+1)
   993  				arow := ab[i*ldab : i*ldab+jlen]
   994  				dlarnv(arow, 2, rnd)
   995  				if jlen > 1 {
   996  					bi.Dscal(jlen-1, tscal, arow[1:], 1)
   997  				}
   998  				ab[i*ldab] = math.Copysign(1, ab[i*ldab])
   999  			}
  1000  			ab[(n-1)*ldab] *= tiny
  1001  		} else {
  1002  			for i := 0; i < n; i++ {
  1003  				jlen := min(i+1, kd+1)
  1004  				arow := ab[i*ldab+kd+1-jlen : i*ldab+kd+1]
  1005  				dlarnv(arow, 2, rnd)
  1006  				if jlen > 1 {
  1007  					bi.Dscal(jlen-1, tscal, arow[:jlen-1], 1)
  1008  				}
  1009  				ab[i*ldab+kd] = math.Copysign(1, ab[i*ldab+kd])
  1010  			}
  1011  			ab[kd] *= tiny
  1012  		}
  1013  
  1014  	case 12:
  1015  		// Make the first diagonal element in the solve small to cause
  1016  		// immediate overflow when dividing by T[j,j].
  1017  		// The offdiagonal elements are O(1) (cnorm[j] > 1).
  1018  		if uplo == blas.Upper {
  1019  			for i := 0; i < n; i++ {
  1020  				jlen := min(n-i, kd+1)
  1021  				arow := ab[i*ldab : i*ldab+jlen]
  1022  				dlarnv(arow, 2, rnd)
  1023  				ab[i*ldab] = math.Copysign(1, ab[i*ldab])
  1024  			}
  1025  			ab[(n-1)*ldab] *= tiny
  1026  		} else {
  1027  			for i := 0; i < n; i++ {
  1028  				jlen := min(i+1, kd+1)
  1029  				arow := ab[i*ldab+kd+1-jlen : i*ldab+kd+1]
  1030  				dlarnv(arow, 2, rnd)
  1031  				ab[i*ldab+kd] = math.Copysign(1, ab[i*ldab+kd])
  1032  			}
  1033  			ab[kd] *= tiny
  1034  		}
  1035  
  1036  	case 13:
  1037  		// T is diagonal with small numbers on the diagonal to make the growth
  1038  		// factor underflow, but a small right hand side chosen so that the
  1039  		// solution does not overflow.
  1040  		if uplo == blas.Upper {
  1041  			icount := 1
  1042  			for i := n - 1; i >= 0; i-- {
  1043  				if icount <= 2 {
  1044  					ab[i*ldab] = tiny
  1045  				} else {
  1046  					ab[i*ldab] = 1
  1047  				}
  1048  				for j := 1; j < min(n-i, kd+1); j++ {
  1049  					ab[i*ldab+j] = 0
  1050  				}
  1051  				icount++
  1052  				if icount > 4 {
  1053  					icount = 1
  1054  				}
  1055  			}
  1056  		} else {
  1057  			icount := 1
  1058  			for i := 0; i < n; i++ {
  1059  				for j := max(0, kd-i); j < kd; j++ {
  1060  					ab[i*ldab+j] = 0
  1061  				}
  1062  				if icount <= 2 {
  1063  					ab[i*ldab+kd] = tiny
  1064  				} else {
  1065  					ab[i*ldab+kd] = 1
  1066  				}
  1067  				icount++
  1068  				if icount > 4 {
  1069  					icount = 1
  1070  				}
  1071  			}
  1072  		}
  1073  		// Set the right hand side alternately zero and small.
  1074  		if uplo == blas.Upper {
  1075  			b[0] = 0
  1076  			for i := n - 1; i > 1; i -= 2 {
  1077  				b[i] = 0
  1078  				b[i-1] = tiny
  1079  			}
  1080  		} else {
  1081  			b[n-1] = 0
  1082  			for i := 0; i < n-1; i += 2 {
  1083  				b[i] = 0
  1084  				b[i+1] = tiny
  1085  			}
  1086  		}
  1087  
  1088  	case 14:
  1089  		// Make the diagonal elements small to cause gradual overflow when
  1090  		// dividing by T[j,j]. To control the amount of scaling needed, the
  1091  		// matrix is bidiagonal.
  1092  		tscal := math.Pow(tiny, 1/float64(kd+1))
  1093  		if uplo == blas.Upper {
  1094  			for i := 0; i < n; i++ {
  1095  				ab[i*ldab] = tscal
  1096  				if i < n-1 && kd > 0 {
  1097  					ab[i*ldab+1] = -1
  1098  				}
  1099  				for j := 2; j < min(n-i, kd+1); j++ {
  1100  					ab[i*ldab+j] = 0
  1101  				}
  1102  			}
  1103  			b[n-1] = 1
  1104  		} else {
  1105  			for i := 0; i < n; i++ {
  1106  				for j := max(0, kd-i); j < kd-1; j++ {
  1107  					ab[i*ldab+j] = 0
  1108  				}
  1109  				if i > 0 && kd > 0 {
  1110  					ab[i*ldab+kd-1] = -1
  1111  				}
  1112  				ab[i*ldab+kd] = tscal
  1113  			}
  1114  			b[0] = 1
  1115  		}
  1116  
  1117  	case 15:
  1118  		// One zero diagonal element.
  1119  		iy := n / 2
  1120  		if uplo == blas.Upper {
  1121  			for i := 0; i < n; i++ {
  1122  				jlen := min(n-i, kd+1)
  1123  				dlarnv(ab[i*ldab:i*ldab+jlen], 2, rnd)
  1124  				if i != iy {
  1125  					ab[i*ldab] = math.Copysign(2, ab[i*ldab])
  1126  				} else {
  1127  					ab[i*ldab] = 0
  1128  				}
  1129  			}
  1130  		} else {
  1131  			for i := 0; i < n; i++ {
  1132  				jlen := min(i+1, kd+1)
  1133  				dlarnv(ab[i*ldab+kd+1-jlen:i*ldab+kd+1], 2, rnd)
  1134  				if i != iy {
  1135  					ab[i*ldab+kd] = math.Copysign(2, ab[i*ldab+kd])
  1136  				} else {
  1137  					ab[i*ldab+kd] = 0
  1138  				}
  1139  			}
  1140  		}
  1141  		bi.Dscal(n, 2, b, 1)
  1142  
  1143  		// case 16:
  1144  		// TODO(vladimir-ch)
  1145  		// Make the off-diagonal elements large to cause overflow when adding a
  1146  		// column of T. In the non-transposed case, the matrix is constructed to
  1147  		// cause overflow when adding a column in every other step.
  1148  
  1149  		// Initialize the matrix to zero.
  1150  		// if uplo == blas.Upper {
  1151  		// 	for i := 0; i < n; i++ {
  1152  		// 		for j := 0; j < min(n-i, kd+1); j++ {
  1153  		// 			ab[i*ldab+j] = 0
  1154  		// 		}
  1155  		// 	}
  1156  		// } else {
  1157  		// 	for i := 0; i < n; i++ {
  1158  		// 		for j := max(0, kd-i); j < kd+1; j++ {
  1159  		// 			ab[i*ldab+j] = 0
  1160  		// 		}
  1161  		// 	}
  1162  		// }
  1163  
  1164  		// const tscal = (1 - ulp) / (unfl / ulp)
  1165  		// texp := 1.0
  1166  		// if kd > 0 {
  1167  		// 	if uplo == blas.Upper {
  1168  		// 		for j := n - 1; j >= 0; j -= kd {
  1169  		// 		}
  1170  		// 	} else {
  1171  		// 		for j := 0; j < n; j += kd {
  1172  		// 		}
  1173  		// 	}
  1174  		// } else {
  1175  		// 	// Diagonal matrix.
  1176  		// 	for i := 0; i < n; i++ {
  1177  		// 		ab[i*ldab] = 1
  1178  		// 		b[i] = float64(i + 1)
  1179  		// 	}
  1180  		// }
  1181  
  1182  	case 17:
  1183  		// Generate a unit triangular matrix with elements between -1 and 1, and
  1184  		// make the right hand side large so that it requires scaling.
  1185  		if uplo == blas.Upper {
  1186  			for i := 0; i < n; i++ {
  1187  				ab[i*ldab] = float64(i + 2)
  1188  				jlen := min(n-i-1, kd)
  1189  				if jlen > 0 {
  1190  					dlarnv(ab[i*ldab+1:i*ldab+1+jlen], 2, rnd)
  1191  				}
  1192  			}
  1193  		} else {
  1194  			for i := 0; i < n; i++ {
  1195  				jlen := min(i, kd)
  1196  				if jlen > 0 {
  1197  					dlarnv(ab[i*ldab+kd-jlen:i*ldab+kd], 2, rnd)
  1198  				}
  1199  				ab[i*ldab+kd] = float64(i + 2)
  1200  			}
  1201  		}
  1202  		// Set the right hand side so that the largest value is huge.
  1203  		bnorm := math.Abs(b[bi.Idamax(n, b, 1)])
  1204  		bscal := huge / math.Max(1, bnorm)
  1205  		bi.Dscal(n, bscal, b, 1)
  1206  
  1207  	case 18:
  1208  		// Generate a triangular matrix with elements between huge/kd and
  1209  		// huge so that at least one of the column norms will exceed huge.
  1210  		tleft := huge / math.Max(1, float64(kd))
  1211  		// The reference LAPACK has
  1212  		//  tscal := huge * (float64(kd) / float64(kd+1))
  1213  		// but this causes overflow when computing cnorm in Dlatbs. Our choice
  1214  		// is more conservative but increases coverage in the same way as the
  1215  		// LAPACK version.
  1216  		tscal := huge / math.Max(1, float64(kd))
  1217  		if uplo == blas.Upper {
  1218  			for i := 0; i < n; i++ {
  1219  				for j := 0; j < min(n-i, kd+1); j++ {
  1220  					r := uniformM11()
  1221  					ab[i*ldab+j] = math.Copysign(tleft, r) + tscal*r
  1222  				}
  1223  			}
  1224  		} else {
  1225  			for i := 0; i < n; i++ {
  1226  				for j := max(0, kd-i); j < kd+1; j++ {
  1227  					r := uniformM11()
  1228  					ab[i*ldab+j] = math.Copysign(tleft, r) + tscal*r
  1229  				}
  1230  			}
  1231  		}
  1232  		bi.Dscal(n, 2, b, 1)
  1233  	}
  1234  
  1235  	// Flip the matrix if the transpose will be used.
  1236  	if trans != blas.NoTrans {
  1237  		if uplo == blas.Upper {
  1238  			for j := 0; j < n/2; j++ {
  1239  				jlen := min(n-2*j-1, kd+1)
  1240  				bi.Dswap(jlen, ab[j*ldab:], 1, ab[(n-j-jlen)*ldab+jlen-1:], min(-ldab+1, -1))
  1241  			}
  1242  		} else {
  1243  			for j := 0; j < n/2; j++ {
  1244  				jlen := min(n-2*j-1, kd+1)
  1245  				bi.Dswap(jlen, ab[j*ldab+kd:], max(ldab-1, 1), ab[(n-j-1)*ldab+kd+1-jlen:], -1)
  1246  			}
  1247  		}
  1248  	}
  1249  
  1250  	return diag, b
  1251  }