fml  0.1-0
Fused Matrix Library
qr.hh
1 // This file is part of fml which is released under the Boost Software
2 // License, Version 1.0. See accompanying file LICENSE or copy at
3 // https://www.boost.org/LICENSE_1_0.txt
4 
5 #ifndef FML_CPU_LINALG_LINALG_QR_H
6 #define FML_CPU_LINALG_LINALG_QR_H
7 #pragma once
8 
9 
10 #include <cmath>
11 #include <stdexcept>
12 
13 #include "../../_internals/linalgutils.hh"
14 #include "../../_internals/omp.hh"
15 
16 #include "../internals/cpu_utils.hh"
17 
18 #include "../copy.hh"
19 #include "../cpumat.hh"
20 #include "../cpuvec.hh"
21 
22 #include "internals/lapack.hh"
23 
24 
25 namespace fml
26 {
27 namespace linalg
28 {
29  namespace
30  {
31  template <typename REAL>
32  void qr_internals(const bool pivot, cpumat<REAL> &x, cpuvec<REAL> &qraux, cpuvec<REAL> &work)
33  {
34  const len_t m = x.nrows();
35  const len_t n = x.ncols();
36  const len_t minmn = std::min(m, n);
37 
38  int info = 0;
39  qraux.resize(minmn);
40 
41  REAL tmp;
42  if (pivot)
43  fml::lapack::geqp3(m, n, NULL, m, NULL, NULL, &tmp, -1, &info);
44  else
45  fml::lapack::geqrf(m, n, NULL, m, NULL, &tmp, -1, &info);
46 
47  int lwork = std::max((int) tmp, 1);
48  if (lwork > work.size())
49  work.resize(lwork);
50 
51  if (pivot)
52  {
53  cpuvec<int> p(n);
54  p.fill_zero();
55  fml::lapack::geqp3(m, n, x.data_ptr(), m, p.data_ptr(), qraux.data_ptr(), work.data_ptr(), lwork, &info);
56  }
57  else
58  fml::lapack::geqrf(m, n, x.data_ptr(), m, qraux.data_ptr(), work.data_ptr(), lwork, &info);
59 
60  if (info != 0)
61  {
62  if (pivot)
63  fml::linalgutils::check_info(info, "geqp3");
64  else
65  fml::linalgutils::check_info(info, "geqrf");
66  }
67  }
68  }
69 
93  template <typename REAL>
94  void qr(const bool pivot, cpumat<REAL> &x, cpuvec<REAL> &qraux)
95  {
96  cpuvec<REAL> work;
97  qr_internals(pivot, x, qraux, work);
98  }
99 
119  template <typename REAL>
120  void qr_Q(const cpumat<REAL> &QR, const cpuvec<REAL> &qraux, cpumat<REAL> &Q,
121  cpuvec<REAL> &work)
122  {
123  const len_t m = QR.nrows();
124  const len_t n = QR.ncols();
125  const len_t minmn = std::min(m, n);
126 
127  int info = 0;
128  REAL tmp;
129  fml::lapack::orgqr(m, minmn, minmn, QR.data_ptr(), m, NULL,
130  &tmp, -1, &info);
131 
132  int lwork = (int) tmp;
133  if (lwork > work.size())
134  work.resize(lwork);
135 
136  Q.resize(m, minmn);
137  fml::lapack::lacpy('A', m, minmn, QR.data_ptr(), m, Q.data_ptr(), m);
138 
139  fml::lapack::orgqr(m, minmn, minmn, Q.data_ptr(), m, qraux.data_ptr(),
140  work.data_ptr(), lwork, &info);
141  fml::linalgutils::check_info(info, "orgqr");
142  }
143 
161  template <typename REAL>
162  void qr_R(const cpumat<REAL> &QR, cpumat<REAL> &R)
163  {
164  const len_t m = QR.nrows();
165  const len_t n = QR.ncols();
166  const len_t minmn = std::min(m, n);
167 
168  R.resize(minmn, n);
169  R.fill_zero();
170  fml::lapack::lacpy('U', m, n, QR.data_ptr(), m, R.data_ptr(), minmn);
171  }
172 
173 
174 
175  namespace
176  {
177  template <typename REAL>
178  void lq_internals(cpumat<REAL> &x, cpuvec<REAL> &lqaux, cpuvec<REAL> &work)
179  {
180  const len_t m = x.nrows();
181  const len_t n = x.ncols();
182  const len_t minmn = std::min(m, n);
183 
184  int info = 0;
185  lqaux.resize(minmn);
186 
187  REAL tmp;
188  fml::lapack::gelqf(m, n, NULL, m, NULL, &tmp, -1, &info);
189  int lwork = std::max((int) tmp, 1);
190  if (lwork > work.size())
191  work.resize(lwork);
192 
193  fml::lapack::gelqf(m, n, x.data_ptr(), m, lqaux.data_ptr(), work.data_ptr(),
194  lwork, &info);
195 
196  if (info != 0)
197  fml::linalgutils::check_info(info, "gelqf");
198  }
199  }
200 
222  template <typename REAL>
223  void lq(cpumat<REAL> &x, cpuvec<REAL> &lqaux)
224  {
225  cpuvec<REAL> work;
226  lq_internals(x, lqaux, work);
227  }
228 
246  template <typename REAL>
247  void lq_L(const cpumat<REAL> &LQ, cpumat<REAL> &L)
248  {
249  const len_t m = LQ.nrows();
250  const len_t n = LQ.ncols();
251  const len_t minmn = std::min(m, n);
252 
253  L.resize(m, minmn);
254  L.fill_zero();
255 
256  fml::lapack::lacpy('L', m, n, LQ.data_ptr(), m, L.data_ptr(), m);
257  }
258 
278  template <typename REAL>
279  void lq_Q(const cpumat<REAL> &LQ, const cpuvec<REAL> &lqaux, cpumat<REAL> &Q,
280  cpuvec<REAL> &work)
281  {
282  const len_t m = LQ.nrows();
283  const len_t n = LQ.ncols();
284  const len_t minmn = std::min(m, n);
285 
286  int info = 0;
287  REAL tmp;
288  fml::lapack::orglq(minmn, n, minmn, LQ.data_ptr(), m, NULL,
289  &tmp, -1, &info);
290 
291  int lwork = (int) tmp;
292  if (lwork > work.size())
293  work.resize(lwork);
294 
295  Q.resize(minmn, n);
296  fml::lapack::lacpy('A', minmn, n, LQ.data_ptr(), m, Q.data_ptr(), minmn);
297 
298  fml::lapack::orglq(minmn, n, minmn, Q.data_ptr(), minmn, lqaux.data_ptr(),
299  work.data_ptr(), lwork, &info);
300  fml::linalgutils::check_info(info, "orglq");
301  }
302 }
303 }
304 
305 
306 #endif
fml::cpumat
Matrix class for data held on a single CPU.
Definition: cpumat.hh:36
fml::cpumat::fill_zero
void fill_zero()
Set all values to zero.
Definition: cpumat.hh:362
fml::univec::data_ptr
T * data_ptr()
Pointer to the internal array.
Definition: univec.hh:28
fml::unimat::nrows
len_t nrows() const
Number of rows.
Definition: unimat.hh:36
fml::cpuvec::resize
void resize(len_t size)
Resize the internal object storage.
Definition: cpuvec.hh:210
fml::linalg::qr
void qr(const bool pivot, cpumat< REAL > &x, cpuvec< REAL > &qraux)
Computes the QR decomposition.
Definition: qr.hh:94
fml::cpumat::resize
void resize(len_t nrows, len_t ncols)
Resize the internal object storage.
Definition: cpumat.hh:233
fml::cpuvec
Vector class for data held on a single CPU.
Definition: cpuvec.hh:31
fml::unimat::ncols
len_t ncols() const
Number of columns.
Definition: unimat.hh:38
fml::unimat::data_ptr
REAL * data_ptr()
Pointer to the internal array.
Definition: unimat.hh:40
fml::linalg::lq_L
void lq_L(const cpumat< REAL > &LQ, cpumat< REAL > &L)
Recover the L matrix from an LQ decomposition.
Definition: qr.hh:247
fml
Core namespace.
Definition: dimops.hh:10
fml::linalg::qr_Q
void qr_Q(const cpumat< REAL > &QR, const cpuvec< REAL > &qraux, cpumat< REAL > &Q, cpuvec< REAL > &work)
Recover the Q matrix from a QR decomposition.
Definition: qr.hh:120
fml::linalg::qr_R
void qr_R(const cpumat< REAL > &QR, cpumat< REAL > &R)
Recover the R matrix from a QR decomposition.
Definition: qr.hh:162
fml::linalg::lq
void lq(cpumat< REAL > &x, cpuvec< REAL > &lqaux)
Computes the LQ decomposition.
Definition: qr.hh:223
fml::linalg::lq_Q
void lq_Q(const cpumat< REAL > &LQ, const cpuvec< REAL > &lqaux, cpumat< REAL > &Q, cpuvec< REAL > &work)
Recover the Q matrix from an LQ decomposition.
Definition: qr.hh:279