gonum.org/v1/gonum@v0.14.0/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 "gonum.org/v1/gonum/blas" 8 9 // Dorm2r multiplies a general matrix C by an orthogonal matrix from a QR factorization 10 // determined by Dgeqrf. 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 size m×k, and if side == blas.Right 18 // a is of size n×k. 19 // 20 // tau contains the Householder factors and is of length at least k and this function 21 // will 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 // Dorm2r is an internal routine. It is exported for testing purposes. 27 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) { 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 lda < max(1, k): 45 panic(badLdA) 46 case ldc < max(1, n): 47 panic(badLdC) 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) < (m-1)*lda+k: 57 panic(shortA) 58 case !left && len(a) < (n-1)*lda+k: 59 panic(shortA) 60 case len(c) < (m-1)*ldc+n: 61 panic(shortC) 62 case len(tau) < k: 63 panic(shortTau) 64 case left && len(work) < n: 65 panic(shortWork) 66 case !left && len(work) < m: 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+i] 74 a[i*lda+i] = 1 75 impl.Dlarf(side, m-i, n, a[i*lda+i:], lda, tau[i], c[i*ldc:], ldc, work) 76 a[i*lda+i] = aii 77 } 78 return 79 } 80 for i := 0; i < k; i++ { 81 aii := a[i*lda+i] 82 a[i*lda+i] = 1 83 impl.Dlarf(side, m-i, n, a[i*lda+i:], lda, tau[i], c[i*ldc:], ldc, work) 84 a[i*lda+i] = aii 85 } 86 return 87 } 88 if trans == blas.NoTrans { 89 for i := 0; i < k; i++ { 90 aii := a[i*lda+i] 91 a[i*lda+i] = 1 92 impl.Dlarf(side, m, n-i, a[i*lda+i:], lda, tau[i], c[i:], ldc, work) 93 a[i*lda+i] = aii 94 } 95 return 96 } 97 for i := k - 1; i >= 0; i-- { 98 aii := a[i*lda+i] 99 a[i*lda+i] = 1 100 impl.Dlarf(side, m, n-i, a[i*lda+i:], lda, tau[i], c[i:], ldc, work) 101 a[i*lda+i] = aii 102 } 103 }