github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/lapack/gonum/dormr2.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/jingcheng-WU/gonum/blas"
     8  
     9  // Dormr2 multiplies a general matrix C by an orthogonal matrix from a RQ factorization
    10  // determined by Dgerqf.
    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 k×m, and if side == blas.Right
    16  // a is of size k×n.
    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  // Dormr2 is an internal routine. It is exported for testing purposes.
    25  func (impl Implementation) Dormr2(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  	nq := n
    28  	nw := m
    29  	if left {
    30  		nq = m
    31  		nw = n
    32  	}
    33  	switch {
    34  	case !left && side != blas.Right:
    35  		panic(badSide)
    36  	case trans != blas.NoTrans && trans != blas.Trans:
    37  		panic(badTrans)
    38  	case m < 0:
    39  		panic(mLT0)
    40  	case n < 0:
    41  		panic(nLT0)
    42  	case k < 0:
    43  		panic(kLT0)
    44  	case left && k > m:
    45  		panic(kGTM)
    46  	case !left && k > n:
    47  		panic(kGTN)
    48  	case lda < max(1, nq):
    49  		panic(badLdA)
    50  	case ldc < max(1, n):
    51  		panic(badLdC)
    52  	}
    53  
    54  	// Quick return if possible.
    55  	if m == 0 || n == 0 || k == 0 {
    56  		return
    57  	}
    58  
    59  	switch {
    60  	case len(a) < (k-1)*lda+nq:
    61  		panic(shortA)
    62  	case len(tau) < k:
    63  		panic(shortTau)
    64  	case len(c) < (m-1)*ldc+n:
    65  		panic(shortC)
    66  	case len(work) < nw:
    67  		panic(shortWork)
    68  	}
    69  
    70  	if left {
    71  		if trans == blas.NoTrans {
    72  			for i := k - 1; i >= 0; i-- {
    73  				aii := a[i*lda+(m-k+i)]
    74  				a[i*lda+(m-k+i)] = 1
    75  				impl.Dlarf(side, m-k+i+1, n, a[i*lda:], 1, tau[i], c, ldc, work)
    76  				a[i*lda+(m-k+i)] = aii
    77  			}
    78  			return
    79  		}
    80  		for i := 0; i < k; i++ {
    81  			aii := a[i*lda+(m-k+i)]
    82  			a[i*lda+(m-k+i)] = 1
    83  			impl.Dlarf(side, m-k+i+1, n, a[i*lda:], 1, tau[i], c, ldc, work)
    84  			a[i*lda+(m-k+i)] = aii
    85  		}
    86  		return
    87  	}
    88  	if trans == blas.NoTrans {
    89  		for i := 0; i < k; i++ {
    90  			aii := a[i*lda+(n-k+i)]
    91  			a[i*lda+(n-k+i)] = 1
    92  			impl.Dlarf(side, m, n-k+i+1, a[i*lda:], 1, tau[i], c, ldc, work)
    93  			a[i*lda+(n-k+i)] = aii
    94  		}
    95  		return
    96  	}
    97  	for i := k - 1; i >= 0; i-- {
    98  		aii := a[i*lda+(n-k+i)]
    99  		a[i*lda+(n-k+i)] = 1
   100  		impl.Dlarf(side, m, n-k+i+1, a[i*lda:], 1, tau[i], c, ldc, work)
   101  		a[i*lda+(n-k+i)] = aii
   102  	}
   103  }