gonum.org/v1/gonum@v0.14.0/lapack/gonum/dgehd2.go (about)

     1  // Copyright ©2016 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  // Dgehd2 reduces a block of a general n×n matrix A to upper Hessenberg form H
    10  // by an orthogonal similarity transformation Qᵀ * A * Q = H.
    11  //
    12  // The matrix Q is represented as a product of (ihi-ilo) elementary
    13  // reflectors
    14  //
    15  //	Q = H_{ilo} H_{ilo+1} ... H_{ihi-1}.
    16  //
    17  // Each H_i has the form
    18  //
    19  //	H_i = I - tau[i] * v * vᵀ
    20  //
    21  // where v is a real vector with v[0:i+1] = 0, v[i+1] = 1 and v[ihi+1:n] = 0.
    22  // v[i+2:ihi+1] is stored on exit in A[i+2:ihi+1,i].
    23  //
    24  // On entry, a contains the n×n general matrix to be reduced. On return, the
    25  // upper triangle and the first subdiagonal of A are overwritten with the upper
    26  // Hessenberg matrix H, and the elements below the first subdiagonal, with the
    27  // slice tau, represent the orthogonal matrix Q as a product of elementary
    28  // reflectors.
    29  //
    30  // The contents of A are illustrated by the following example, with n = 7, ilo =
    31  // 1 and ihi = 5.
    32  // On entry,
    33  //
    34  //	[ a   a   a   a   a   a   a ]
    35  //	[     a   a   a   a   a   a ]
    36  //	[     a   a   a   a   a   a ]
    37  //	[     a   a   a   a   a   a ]
    38  //	[     a   a   a   a   a   a ]
    39  //	[     a   a   a   a   a   a ]
    40  //	[                         a ]
    41  //
    42  // on return,
    43  //
    44  //	[ a   a   h   h   h   h   a ]
    45  //	[     a   h   h   h   h   a ]
    46  //	[     h   h   h   h   h   h ]
    47  //	[     v1  h   h   h   h   h ]
    48  //	[     v1  v2  h   h   h   h ]
    49  //	[     v1  v2  v3  h   h   h ]
    50  //	[                         a ]
    51  //
    52  // where a denotes an element of the original matrix A, h denotes a
    53  // modified element of the upper Hessenberg matrix H, and vi denotes an
    54  // element of the vector defining H_i.
    55  //
    56  // ilo and ihi determine the block of A that will be reduced to upper Hessenberg
    57  // form. It must hold that 0 <= ilo <= ihi <= max(0, n-1), otherwise Dgehd2 will
    58  // panic.
    59  //
    60  // On return, tau will contain the scalar factors of the elementary reflectors.
    61  // It must have length equal to n-1, otherwise Dgehd2 will panic.
    62  //
    63  // work must have length at least n, otherwise Dgehd2 will panic.
    64  //
    65  // Dgehd2 is an internal routine. It is exported for testing purposes.
    66  func (impl Implementation) Dgehd2(n, ilo, ihi int, a []float64, lda int, tau, work []float64) {
    67  	switch {
    68  	case n < 0:
    69  		panic(nLT0)
    70  	case ilo < 0 || max(0, n-1) < ilo:
    71  		panic(badIlo)
    72  	case ihi < min(ilo, n-1) || n <= ihi:
    73  		panic(badIhi)
    74  	case lda < max(1, n):
    75  		panic(badLdA)
    76  	}
    77  
    78  	// Quick return if possible.
    79  	if n == 0 {
    80  		return
    81  	}
    82  
    83  	switch {
    84  	case len(a) < (n-1)*lda+n:
    85  		panic(shortA)
    86  	case len(tau) != n-1:
    87  		panic(badLenTau)
    88  	case len(work) < n:
    89  		panic(shortWork)
    90  	}
    91  
    92  	for i := ilo; i < ihi; i++ {
    93  		// Compute elementary reflector H_i to annihilate A[i+2:ihi+1,i].
    94  		var aii float64
    95  		aii, tau[i] = impl.Dlarfg(ihi-i, a[(i+1)*lda+i], a[min(i+2, n-1)*lda+i:], lda)
    96  		a[(i+1)*lda+i] = 1
    97  
    98  		// Apply H_i to A[0:ihi+1,i+1:ihi+1] from the right.
    99  		impl.Dlarf(blas.Right, ihi+1, ihi-i, a[(i+1)*lda+i:], lda, tau[i], a[i+1:], lda, work)
   100  
   101  		// Apply H_i to A[i+1:ihi+1,i+1:n] from the left.
   102  		impl.Dlarf(blas.Left, ihi-i, n-i-1, a[(i+1)*lda+i:], lda, tau[i], a[(i+1)*lda+i+1:], lda, work)
   103  		a[(i+1)*lda+i] = aii
   104  	}
   105  }