File: dormhr.go

package info (click to toggle)
golang-gonum-v1-gonum 0.15.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 18,792 kB
  • sloc: asm: 6,252; fortran: 5,271; sh: 377; ruby: 211; makefile: 98
file content (134 lines) | stat: -rw-r--r-- 3,970 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright ©2016 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gonum

import "gonum.org/v1/gonum/blas"

// Dormhr multiplies an m×n general matrix C with an nq×nq orthogonal matrix Q
//
//	Q * C   if side == blas.Left  and trans == blas.NoTrans,
//	Qᵀ * C  if side == blas.Left  and trans == blas.Trans,
//	C * Q   if side == blas.Right and trans == blas.NoTrans,
//	C * Qᵀ  if side == blas.Right and trans == blas.Trans,
//
// where nq == m if side == blas.Left and nq == n if side == blas.Right.
//
// Q is defined implicitly as the product of ihi-ilo elementary reflectors, as
// returned by Dgehrd:
//
//	Q = H_{ilo} H_{ilo+1} ... H_{ihi-1}.
//
// Q is equal to the identity matrix except in the submatrix
// Q[ilo+1:ihi+1,ilo+1:ihi+1].
//
// ilo and ihi must have the same values as in the previous call of Dgehrd. It
// must hold that
//
//	0 <= ilo <= ihi < m   if m > 0 and side == blas.Left,
//	ilo = 0 and ihi = -1  if m = 0 and side == blas.Left,
//	0 <= ilo <= ihi < n   if n > 0 and side == blas.Right,
//	ilo = 0 and ihi = -1  if n = 0 and side == blas.Right.
//
// a and lda represent an m×m matrix if side == blas.Left and an n×n matrix if
// side == blas.Right. The matrix contains vectors which define the elementary
// reflectors, as returned by Dgehrd.
//
// tau contains the scalar factors of the elementary reflectors, as returned by
// Dgehrd. tau must have length m-1 if side == blas.Left and n-1 if side ==
// blas.Right.
//
// c and ldc represent the m×n matrix C. On return, c is overwritten by the
// product with Q.
//
// work must have length at least max(1,lwork), and lwork must be at least
// max(1,n), if side == blas.Left, and max(1,m), if side == blas.Right. For
// optimum performance lwork should be at least n*nb if side == blas.Left and
// m*nb if side == blas.Right, where nb is the optimal block size. On return,
// work[0] will contain the optimal value of lwork.
//
// If lwork == -1, instead of performing Dormhr, only the optimal value of lwork
// will be stored in work[0].
//
// If any requirement on input sizes is not met, Dormhr will panic.
//
// Dormhr is an internal routine. It is exported for testing purposes.
func (impl Implementation) Dormhr(side blas.Side, trans blas.Transpose, m, n, ilo, ihi int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) {
	nq := n // The order of Q.
	nw := m // The minimum length of work.
	if side == blas.Left {
		nq = m
		nw = n
	}
	switch {
	case side != blas.Left && side != blas.Right:
		panic(badSide)
	case trans != blas.NoTrans && trans != blas.Trans:
		panic(badTrans)
	case m < 0:
		panic(mLT0)
	case n < 0:
		panic(nLT0)
	case ilo < 0 || max(1, nq) <= ilo:
		panic(badIlo)
	case ihi < min(ilo, nq-1) || nq <= ihi:
		panic(badIhi)
	case lda < max(1, nq):
		panic(badLdA)
	case lwork < max(1, nw) && lwork != -1:
		panic(badLWork)
	case len(work) < max(1, lwork):
		panic(shortWork)
	}

	// Quick return if possible.
	if m == 0 || n == 0 {
		work[0] = 1
		return
	}

	nh := ihi - ilo
	var nb int
	if side == blas.Left {
		opts := "LN"
		if trans == blas.Trans {
			opts = "LT"
		}
		nb = impl.Ilaenv(1, "DORMQR", opts, nh, n, nh, -1)
	} else {
		opts := "RN"
		if trans == blas.Trans {
			opts = "RT"
		}
		nb = impl.Ilaenv(1, "DORMQR", opts, m, nh, nh, -1)
	}
	lwkopt := max(1, nw) * nb
	if lwork == -1 {
		work[0] = float64(lwkopt)
		return
	}

	if nh == 0 {
		work[0] = 1
		return
	}

	switch {
	case len(a) < (nq-1)*lda+nq:
		panic(shortA)
	case len(c) < (m-1)*ldc+n:
		panic(shortC)
	case len(tau) != nq-1:
		panic(badLenTau)
	}

	if side == blas.Left {
		impl.Dormqr(side, trans, nh, n, nh, a[(ilo+1)*lda+ilo:], lda,
			tau[ilo:ihi], c[(ilo+1)*ldc:], ldc, work, lwork)
	} else {
		impl.Dormqr(side, trans, m, nh, nh, a[(ilo+1)*lda+ilo:], lda,
			tau[ilo:ihi], c[ilo+1:], ldc, work, lwork)
	}
	work[0] = float64(lwkopt)
}