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