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