gonum.org/v1/gonum@v0.14.0/lapack/gonum/dorml2.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  package gonum
     6  
     7  import "gonum.org/v1/gonum/blas"
     8  
     9  // Dorml2 multiplies a general matrix C by an orthogonal matrix from an LQ factorization
    10  // determined by Dgelqf.
    11  //
    12  //	C = Q * C   if side == blas.Left and trans == blas.NoTrans
    13  //	C = Qᵀ * C  if side == blas.Left and trans == blas.Trans
    14  //	C = C * Q   if side == blas.Right and trans == blas.NoTrans
    15  //	C = C * Qᵀ  if side == blas.Right and trans == blas.Trans
    16  //
    17  // If side == blas.Left, a is a matrix of side k×m, and if side == blas.Right
    18  // a is of size k×n.
    19  //
    20  // tau contains the Householder factors and is of length at least k and this function will
    21  // panic otherwise.
    22  //
    23  // work is temporary storage of length at least n if side == blas.Left
    24  // and at least m if side == blas.Right and this function will panic otherwise.
    25  //
    26  // Dorml2 is an internal routine. It is exported for testing purposes.
    27  func (impl Implementation) Dorml2(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64) {
    28  	left := side == blas.Left
    29  	switch {
    30  	case !left && side != blas.Right:
    31  		panic(badSide)
    32  	case trans != blas.Trans && trans != blas.NoTrans:
    33  		panic(badTrans)
    34  	case m < 0:
    35  		panic(mLT0)
    36  	case n < 0:
    37  		panic(nLT0)
    38  	case k < 0:
    39  		panic(kLT0)
    40  	case left && k > m:
    41  		panic(kGTM)
    42  	case !left && k > n:
    43  		panic(kGTN)
    44  	case left && lda < max(1, m):
    45  		panic(badLdA)
    46  	case !left && lda < max(1, n):
    47  		panic(badLdA)
    48  	}
    49  
    50  	// Quick return if possible.
    51  	if m == 0 || n == 0 || k == 0 {
    52  		return
    53  	}
    54  
    55  	switch {
    56  	case left && len(a) < (k-1)*lda+m:
    57  		panic(shortA)
    58  	case !left && len(a) < (k-1)*lda+n:
    59  		panic(shortA)
    60  	case len(tau) < k:
    61  		panic(shortTau)
    62  	case len(c) < (m-1)*ldc+n:
    63  		panic(shortC)
    64  	case left && len(work) < n:
    65  		panic(shortWork)
    66  	case !left && len(work) < m:
    67  		panic(shortWork)
    68  	}
    69  
    70  	notrans := trans == blas.NoTrans
    71  	switch {
    72  	case left && notrans:
    73  		for i := 0; i < k; i++ {
    74  			aii := a[i*lda+i]
    75  			a[i*lda+i] = 1
    76  			impl.Dlarf(side, m-i, n, a[i*lda+i:], 1, tau[i], c[i*ldc:], ldc, work)
    77  			a[i*lda+i] = aii
    78  		}
    79  
    80  	case left && !notrans:
    81  		for i := k - 1; i >= 0; i-- {
    82  			aii := a[i*lda+i]
    83  			a[i*lda+i] = 1
    84  			impl.Dlarf(side, m-i, n, a[i*lda+i:], 1, tau[i], c[i*ldc:], ldc, work)
    85  			a[i*lda+i] = aii
    86  		}
    87  
    88  	case !left && notrans:
    89  		for i := k - 1; i >= 0; i-- {
    90  			aii := a[i*lda+i]
    91  			a[i*lda+i] = 1
    92  			impl.Dlarf(side, m, n-i, a[i*lda+i:], 1, tau[i], c[i:], ldc, work)
    93  			a[i*lda+i] = aii
    94  		}
    95  
    96  	case !left && !notrans:
    97  		for i := 0; i < k; i++ {
    98  			aii := a[i*lda+i]
    99  			a[i*lda+i] = 1
   100  			impl.Dlarf(side, m, n-i, a[i*lda+i:], 1, tau[i], c[i:], ldc, work)
   101  			a[i*lda+i] = aii
   102  		}
   103  	}
   104  }