gonum.org/v1/gonum@v0.14.0/lapack/gonum/dgelqf.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 (
     8  	"gonum.org/v1/gonum/blas"
     9  	"gonum.org/v1/gonum/lapack"
    10  )
    11  
    12  // Dgelqf computes the LQ factorization of the m×n matrix A using a blocked
    13  // algorithm. See the documentation for Dgelq2 for a description of the
    14  // parameters at entry and exit.
    15  //
    16  // work is temporary storage, and lwork specifies the usable memory length.
    17  // At minimum, lwork >= m, and this function will panic otherwise.
    18  // Dgelqf is a blocked LQ factorization, but the block size is limited
    19  // by the temporary space available. If lwork == -1, instead of performing Dgelqf,
    20  // the optimal work length will be stored into work[0].
    21  //
    22  // tau must have length at least min(m,n), and this function will panic otherwise.
    23  func (impl Implementation) Dgelqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) {
    24  	switch {
    25  	case m < 0:
    26  		panic(mLT0)
    27  	case n < 0:
    28  		panic(nLT0)
    29  	case lda < max(1, n):
    30  		panic(badLdA)
    31  	case lwork < max(1, m) && lwork != -1:
    32  		panic(badLWork)
    33  	case len(work) < max(1, lwork):
    34  		panic(shortWork)
    35  	}
    36  
    37  	k := min(m, n)
    38  	if k == 0 {
    39  		work[0] = 1
    40  		return
    41  	}
    42  
    43  	nb := impl.Ilaenv(1, "DGELQF", " ", m, n, -1, -1)
    44  	if lwork == -1 {
    45  		work[0] = float64(m * nb)
    46  		return
    47  	}
    48  
    49  	if len(a) < (m-1)*lda+n {
    50  		panic(shortA)
    51  	}
    52  	if len(tau) < k {
    53  		panic(shortTau)
    54  	}
    55  
    56  	// Find the optimal blocking size based on the size of available memory
    57  	// and optimal machine parameters.
    58  	nbmin := 2
    59  	var nx int
    60  	iws := m
    61  	if 1 < nb && nb < k {
    62  		nx = max(0, impl.Ilaenv(3, "DGELQF", " ", m, n, -1, -1))
    63  		if nx < k {
    64  			iws = m * nb
    65  			if lwork < iws {
    66  				nb = lwork / m
    67  				nbmin = max(2, impl.Ilaenv(2, "DGELQF", " ", m, n, -1, -1))
    68  			}
    69  		}
    70  	}
    71  	ldwork := nb
    72  	// Computed blocked LQ factorization.
    73  	var i int
    74  	if nbmin <= nb && nb < k && nx < k {
    75  		for i = 0; i < k-nx; i += nb {
    76  			ib := min(k-i, nb)
    77  			impl.Dgelq2(ib, n-i, a[i*lda+i:], lda, tau[i:], work)
    78  			if i+ib < m {
    79  				impl.Dlarft(lapack.Forward, lapack.RowWise, n-i, ib,
    80  					a[i*lda+i:], lda,
    81  					tau[i:],
    82  					work, ldwork)
    83  				impl.Dlarfb(blas.Right, blas.NoTrans, lapack.Forward, lapack.RowWise,
    84  					m-i-ib, n-i, ib,
    85  					a[i*lda+i:], lda,
    86  					work, ldwork,
    87  					a[(i+ib)*lda+i:], lda,
    88  					work[ib*ldwork:], ldwork)
    89  			}
    90  		}
    91  	}
    92  	// Perform unblocked LQ factorization on the remainder.
    93  	if i < k {
    94  		impl.Dgelq2(m-i, n-i, a[i*lda+i:], lda, tau[i:], work)
    95  	}
    96  	work[0] = float64(iws)
    97  }