comparison liboctave/CmplxQR.cc @ 8597:c86718093c1b

improve & fix QR classes
author Jaroslav Hajek <highegg@gmail.com>
date Tue, 27 Jan 2009 12:40:06 +0100
parents a6edd5c23cb5
children e9cb742df9eb
comparison
equal deleted inserted replaced
8596:8833c0b18eb2 8597:c86718093c1b
1 /* 1 /*
2 2
3 Copyright (C) 1994, 1995, 1996, 1997, 2002, 2003, 2004, 2005, 2007 3 Copyright (C) 1994, 1995, 1996, 1997, 2002, 2003, 2004, 2005, 2007
4 John W. Eaton 4 John W. Eaton
5 Copyright (C) 2008, 2009 Jaroslav Hajek 5 Copyright (C) 2008, 2009 Jaroslav Hajek
6 Copyright (C) 2009 VZLU Prague
6 7
7 This file is part of Octave. 8 This file is part of Octave.
8 9
9 Octave is free software; you can redistribute it and/or modify it 10 Octave is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the 11 under the terms of the GNU General Public License as published by the
91 ComplexQR::init (const ComplexMatrix& a, QR::type qr_type) 92 ComplexQR::init (const ComplexMatrix& a, QR::type qr_type)
92 { 93 {
93 octave_idx_type m = a.rows (); 94 octave_idx_type m = a.rows ();
94 octave_idx_type n = a.cols (); 95 octave_idx_type n = a.cols ();
95 96
96 if (m == 0 || n == 0)
97 {
98 (*current_liboctave_error_handler)
99 ("ComplexQR must have non-empty matrix");
100 return;
101 }
102
103 octave_idx_type min_mn = m < n ? m : n; 97 octave_idx_type min_mn = m < n ? m : n;
104 98 OCTAVE_LOCAL_BUFFER (Complex, tau, min_mn);
105 Array<Complex> tau (min_mn);
106 Complex *ptau = tau.fortran_vec ();
107
108 octave_idx_type lwork = 32*n;
109 Array<Complex> work (lwork);
110 Complex *pwork = work.fortran_vec ();
111 99
112 octave_idx_type info = 0; 100 octave_idx_type info = 0;
113 101
114 ComplexMatrix A_fact; 102 ComplexMatrix afact = a;
115 if (m > n && qr_type != QR::economy) 103 if (m > n && qr_type == QR::std)
116 { 104 afact.resize (m, m);
117 A_fact.resize (m, m); 105
118 A_fact.insert (a, 0, 0); 106 if (m > 0)
119 } 107 {
120 else 108 // workspace query.
121 A_fact = a; 109 Complex clwork;
122 110 F77_XFCN (zgeqrf, ZGEQRF, (m, n, afact.fortran_vec (), m, tau, &clwork, -1, info));
123 Complex *tmp_data = A_fact.fortran_vec (); 111
124 112 // allocate buffer and do the job.
125 F77_XFCN (zgeqrf, ZGEQRF, (m, n, tmp_data, m, ptau, pwork, lwork, info)); 113 octave_idx_type lwork = clwork.real (); lwork = std::max (lwork, 1);
114 OCTAVE_LOCAL_BUFFER (Complex, work, lwork);
115 F77_XFCN (zgeqrf, ZGEQRF, (m, n, afact.fortran_vec (), m, tau, work, lwork, info));
116 }
117
118 form (n, afact, tau, qr_type);
119 }
120
121 void ComplexQR::form (octave_idx_type n, ComplexMatrix& afact,
122 Complex *tau, QR::type qr_type)
123 {
124 octave_idx_type m = afact.rows (), min_mn = std::min (m, n);
125 octave_idx_type info;
126 126
127 if (qr_type == QR::raw) 127 if (qr_type == QR::raw)
128 { 128 {
129 for (octave_idx_type j = 0; j < min_mn; j++) 129 for (octave_idx_type j = 0; j < min_mn; j++)
130 { 130 {
131 octave_idx_type limit = j < min_mn - 1 ? j : min_mn - 1; 131 octave_idx_type limit = j < min_mn - 1 ? j : min_mn - 1;
132 for (octave_idx_type i = limit + 1; i < m; i++) 132 for (octave_idx_type i = limit + 1; i < m; i++)
133 A_fact.elem (i, j) *= tau.elem (j); 133 afact.elem (i, j) *= tau[j];
134 } 134 }
135 135
136 r = A_fact; 136 r = afact;
137 137 }
138 if (m > n) 138 else
139 r.resize (m, n); 139 {
140 } 140 // Attempt to minimize copying.
141 else 141 if (m >= n)
142 { 142 {
143 octave_idx_type n2 = (qr_type == QR::economy) ? min_mn : m; 143 // afact will become q.
144 144 q = afact;
145 if (qr_type == QR::economy && m > n) 145 octave_idx_type k = qr_type == QR::economy ? n : m;
146 r.resize (n, n, 0.0); 146 r = ComplexMatrix (k, n);
147 for (octave_idx_type j = 0; j < n; j++)
148 {
149 octave_idx_type i = 0;
150 for (; i <= j; i++)
151 r.xelem (i, j) = afact.xelem (i, j);
152 for (;i < k; i++)
153 r.xelem (i, j) = 0;
154 }
155 afact = ComplexMatrix (); // optimize memory
156 }
147 else 157 else
148 r.resize (m, n, 0.0); 158 {
149 159 // afact will become r.
150 for (octave_idx_type j = 0; j < n; j++) 160 q = ComplexMatrix (m, m);
151 { 161 for (octave_idx_type j = 0; j < m; j++)
152 octave_idx_type limit = j < min_mn-1 ? j : min_mn-1; 162 for (octave_idx_type i = j + 1; i < m; i++)
153 for (octave_idx_type i = 0; i <= limit; i++) 163 {
154 r.elem (i, j) = A_fact.elem (i, j); 164 q.xelem (i, j) = afact.xelem (i, j);
155 } 165 afact.xelem (i, j) = 0;
156 166 }
157 lwork = 32 * n2; 167 r = afact;
158 work.resize (lwork); 168 }
159 Complex *pwork2 = work.fortran_vec (); 169
160 170
161 F77_XFCN (zungqr, ZUNGQR, (m, n2, min_mn, tmp_data, m, ptau, 171 if (m > 0)
162 pwork2, lwork, info)); 172 {
163 173 octave_idx_type k = q.columns ();
164 q = A_fact; 174 // workspace query.
165 q.resize (m, n2); 175 Complex clwork;
176 F77_XFCN (zungqr, ZUNGQR, (m, k, min_mn, q.fortran_vec (), m, tau,
177 &clwork, -1, info));
178
179 // allocate buffer and do the job.
180 octave_idx_type lwork = clwork.real (); lwork = std::max (lwork, 1);
181 OCTAVE_LOCAL_BUFFER (Complex, work, lwork);
182 F77_XFCN (zungqr, ZUNGQR, (m, k, min_mn, q.fortran_vec (), m, tau,
183 work, lwork, info));
184 }
166 } 185 }
167 } 186 }
168 187
169 ComplexQR::ComplexQR (const ComplexMatrix& q_arg, const ComplexMatrix& r_arg) 188 ComplexQR::ComplexQR (const ComplexMatrix& q_arg, const ComplexMatrix& r_arg)
170 { 189 {