1 /*
2 * Copyright (c) 2011, Michael Lehn
3 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1) Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2) Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * 3) Neither the name of the FLENS development group nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /* Based on
34 *
35 SUBROUTINE DTREXC( COMPQ, N, T, LDT, Q, LDQ, IFST, ILST, WORK,
36 $ INFO )
37 *
38 * -- LAPACK routine (version 3.2) --
39 * -- LAPACK is a software package provided by Univ. of Tennessee, --
40 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
41 * November 2006
42 */
43
44 #ifndef FLENS_LAPACK_EIG_TREXC_TCC
45 #define FLENS_LAPACK_EIG_TREXC_TCC 1
46
47 #include <flens/blas/blas.h>
48 #include <flens/lapack/lapack.h>
49
50 namespace flens { namespace lapack {
51
52 //== generic lapack implementation =============================================
53
54 template <typename MT, typename MQ, typename IndexType, typename VWORK>
55 IndexType
56 trexc_generic(bool computeQ,
57 GeMatrix<MT> &T,
58 GeMatrix<MQ> &Q,
59 IndexType &iFirst,
60 IndexType &iLast,
61 DenseVector<VWORK> &work)
62 {
63 typedef typename GeMatrix<MT>::ElementType ElementType;
64
65 const IndexType n = T.numRows();
66 const ElementType Zero(0);
67
68 IndexType nBlockFirst, nBlockLast, nBlockNext, here;
69 IndexType info = 0;
70 //
71 // Quick return if possible
72 //
73 if (n<=1) {
74 return info;
75 }
76 //
77 // Determine the first row of specified block
78 // and find out if it is 1 by 1 or 2 by 2.
79 //
80 if (iFirst>1) {
81 if (T(iFirst,iFirst-1)!=Zero) {
82 --iFirst;
83 }
84 }
85 nBlockFirst = 1;
86 if (iFirst<n) {
87 if (T(iFirst+1,iFirst)!=Zero) {
88 nBlockFirst = 2;
89 }
90 }
91 //
92 // Determine the first row of the final block
93 // and find out if it is 1 by 1 or 2 by 2.
94 //
95 if (iLast>1) {
96 if (T(iLast,iLast-1)!=Zero) {
97 --iLast;
98 }
99 }
100 nBlockLast = 1;
101 if (iLast<n) {
102 if (T(iLast+1,iLast)!=Zero) {
103 nBlockLast = 2;
104 }
105 }
106
107 if (iFirst==iLast) {
108 return info;
109 }
110
111 if (iFirst<iLast) {
112 //
113 // Update ILST
114 //
115 if (nBlockFirst==2 && nBlockLast==1) {
116 --iLast;
117 }
118 if (nBlockFirst==1 && nBlockLast==2) {
119 ++iLast;
120 }
121
122 here = iFirst;
123
124 do {
125 //
126 // Swap block with next one below
127 //
128 if (nBlockFirst==1 || nBlockFirst==2) {
129 //
130 // Current block either 1 by 1 or 2 by 2
131 //
132 nBlockNext = 1;
133 if (here+nBlockFirst+1<=n) {
134 if (T(here+nBlockFirst+1,here+nBlockFirst)!=Zero) {
135 nBlockNext = 2;
136 }
137 }
138 info = laexc(computeQ, T, Q,
139 here, nBlockFirst, nBlockNext,
140 work);
141 if (info!=0) {
142 iLast = here;
143 return info;
144 }
145 here += nBlockNext;
146 //
147 // Test if 2 by 2 block breaks into two 1 by 1 blocks
148 //
149 if (nBlockFirst==2) {
150 if (T(here+1,here)==Zero) {
151 nBlockFirst = 3;
152 }
153 }
154
155 } else {
156 //
157 // Current block consists of two 1 by 1 blocks each of which
158 // must be swapped individually
159 //
160 nBlockNext = 1;
161 if (here+3<=n) {
162 if (T(here+3,here+2)!=Zero) {
163 nBlockNext = 2;
164 }
165 }
166 info = laexc(computeQ, T, Q, here+1,
167 IndexType(1), nBlockNext,
168 work);
169 if (info!=0) {
170 iLast = here;
171 return info;
172 }
173 if (nBlockNext==1) {
174 //
175 // Swap two 1 by 1 blocks, no problems possible
176 //
177 laexc(computeQ, T, Q, here, IndexType(1), nBlockNext, work);
178 ++here;
179 } else {
180 //
181 // Recompute NBNEXT in case 2 by 2 split
182 //
183 if (T(here+2,here+1)==Zero) {
184 nBlockNext = 1;
185 }
186 if (nBlockNext==2) {
187 //
188 // 2 by 2 Block did not split
189 //
190 info = laexc(computeQ, T, Q, here,
191 IndexType(1), nBlockNext,
192 work);
193 if (info!=0) {
194 iLast = here;
195 return info;
196 }
197 here += 2;
198 } else {
199 //
200 // 2 by 2 Block did split
201 //
202 laexc(computeQ, T, Q,
203 here, IndexType(1), IndexType(1),
204 work);
205 laexc(computeQ, T, Q,
206 here+1, IndexType(1), IndexType(1),
207 work);
208 here += 2;
209 }
210 }
211 }
212 } while (here<iLast);
213 } else {
214
215 here = iFirst;
216 do {
217 //
218 // Swap block with next one above
219 //
220 if (nBlockFirst==1 || nBlockFirst==2) {
221 //
222 // Current block either 1 by 1 or 2 by 2
223 //
224 nBlockNext = 1;
225 if (here>=3) {
226 if (T(here-1,here-2)!=Zero) {
227 nBlockNext = 2;
228 }
229 }
230 info = laexc(computeQ, T, Q,
231 here-nBlockNext, nBlockNext, nBlockFirst,
232 work);
233 if (info!=0) {
234 iLast = here;
235 return info;
236 }
237 here -= nBlockNext;
238 //
239 // Test if 2 by 2 block breaks into two 1 by 1 blocks
240 //
241 if (nBlockFirst==2) {
242 if (T(here+1,here)==Zero) {
243 nBlockFirst = 3;
244 }
245 }
246
247 } else {
248 //
249 // Current block consists of two 1 by 1 blocks each of which
250 // must be swapped individually
251 //
252 nBlockNext = 1;
253 if (here>=3) {
254 if (T(here-1,here-2)!=Zero) {
255 nBlockNext = 2;
256 }
257 }
258 info = laexc(computeQ, T, Q,
259 here-nBlockNext, nBlockNext, IndexType(1),
260 work);
261 if (info!=0) {
262 iLast = here;
263 return info;
264 }
265 if (nBlockNext==1) {
266 //
267 // Swap two 1 by 1 blocks, no problems possible
268 //
269 laexc(computeQ, T, Q,
270 here, nBlockNext, IndexType(1),
271 work);
272 --here;
273 } else {
274 //
275 // Recompute NBNEXT in case 2 by 2 split
276 //
277 if (T(here,here-1)==Zero) {
278 nBlockNext = 1;
279 }
280 if (nBlockNext==2) {
281 //
282 // 2 by 2 Block did not split
283 //
284 info = laexc(computeQ, T, Q,
285 here-1, IndexType(2), IndexType(1),
286 work);
287 if (info!=0) {
288 iLast = here;
289 return info;
290 }
291 here -= 2;
292 } else {
293 //
294 // 2 by 2 Block did split
295 //
296 laexc(computeQ, T, Q,
297 here, IndexType(1), IndexType(1),
298 work);
299 laexc(computeQ, T, Q,
300 here-1, IndexType(1), IndexType(1),
301 work);
302 here -= 2;
303 }
304 }
305 }
306 } while (here>iLast);
307 }
308 iLast = here;
309 return info;
310 }
311
312 //== interface for native lapack ===============================================
313
314 #ifdef CHECK_CXXLAPACK
315
316 template <typename MT, typename MQ, typename IndexType, typename VWORK>
317 IndexType
318 trexc_native(bool computeQ,
319 GeMatrix<MT> &T,
320 GeMatrix<MQ> &Q,
321 IndexType &iFirst,
322 IndexType &iLast,
323 DenseVector<VWORK> &work)
324 {
325 typedef typename GeMatrix<MT>::ElementType ElementType;
326
327 const char COMPQ = (computeQ) ? 'V' : 'N';
328 const INTEGER N = T.numRows();
329 const INTEGER LDT = T.leadingDimension();
330 const INTEGER LDQ = Q.leadingDimension();
331 INTEGER IFST = iFirst;
332 INTEGER ILST = iLast;
333 INTEGER INFO;
334
335 if (IsSame<ElementType,DOUBLE>::value) {
336 LAPACK_IMPL(dtrexc)(&COMPQ,
337 &N,
338 T.data(),
339 &LDT,
340 Q.data(),
341 &LDQ,
342 &IFST,
343 &ILST,
344 work.data(),
345 &INFO);
346 } else {
347 ASSERT(0);
348 }
349 ASSERT(INFO>=0);
350
351 iFirst = IFST;
352 iLast = ILST;
353 return INFO;
354 }
355
356 #endif // CHECK_CXXLAPACK
357
358 //== public interface ==========================================================
359
360 template <typename MT, typename MQ, typename IndexType, typename VWORK>
361 IndexType
362 trexc(bool computeQ,
363 GeMatrix<MT> &T,
364 GeMatrix<MQ> &Q,
365 IndexType &iFirst,
366 IndexType &iLast,
367 DenseVector<VWORK> &work)
368 {
369 LAPACK_DEBUG_OUT("trexc");
370
371 //
372 // Test the input parameters
373 //
374 # ifndef NDEBUG
375 ASSERT(T.firstRow()==1);
376 ASSERT(T.firstCol()==1);
377 ASSERT(T.numRows()==T.numCols());
378
379 const IndexType n = T.numRows();
380
381 if (computeQ) {
382 ASSERT(Q.firstRow()==1);
383 ASSERT(Q.firstCol()==1);
384 ASSERT(Q.numRows()==Q.numCols());
385 ASSERT(Q.numRows()==n);
386 }
387
388 ASSERT(work.firstIndex()==1);
389 ASSERT(work.length()==n);
390 # endif
391
392 # ifdef CHECK_CXXLAPACK
393 //
394 // Make copies of output arguments
395 //
396 typename GeMatrix<MT>::NoView T_org = T;
397 typename GeMatrix<MQ>::NoView Q_org = Q;
398 IndexType iFirst_org = iFirst;
399 IndexType iLast_org = iLast;
400 typename DenseVector<VWORK>::NoView work_org = work;
401 # endif
402
403 //
404 // Call implementation
405 //
406 IndexType info = trexc_generic(computeQ, T, Q, iFirst, iLast, work);
407
408 # ifdef CHECK_CXXLAPACK
409 //
410 // Make copies of results computed by the generic implementation
411 //
412 typename GeMatrix<MT>::NoView T_generic = T;
413 typename GeMatrix<MQ>::NoView Q_generic = Q;
414 IndexType iFirst_generic = iFirst;
415 IndexType iLast_generic = iLast;
416 typename DenseVector<VWORK>::NoView work_generic = work;
417
418 //
419 // restore output arguments
420 //
421 T = T_org;
422 Q = Q_org;
423 iFirst = iFirst_org;
424 iLast = iLast_org;
425 work = work_org;
426
427 //
428 // Compare results
429 //
430 IndexType _info = trexc_native(computeQ, T, Q, iFirst, iLast, work);
431
432 bool failed = false;
433 if (! isIdentical(T_generic, T, "T_generic", "T")) {
434 std::cerr << "CXXLAPACK: T_generic = " << T_generic << std::endl;
435 std::cerr << "F77LAPACK: T = " << T << std::endl;
436 failed = true;
437 }
438
439 if (! isIdentical(Q_generic, Q, "Q_generic", "Q")) {
440 std::cerr << "CXXLAPACK: Q_generic = " << Q_generic << std::endl;
441 std::cerr << "F77LAPACK: Q = " << Q << std::endl;
442 failed = true;
443 }
444
445 if (! isIdentical(iFirst_generic, iFirst, "iFirst_generic", "iFirst")) {
446 std::cerr << "CXXLAPACK: iFirst_generic = "
447 << iFirst_generic << std::endl;
448 std::cerr << "F77LAPACK: iFirst = "
449 << iFirst << std::endl;
450 failed = true;
451 }
452
453 if (! isIdentical(iLast_generic, iLast, "iLast_generic", "iLast")) {
454 std::cerr << "CXXLAPACK: iLast_generic = "
455 << iLast_generic << std::endl;
456 std::cerr << "F77LAPACK: iLast = " << iLast << std::endl;
457 failed = true;
458 }
459
460 if (! isIdentical(work_generic, work, "work_generic", "work")) {
461 std::cerr << "CXXLAPACK: work_generic = " << work_generic << std::endl;
462 std::cerr << "F77LAPACK: work = " << work << std::endl;
463 failed = true;
464 }
465
466 if (! isIdentical(info, _info, " info", "_info")) {
467 std::cerr << "CXXLAPACK: info = " << info << std::endl;
468 std::cerr << "F77LAPACK: _info = " << _info << std::endl;
469 failed = true;
470 }
471
472 if (failed) {
473 ASSERT(0);
474 }
475 # endif
476
477 return info;
478 }
479
480 //-- forwarding ----------------------------------------------------------------
481 template <typename MT, typename MQ, typename IndexType, typename VWORK>
482 IndexType
483 trexc(bool computeQ,
484 MT &&T,
485 MQ &&Q,
486 IndexType &iFirst,
487 IndexType &iLast,
488 VWORK &&work)
489 {
490 CHECKPOINT_ENTER;
491 const IndexType info = trexc(computeQ, T, Q, iFirst, iLast, work);
492 CHECKPOINT_LEAVE;
493
494 return info;
495 }
496
497 } } // namespace lapack, flens
498
499 #endif // FLENS_LAPACK_EIG_TREVC_TCC
2 * Copyright (c) 2011, Michael Lehn
3 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1) Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2) Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * 3) Neither the name of the FLENS development group nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /* Based on
34 *
35 SUBROUTINE DTREXC( COMPQ, N, T, LDT, Q, LDQ, IFST, ILST, WORK,
36 $ INFO )
37 *
38 * -- LAPACK routine (version 3.2) --
39 * -- LAPACK is a software package provided by Univ. of Tennessee, --
40 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
41 * November 2006
42 */
43
44 #ifndef FLENS_LAPACK_EIG_TREXC_TCC
45 #define FLENS_LAPACK_EIG_TREXC_TCC 1
46
47 #include <flens/blas/blas.h>
48 #include <flens/lapack/lapack.h>
49
50 namespace flens { namespace lapack {
51
52 //== generic lapack implementation =============================================
53
54 template <typename MT, typename MQ, typename IndexType, typename VWORK>
55 IndexType
56 trexc_generic(bool computeQ,
57 GeMatrix<MT> &T,
58 GeMatrix<MQ> &Q,
59 IndexType &iFirst,
60 IndexType &iLast,
61 DenseVector<VWORK> &work)
62 {
63 typedef typename GeMatrix<MT>::ElementType ElementType;
64
65 const IndexType n = T.numRows();
66 const ElementType Zero(0);
67
68 IndexType nBlockFirst, nBlockLast, nBlockNext, here;
69 IndexType info = 0;
70 //
71 // Quick return if possible
72 //
73 if (n<=1) {
74 return info;
75 }
76 //
77 // Determine the first row of specified block
78 // and find out if it is 1 by 1 or 2 by 2.
79 //
80 if (iFirst>1) {
81 if (T(iFirst,iFirst-1)!=Zero) {
82 --iFirst;
83 }
84 }
85 nBlockFirst = 1;
86 if (iFirst<n) {
87 if (T(iFirst+1,iFirst)!=Zero) {
88 nBlockFirst = 2;
89 }
90 }
91 //
92 // Determine the first row of the final block
93 // and find out if it is 1 by 1 or 2 by 2.
94 //
95 if (iLast>1) {
96 if (T(iLast,iLast-1)!=Zero) {
97 --iLast;
98 }
99 }
100 nBlockLast = 1;
101 if (iLast<n) {
102 if (T(iLast+1,iLast)!=Zero) {
103 nBlockLast = 2;
104 }
105 }
106
107 if (iFirst==iLast) {
108 return info;
109 }
110
111 if (iFirst<iLast) {
112 //
113 // Update ILST
114 //
115 if (nBlockFirst==2 && nBlockLast==1) {
116 --iLast;
117 }
118 if (nBlockFirst==1 && nBlockLast==2) {
119 ++iLast;
120 }
121
122 here = iFirst;
123
124 do {
125 //
126 // Swap block with next one below
127 //
128 if (nBlockFirst==1 || nBlockFirst==2) {
129 //
130 // Current block either 1 by 1 or 2 by 2
131 //
132 nBlockNext = 1;
133 if (here+nBlockFirst+1<=n) {
134 if (T(here+nBlockFirst+1,here+nBlockFirst)!=Zero) {
135 nBlockNext = 2;
136 }
137 }
138 info = laexc(computeQ, T, Q,
139 here, nBlockFirst, nBlockNext,
140 work);
141 if (info!=0) {
142 iLast = here;
143 return info;
144 }
145 here += nBlockNext;
146 //
147 // Test if 2 by 2 block breaks into two 1 by 1 blocks
148 //
149 if (nBlockFirst==2) {
150 if (T(here+1,here)==Zero) {
151 nBlockFirst = 3;
152 }
153 }
154
155 } else {
156 //
157 // Current block consists of two 1 by 1 blocks each of which
158 // must be swapped individually
159 //
160 nBlockNext = 1;
161 if (here+3<=n) {
162 if (T(here+3,here+2)!=Zero) {
163 nBlockNext = 2;
164 }
165 }
166 info = laexc(computeQ, T, Q, here+1,
167 IndexType(1), nBlockNext,
168 work);
169 if (info!=0) {
170 iLast = here;
171 return info;
172 }
173 if (nBlockNext==1) {
174 //
175 // Swap two 1 by 1 blocks, no problems possible
176 //
177 laexc(computeQ, T, Q, here, IndexType(1), nBlockNext, work);
178 ++here;
179 } else {
180 //
181 // Recompute NBNEXT in case 2 by 2 split
182 //
183 if (T(here+2,here+1)==Zero) {
184 nBlockNext = 1;
185 }
186 if (nBlockNext==2) {
187 //
188 // 2 by 2 Block did not split
189 //
190 info = laexc(computeQ, T, Q, here,
191 IndexType(1), nBlockNext,
192 work);
193 if (info!=0) {
194 iLast = here;
195 return info;
196 }
197 here += 2;
198 } else {
199 //
200 // 2 by 2 Block did split
201 //
202 laexc(computeQ, T, Q,
203 here, IndexType(1), IndexType(1),
204 work);
205 laexc(computeQ, T, Q,
206 here+1, IndexType(1), IndexType(1),
207 work);
208 here += 2;
209 }
210 }
211 }
212 } while (here<iLast);
213 } else {
214
215 here = iFirst;
216 do {
217 //
218 // Swap block with next one above
219 //
220 if (nBlockFirst==1 || nBlockFirst==2) {
221 //
222 // Current block either 1 by 1 or 2 by 2
223 //
224 nBlockNext = 1;
225 if (here>=3) {
226 if (T(here-1,here-2)!=Zero) {
227 nBlockNext = 2;
228 }
229 }
230 info = laexc(computeQ, T, Q,
231 here-nBlockNext, nBlockNext, nBlockFirst,
232 work);
233 if (info!=0) {
234 iLast = here;
235 return info;
236 }
237 here -= nBlockNext;
238 //
239 // Test if 2 by 2 block breaks into two 1 by 1 blocks
240 //
241 if (nBlockFirst==2) {
242 if (T(here+1,here)==Zero) {
243 nBlockFirst = 3;
244 }
245 }
246
247 } else {
248 //
249 // Current block consists of two 1 by 1 blocks each of which
250 // must be swapped individually
251 //
252 nBlockNext = 1;
253 if (here>=3) {
254 if (T(here-1,here-2)!=Zero) {
255 nBlockNext = 2;
256 }
257 }
258 info = laexc(computeQ, T, Q,
259 here-nBlockNext, nBlockNext, IndexType(1),
260 work);
261 if (info!=0) {
262 iLast = here;
263 return info;
264 }
265 if (nBlockNext==1) {
266 //
267 // Swap two 1 by 1 blocks, no problems possible
268 //
269 laexc(computeQ, T, Q,
270 here, nBlockNext, IndexType(1),
271 work);
272 --here;
273 } else {
274 //
275 // Recompute NBNEXT in case 2 by 2 split
276 //
277 if (T(here,here-1)==Zero) {
278 nBlockNext = 1;
279 }
280 if (nBlockNext==2) {
281 //
282 // 2 by 2 Block did not split
283 //
284 info = laexc(computeQ, T, Q,
285 here-1, IndexType(2), IndexType(1),
286 work);
287 if (info!=0) {
288 iLast = here;
289 return info;
290 }
291 here -= 2;
292 } else {
293 //
294 // 2 by 2 Block did split
295 //
296 laexc(computeQ, T, Q,
297 here, IndexType(1), IndexType(1),
298 work);
299 laexc(computeQ, T, Q,
300 here-1, IndexType(1), IndexType(1),
301 work);
302 here -= 2;
303 }
304 }
305 }
306 } while (here>iLast);
307 }
308 iLast = here;
309 return info;
310 }
311
312 //== interface for native lapack ===============================================
313
314 #ifdef CHECK_CXXLAPACK
315
316 template <typename MT, typename MQ, typename IndexType, typename VWORK>
317 IndexType
318 trexc_native(bool computeQ,
319 GeMatrix<MT> &T,
320 GeMatrix<MQ> &Q,
321 IndexType &iFirst,
322 IndexType &iLast,
323 DenseVector<VWORK> &work)
324 {
325 typedef typename GeMatrix<MT>::ElementType ElementType;
326
327 const char COMPQ = (computeQ) ? 'V' : 'N';
328 const INTEGER N = T.numRows();
329 const INTEGER LDT = T.leadingDimension();
330 const INTEGER LDQ = Q.leadingDimension();
331 INTEGER IFST = iFirst;
332 INTEGER ILST = iLast;
333 INTEGER INFO;
334
335 if (IsSame<ElementType,DOUBLE>::value) {
336 LAPACK_IMPL(dtrexc)(&COMPQ,
337 &N,
338 T.data(),
339 &LDT,
340 Q.data(),
341 &LDQ,
342 &IFST,
343 &ILST,
344 work.data(),
345 &INFO);
346 } else {
347 ASSERT(0);
348 }
349 ASSERT(INFO>=0);
350
351 iFirst = IFST;
352 iLast = ILST;
353 return INFO;
354 }
355
356 #endif // CHECK_CXXLAPACK
357
358 //== public interface ==========================================================
359
360 template <typename MT, typename MQ, typename IndexType, typename VWORK>
361 IndexType
362 trexc(bool computeQ,
363 GeMatrix<MT> &T,
364 GeMatrix<MQ> &Q,
365 IndexType &iFirst,
366 IndexType &iLast,
367 DenseVector<VWORK> &work)
368 {
369 LAPACK_DEBUG_OUT("trexc");
370
371 //
372 // Test the input parameters
373 //
374 # ifndef NDEBUG
375 ASSERT(T.firstRow()==1);
376 ASSERT(T.firstCol()==1);
377 ASSERT(T.numRows()==T.numCols());
378
379 const IndexType n = T.numRows();
380
381 if (computeQ) {
382 ASSERT(Q.firstRow()==1);
383 ASSERT(Q.firstCol()==1);
384 ASSERT(Q.numRows()==Q.numCols());
385 ASSERT(Q.numRows()==n);
386 }
387
388 ASSERT(work.firstIndex()==1);
389 ASSERT(work.length()==n);
390 # endif
391
392 # ifdef CHECK_CXXLAPACK
393 //
394 // Make copies of output arguments
395 //
396 typename GeMatrix<MT>::NoView T_org = T;
397 typename GeMatrix<MQ>::NoView Q_org = Q;
398 IndexType iFirst_org = iFirst;
399 IndexType iLast_org = iLast;
400 typename DenseVector<VWORK>::NoView work_org = work;
401 # endif
402
403 //
404 // Call implementation
405 //
406 IndexType info = trexc_generic(computeQ, T, Q, iFirst, iLast, work);
407
408 # ifdef CHECK_CXXLAPACK
409 //
410 // Make copies of results computed by the generic implementation
411 //
412 typename GeMatrix<MT>::NoView T_generic = T;
413 typename GeMatrix<MQ>::NoView Q_generic = Q;
414 IndexType iFirst_generic = iFirst;
415 IndexType iLast_generic = iLast;
416 typename DenseVector<VWORK>::NoView work_generic = work;
417
418 //
419 // restore output arguments
420 //
421 T = T_org;
422 Q = Q_org;
423 iFirst = iFirst_org;
424 iLast = iLast_org;
425 work = work_org;
426
427 //
428 // Compare results
429 //
430 IndexType _info = trexc_native(computeQ, T, Q, iFirst, iLast, work);
431
432 bool failed = false;
433 if (! isIdentical(T_generic, T, "T_generic", "T")) {
434 std::cerr << "CXXLAPACK: T_generic = " << T_generic << std::endl;
435 std::cerr << "F77LAPACK: T = " << T << std::endl;
436 failed = true;
437 }
438
439 if (! isIdentical(Q_generic, Q, "Q_generic", "Q")) {
440 std::cerr << "CXXLAPACK: Q_generic = " << Q_generic << std::endl;
441 std::cerr << "F77LAPACK: Q = " << Q << std::endl;
442 failed = true;
443 }
444
445 if (! isIdentical(iFirst_generic, iFirst, "iFirst_generic", "iFirst")) {
446 std::cerr << "CXXLAPACK: iFirst_generic = "
447 << iFirst_generic << std::endl;
448 std::cerr << "F77LAPACK: iFirst = "
449 << iFirst << std::endl;
450 failed = true;
451 }
452
453 if (! isIdentical(iLast_generic, iLast, "iLast_generic", "iLast")) {
454 std::cerr << "CXXLAPACK: iLast_generic = "
455 << iLast_generic << std::endl;
456 std::cerr << "F77LAPACK: iLast = " << iLast << std::endl;
457 failed = true;
458 }
459
460 if (! isIdentical(work_generic, work, "work_generic", "work")) {
461 std::cerr << "CXXLAPACK: work_generic = " << work_generic << std::endl;
462 std::cerr << "F77LAPACK: work = " << work << std::endl;
463 failed = true;
464 }
465
466 if (! isIdentical(info, _info, " info", "_info")) {
467 std::cerr << "CXXLAPACK: info = " << info << std::endl;
468 std::cerr << "F77LAPACK: _info = " << _info << std::endl;
469 failed = true;
470 }
471
472 if (failed) {
473 ASSERT(0);
474 }
475 # endif
476
477 return info;
478 }
479
480 //-- forwarding ----------------------------------------------------------------
481 template <typename MT, typename MQ, typename IndexType, typename VWORK>
482 IndexType
483 trexc(bool computeQ,
484 MT &&T,
485 MQ &&Q,
486 IndexType &iFirst,
487 IndexType &iLast,
488 VWORK &&work)
489 {
490 CHECKPOINT_ENTER;
491 const IndexType info = trexc(computeQ, T, Q, iFirst, iLast, work);
492 CHECKPOINT_LEAVE;
493
494 return info;
495 }
496
497 } } // namespace lapack, flens
498
499 #endif // FLENS_LAPACK_EIG_TREVC_TCC