1 // =============================================================================
2 // === spqr_panel ==============================================================
3 // =============================================================================
4
5 // Applies a panel of Householder vectors to a dense m-by-n matrix X.
6 //
7 // Let H(k) = I - Tau(k) * V(k) * V(k)', then either of the following is done:
8 //
9 // method SPQR_QTX (0): X = Q'*X
10 // X = H(h-1) * ... * H(1) * H(0) * X where H is m-by-h
11 //
12 // method SPQR_QX (1): X = Q*X
13 // X = H(0)' * H(1)' * ... * H(h-1)' * X where H is m-by-h
14 //
15 // method SPQR_XQT (2): X = X*Q'
16 // X = X * H(h-1) * ... * H(1) * H(0) where H is n-by-h
17 //
18 // method SPQR_XQ (3): X = X*Q
19 // X = X * H(0)' * H(1) * ... * H(h-1)' where H is n-by-h
20 //
21 // The first nonzero entry in each column of H is assumed to be equal to 1.
22 // This function does not apply the row permutation vector (the Q.P part of
23 // the Q struct in the MATLAB interface).
24 //
25 // The Householder vectors are stored in a sparse block format. The vectors
26 // are held in V, an array of size v-by-h. The nonzero patterns of each of
27 // these vectors is the same; it is held in Vi [0:v-1]. The array V is lower
28 // triangular with implicit unit diagonal (the unit need not be actually
29 // present).
30
31 #include "spqr.hpp"
32
spqr_panel(int method,Long m,Long n,Long v,Long h,Long * Vi,Entry * V,Entry * Tau,Long ldx,Entry * X,Entry * C,Entry * W,cholmod_common * cc)33 template <typename Entry> void spqr_panel
34 (
35 // input
36 int method, // 0,1,2,3
37 Long m,
38 Long n,
39 Long v, // length of the first vector in V
40 Long h, // number of Householder vectors in the panel
41 Long *Vi, // Vi [0:v-1] defines the pattern of the panel
42 Entry *V, // v-by-h, panel of Householder vectors
43 Entry *Tau, // size h, Householder coefficients for the panel
44 Long ldx,
45
46 // input/output
47 Entry *X, // m-by-n with leading dimension ldx
48
49 // workspace
50 Entry *C, // method 0,1: v-by-n; method 2,3: m-by-v
51 Entry *W, // method 0,1: h*h+n*h; method 2,3: h*h+m*h
52
53 cholmod_common *cc
54 )
55 {
56 Entry *C1, *X1 ;
57 Long k, p, i ;
58
59 // -------------------------------------------------------------------------
60 // gather X into workspace C
61 // -------------------------------------------------------------------------
62
63 if (method == SPQR_QTX || method == SPQR_QX)
64 {
65 // X is m-by-n with leading dimension ldx
66 // C is v-by-n with leading dimension v
67 C1 = C ;
68 X1 = X ;
69 for (k = 0 ; k < n ; k++)
70 {
71 for (p = 0 ; p < v ; p++)
72 {
73 i = Vi [p] ;
74 C1 [p] = X1 [i] ;
75 }
76 C1 += v ;
77 X1 += ldx ;
78 }
79 }
80 else // if (method == SPQR_XQT || method == SPQR_XQ)
81 {
82 // X is m-by-n with leading dimension ldx
83 // C is m-by-v with leading dimension m
84 C1 = C ;
85 for (p = 0 ; p < v ; p++)
86 {
87 i = Vi [p] ;
88 X1 = X + i*ldx ;
89 for (k = 0 ; k < m ; k++)
90 {
91 C1 [k] = X1 [k] ;
92 }
93 C1 += m ;
94 }
95 }
96
97 // -------------------------------------------------------------------------
98 // apply the Householder panel to C
99 // -------------------------------------------------------------------------
100
101 if (method == SPQR_QTX || method == SPQR_QX)
102 {
103 spqr_larftb (method, v, n, h, v, v, V, Tau, C, W, cc) ;
104 }
105 else // if (method == SPQR_XQT || method == SPQR_XQ)
106 {
107 spqr_larftb (method, m, v, h, m, v, V, Tau, C, W, cc) ;
108 }
109
110 // -------------------------------------------------------------------------
111 // scatter C back into X
112 // -------------------------------------------------------------------------
113
114 if (method == SPQR_QTX || method == SPQR_QX)
115 {
116 C1 = C ;
117 X1 = X ;
118 for (k = 0 ; k < n ; k++)
119 {
120 for (p = 0 ; p < v ; p++)
121 {
122 i = Vi [p] ;
123 X1 [i] = C1 [p] ;
124 }
125 C1 += v ;
126 X1 += ldx ;
127 }
128 }
129 else // if (method == SPQR_XQT || method == SPQR_XQ)
130 {
131 C1 = C ;
132 for (p = 0 ; p < v ; p++)
133 {
134 i = Vi [p] ;
135 X1 = X + i*ldx ;
136 for (k = 0 ; k < m ; k++)
137 {
138 X1 [k] = C1 [k] ;
139 }
140 C1 += m ;
141 }
142 }
143 }
144
145
146 // =============================================================================
147
148 template void spqr_panel <double>
149 (
150 // input
151 int method,
152 Long m,
153 Long n,
154 Long v,
155 Long h, // number of Householder vectors in the panel
156 Long *Vi, // Vi [0:v-1] defines the pattern of the panel
157 double *V, // v-by-h, panel of Householder vectors
158 double *Tau, // size h, Householder coefficients for the panel
159 Long ldx,
160
161 // input/output
162 double *X, // m-by-n with leading dimension m
163
164 // workspace
165 double *C, // method 0,1: v-by-n; method 2,3: m-by-v
166 double *W, // method 0,1: k*k+n*k; method 2,3: k*k+m*k
167
168 cholmod_common *cc
169 ) ;
170
171 template void spqr_panel <Complex>
172 (
173 // input
174 int method,
175 Long m,
176 Long n,
177 Long v,
178 Long h, // number of Householder vectors in the panel
179 Long *Vi, // Vi [0:v-1] defines the pattern of the panel
180 Complex *V, // v-by-h, panel of Householder vectors
181 Complex *Tau, // size h, Householder coefficients for the panel
182 Long ldx,
183
184 // input/output
185 Complex *X, // m-by-n with leading dimension m
186
187 // workspace
188 Complex *C, // method 0,1: v-by-n; method 2,3: m-by-v
189 Complex *W, // method 0,1: k*k+n*k; method 2,3: k*k+m*k
190
191 cholmod_common *cc
192 ) ;
193