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