// Copyright (C) 2003-2009 Marc Duruflé
// Copyright (C) 2001-2009 Vivien Mallet
//
// This file is part of the linear-algebra library Seldon,
// http://seldon.sourceforge.net/.
//
// Seldon is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 2.1 of the License, or (at your option)
// any later version.
//
// Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
// more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Seldon. If not, see http://www.gnu.org/licenses/.
#ifndef SELDON_FILE_LAPACK_LEAST_SQUARES_CXX
/*
Functions included in this file:
xGEQRF (GetQR, GetLQ)
xGELQF (GetQR, GetLQ)
xGEQP3 (GetQR_Pivot)
xORGQR (GetQ_FromQR)
xUNGQR (GetQ_FromQR)
xUNMQR (MltQ_FromQR)
xORMQR (MltQ_FromQR)
xORMQR + xTRSM (SolveQR)
ZUNMQR + ZTRSM (SolveQR)
xORMLQ + xTRSM (SolveQR)
ZUNMLQ + ZTRSM (SolveQR)
xTRSM + xORMLQ (SolveLQ)
ZTRSM + ZUNMLQ (SolveLQ)
xTRSM + xORMQR (SolveLQ)
ZTRSM + ZUNMQR (SolveLQ)
*/
namespace Seldon
{
///////////
// GETQR //
/*** ColMajor ***/
template<class Prop0, class Allocator0,
class Allocator1>
void GetQR(Matrix<float, Prop0, ColMajor, Allocator0>& A,
Vector<float, VectFull, Allocator1>& tau,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int lwork = max(m,n);
Vector<float, VectFull, Allocator1> work(lwork);
tau.Reallocate(min(m, n));
sgeqrf_(&m, &n, A.GetData(), &m, tau.GetData(),
work.GetData(), &lwork, &info.GetInfoRef());
}
template<class Prop0, class Allocator0,
class Allocator1>
void GetQR(Matrix<double, Prop0, ColMajor, Allocator0>& A,
Vector<double, VectFull, Allocator1>& tau,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int lwork = max(m,n);
Vector<double, VectFull, Allocator1> work(lwork);
tau.Reallocate(min(m, n));
dgeqrf_(&m, &n, A.GetData(), &m, tau.GetData(),
work.GetData(), &lwork, &info.GetInfoRef());
}
template<class Prop0, class Allocator0,
class Allocator1>
void GetQR(Matrix<complex<double>, Prop0, ColMajor, Allocator0>& A,
Vector<complex<double>, VectFull, Allocator1>& tau,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int lwork = max(m,n);
Vector<complex<double>, VectFull, Allocator1> work(lwork);
tau.Reallocate(min(m, n));
zgeqrf_(&m, &n, A.GetData(), &m, tau.GetData(),
work.GetData(), &lwork, &info.GetInfoRef());
}
/*** RowMajor ***/
template<class Prop0, class Allocator0,
class Allocator1>
void GetQR(Matrix<float, Prop0, RowMajor, Allocator0>& A,
Vector<float, VectFull, Allocator1>& tau,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int lwork = max(m,n);
Vector<float, VectFull, Allocator1> work(lwork);
tau.Reallocate(min(m, n));
// Factorization LQ of A^t.
sgelqf_(&n, &m, A.GetData(), &n, tau.GetData(),
work.GetData(), &lwork, &info.GetInfoRef());
}
template<class Prop0, class Allocator0,
class Allocator1>
void GetQR(Matrix<double, Prop0, RowMajor, Allocator0>& A,
Vector<double, VectFull, Allocator1>& tau,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int lwork = max(m,n);
Vector<double, VectFull, Allocator1> work(lwork);
tau.Reallocate(min(m, n));
// Factorization LQ of A^t.
dgelqf_(&n, &m, A.GetData(), &n, tau.GetData(),
work.GetData(), &lwork, &info.GetInfoRef());
}
template<class Prop0, class Allocator0,
class Allocator1>
void GetQR(Matrix<complex<double>, Prop0, RowMajor, Allocator0>& A,
Vector<complex<double>, VectFull, Allocator1>& tau,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int lwork = max(m,n);
Vector<complex<double>, VectFull, Allocator1> work(lwork);
tau.Reallocate(min(m, n));
// Factorization LQ of A^t.
zgelqf_(&n, &m, A.GetData(), &n, tau.GetData(),
work.GetData(), &lwork, &info.GetInfoRef());
}
// GETQR //
///////////
/////////////////
// GETQR_PIVOT //
/*** ColMajor ***/
template<class Prop0, class Allocator0,
class Allocator1>
void GetQR_Pivot(Matrix<double, Prop0, ColMajor, Allocator0>& A,
Vector<double, VectFull, Allocator1>& tau,
Vector<int>& ipivot, LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int lwork = 4 * max(m, n);
ipivot.Fill(0);
Vector<double, VectFull, Allocator1> work(lwork);
tau.Reallocate(min(m, n));
dgeqp3_(&m, &n, A.GetData(), &m, ipivot.GetData(), tau.GetData(),
work.GetData(), &lwork, &info.GetInfoRef());
}
// GETQR_PIVOT //
/////////////////
/////////////////
// GETQ_FROMQR //
/*** ColMajor ***/
template<class Prop0, class Allocator0,
class Allocator1>
void GetQ_FromQR(Matrix<double, Prop0, ColMajor, Allocator0>& A,
Vector<double, VectFull, Allocator1>& tau,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int lwork = 2 * max(m, n);
Vector<double, VectFull, Allocator1> work(lwork);
dorgqr_(&m, &m, &n, A.GetData(), &m, tau.GetData(),
work.GetData(), &lwork, &info.GetInfoRef());
}
template<class Prop0, class Allocator0,
class Allocator1>
void GetQ_FromQR(Matrix<complex<double>, Prop0, ColMajor, Allocator0>& A,
Vector<complex<double>, VectFull, Allocator1>& tau,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int lwork = 2 * max(m, n);
Vector<double, VectFull, Allocator1> work(lwork);
zungqr_(&m, &m, &n, A.GetDataVoid(), &m, tau.GetData(),
work.GetData(), &lwork, &info.GetInfoRef());
}
template<class Prop0, class Allocator0,
class Allocator1, class Allocator2, class Side, class Trans>
void MltQ_FromQR(const Side& side, const Trans& trans,
Matrix<complex<double>, Prop0, ColMajor, Allocator0>& A,
Vector<complex<double>, VectFull, Allocator1>& tau,
Matrix<complex<double>, Prop0, ColMajor, Allocator2>& C,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int lwork = max(m, n);
Vector<double, VectFull, Allocator1> work(lwork);
char side_ = side.Char();
char trans_ = trans.Char();
int k = m;
if (side_ == 'R')
k = n;
zunmqr_(&side, &trans, &m, &n, &k, A.GetDataVoid(), &m, tau.GetDataVoid(),
C.GetDataVoid(), &m, work.GetData(), &lwork,
&info.GetInfoRef());
}
// GETQ_FROMQR //
/////////////////
///////////
// GETLQ //
/*** ColMajor ***/
template<class Prop0, class Allocator0,
class Allocator1>
void GetLQ(Matrix<float, Prop0, ColMajor, Allocator0>& A,
Vector<float, VectFull, Allocator1>& tau,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int lwork = max(m,n);
Vector<float, VectFull, Allocator1> work(lwork);
tau.Reallocate(min(m, n));
sgelqf_(&m, &n, A.GetData(), &m, tau.GetData(),
work.GetData(), &lwork, &info.GetInfoRef());
}
template<class Prop0, class Allocator0,
class Allocator1>
void GetLQ(Matrix<double, Prop0, ColMajor, Allocator0>& A,
Vector<double, VectFull, Allocator1>& tau,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int lwork = max(m,n);
Vector<double, VectFull, Allocator1> work(lwork);
tau.Reallocate(min(m, n));
dgelqf_(&m, &n, A.GetData(), &m, tau.GetData(),
work.GetData(), &lwork, &info.GetInfoRef());
}
template<class Prop0, class Allocator0,
class Allocator1>
void GetLQ(Matrix<complex<double>, Prop0, ColMajor, Allocator0>& A,
Vector<complex<double>, VectFull, Allocator1>& tau,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int lwork = max(m,n);
Vector<complex<double>, VectFull, Allocator1> work(lwork);
tau.Reallocate(min(m, n));
zgelqf_(&m, &n, A.GetData(), &m, tau.GetData(),
work.GetData(), &lwork, &info.GetInfoRef());
}
/*** RowMajor ***/
template<class Prop0, class Allocator0,
class Allocator1>
void GetLQ(Matrix<float, Prop0, RowMajor, Allocator0>& A,
Vector<float, VectFull, Allocator1>& tau,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int lwork = max(m,n);
Vector<float, VectFull, Allocator1> work(lwork);
tau.Reallocate(min(m, n));
// Factorization QR of A^t.
sgeqrf_(&n, &m, A.GetData(), &n, tau.GetData(),
work.GetData(), &lwork, &info.GetInfoRef());
}
template<class Prop0, class Allocator0,
class Allocator1>
void GetLQ(Matrix<double, Prop0, RowMajor, Allocator0>& A,
Vector<double, VectFull, Allocator1>& tau,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int lwork = max(m,n);
Vector<double, VectFull, Allocator1> work(lwork);
tau.Reallocate(min(m, n));
// Factorization LQ of A^t.
dgeqrf_(&n, &m, A.GetData(), &n, tau.GetData(),
work.GetData(), &lwork, &info.GetInfoRef());
}
template<class Prop0, class Allocator0,
class Allocator1>
void GetLQ(Matrix<complex<double>, Prop0, RowMajor, Allocator0>& A,
Vector<complex<double>, VectFull, Allocator1>& tau,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int lwork = max(m,n);
Vector<complex<double>, VectFull, Allocator1> work(lwork);
tau.Reallocate(min(m, n));
// Factorization LQ of A^t.
zgeqrf_(&n, &m, A.GetData(), &n, tau.GetData(),
work.GetData(), &lwork, &info.GetInfoRef());
}
// GETLQ //
///////////
/////////////////
// MLTQ_FROMQR //
/*** ColMajor ***/
template<class Prop0, class Allocator0,
class Allocator1, class Allocator2, class IsTranspose>
void MltQ_FromQR(Matrix<double, Prop0, ColMajor, Allocator0>& A,
const IsTranspose& trans,
Vector<double, VectFull, Allocator1>& tau,
Vector<double, VectFull, Allocator2>& b,
LapackInfo& info = lapack_info)
{
int m = b.GetM();
int n = 1;
int k = tau.GetM();
int lwork = max(m,n);
Vector<double, VectFull, Allocator1> work(lwork);
char side('L');
char trans_(trans);
dormqr_(&side, &trans_, &m, &n, &k, A.GetData(), &m, tau.GetData(),
b.GetData(), &m, work.GetData(), &lwork,
&info.GetInfoRef());
}
// MLTQ_FROMQR //
/////////////////
/////////////
// SOLVEQR //
/*** ColMajor ***/
template <class Prop0, class Allocator0,
class Allocator1,class Allocator2>
void SolveQR(const Matrix<float, Prop0, ColMajor, Allocator0>& A,
const Vector<float, VectFull, Allocator1>& tau,
Vector<float, VectFull, Allocator2>& b,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int k = tau.GetM();
int nrhs = 1, nb = b.GetM();
char side('L');
char trans('T');
int lwork = max(m, n);
Vector<float, VectFull, Allocator1> work(lwork);
// Computes Q^t b.
sormqr_(&side, &trans, &m, &nrhs, &k, A.GetData(),
&m, tau.GetData(), b.GetData(),
&m, work.GetData(), &lwork, &info.GetInfoRef());
b.Resize(n);
for (int i = nb; i < n; i++)
b(i) = 0;
// Then solves R x = Q^t b.
float alpha(1);
cblas_strsm(CblasColMajor, CblasLeft, CblasUpper, CblasNoTrans,
CblasNonUnit, b.GetM(), nrhs,
alpha, A.GetData(), A.GetM(), b.GetData(), b.GetM());
}
template <class Prop0, class Allocator0,
class Allocator1,class Allocator2>
void SolveQR(const Matrix<double, Prop0, ColMajor, Allocator0>& A,
const Vector<double, VectFull, Allocator1>& tau,
Vector<double, VectFull, Allocator2>& b,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int k = tau.GetM();
int nrhs = 1, nb = b.GetM();
char side('L');
char trans('T');
int lwork = max(m, n);
Vector<double, VectFull, Allocator1> work(lwork);
// Computes Q^t b.
dormqr_(&side, &trans, &lwork, &nrhs, &k, A.GetData(),
&m, tau.GetData(), b.GetData(),
&lwork, work.GetData(), &lwork, &info.GetInfoRef());
b.Resize(n);
for (int i = nb; i < n; i++)
b(i) = 0;
// Then solves R x = Q^t b.
double alpha(1);
cblas_dtrsm(CblasColMajor, CblasLeft, CblasUpper, CblasNoTrans,
CblasNonUnit, b.GetM(), nrhs,
alpha, A.GetData(), A.GetM(), b.GetData(), b.GetM());
}
template <class Prop0, class Allocator0,
class Allocator1,class Allocator2>
void SolveQR(const Matrix<complex<double>, Prop0, ColMajor, Allocator0>& A,
const Vector<complex<double>, VectFull, Allocator1>& tau,
Vector<complex<double>, VectFull, Allocator2>& b,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int k = tau.GetM();
int nrhs = 1, nb = b.GetM();
char side('L');
char trans('C');
int lwork = max(m, n);
Vector<complex<double>, VectFull, Allocator1> work(lwork);
// Computes Q^t b.
zunmqr_(&side, &trans, &m, &nrhs, &k, A.GetData(),
&m, tau.GetData(), b.GetData(),
&m, work.GetData(), &lwork, &info.GetInfoRef());
b.Resize(n);
for (int i = nb; i < n; i++)
b(i) = 0;
// Then solves R x = Q^t b.
complex<double> alpha(1);
cblas_ztrsm(CblasColMajor, CblasLeft, CblasUpper, CblasNoTrans,
CblasNonUnit, b.GetM(), nrhs,
&alpha, A.GetData(), A.GetM(), b.GetData(), b.GetM());
}
/*** RowMajor ***/
template <class Prop0, class Allocator0,
class Allocator1,class Allocator2>
void SolveQR(const Matrix<float, Prop0, RowMajor, Allocator0>& A,
const Vector<float, VectFull, Allocator1>& tau,
Vector<float, VectFull, Allocator2>& b,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int k = tau.GetM();
int nrhs = 1, nb = b.GetM();
char side('L');
char trans('N');
int lwork = max(m, n);
Vector<float, VectFull, Allocator1> work(lwork);
// Computes Q b.
sormlq_(&side, &trans, &m, &nrhs, &k, A.GetData(),
&n, tau.GetData(), b.GetData(),
&m, work.GetData(), &lwork, &info.GetInfoRef());
b.Resize(n);
for (int i = nb; i < n; i++)
b(i) = 0;
// Solves L^t y = b.
float alpha(1);
cblas_strsm(CblasColMajor, CblasLeft, CblasLower, CblasTrans,
CblasNonUnit, n, nrhs,
alpha, A.GetData(), n, b.GetData(), b.GetM());
}
template <class Prop0, class Allocator0,
class Allocator1,class Allocator2>
void SolveQR(const Matrix<double, Prop0, RowMajor, Allocator0>& A,
const Vector<double, VectFull, Allocator1>& tau,
Vector<double, VectFull, Allocator2>& b,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int k = tau.GetM();
int nrhs = 1, nb = b.GetM();
char side('L');
char trans('N');
int lwork = max(m, n);
Vector<double, VectFull, Allocator1> work(lwork);
// Computes Q b.
dormlq_(&side, &trans, &m, &nrhs, &k, A.GetData(),
&n, tau.GetData(), b.GetData(),
&m, work.GetData(), &lwork, &info.GetInfoRef());
b.Resize(n);
for (int i = nb; i < n; i++)
b(i) = 0;
// Solves L^t y = b.
double alpha(1);
cblas_dtrsm(CblasColMajor, CblasLeft, CblasLower, CblasTrans,
CblasNonUnit, n, nrhs,
alpha, A.GetData(), n, b.GetData(), b.GetM());
}
template <class Prop0, class Allocator0,
class Allocator1,class Allocator2>
void SolveQR(const Matrix<complex<double>, Prop0, RowMajor, Allocator0>& A,
const Vector<complex<double>, VectFull, Allocator1>& tau,
Vector<complex<double>, VectFull, Allocator2>& b,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int k = tau.GetM();
int nrhs = 1, nb = b.GetM();
char side('L');
char trans('N');
int lwork = max(m, n);
Vector<complex<double>, VectFull, Allocator1> work(lwork);
// Computes Q b.
zunmlq_(&side, &trans, &m, &nrhs, &k, A.GetData(),
&n, tau.GetData(), b.GetData(),
&m, work.GetData(), &lwork, &info.GetInfoRef());
b.Resize(n);
for (int i = nb; i < n; i++)
b(i) = 0;
// Solves L^t y = b.
complex<double> alpha(1);
cblas_ztrsm(CblasColMajor, CblasLeft, CblasLower, CblasTrans,
CblasNonUnit, n, nrhs,
&alpha, A.GetData(), n, b.GetData(), b.GetM());
}
// SOLVEQR //
/////////////
/////////////
// SOLVELQ //
/*** ColMajor ***/
template <class Prop0, class Allocator0,
class Allocator1,class Allocator2>
void SolveLQ(const Matrix<float, Prop0, ColMajor, Allocator0>& A,
const Vector<float, VectFull, Allocator1>& tau,
Vector<float, VectFull, Allocator2>& b,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int k = tau.GetM();
int nrhs = 1, nb = b.GetM();
char side('L');
char trans('T');
int lwork = max(m, n);
Vector<float, VectFull, Allocator1> work(lwork);
// Solves L y = b.
float alpha(1);
cblas_strsm(CblasColMajor, CblasLeft, CblasLower, CblasNoTrans,
CblasNonUnit, m, nrhs,
alpha, A.GetData(), m, b.GetData(), b.GetM());
b.Resize(n);
for (int i = nb; i < n; i++)
b(i) = 0;
// Computes Q^t b.
sormlq_(&side, &trans, &n, &nrhs, &k, A.GetData(),
&m, tau.GetData(), b.GetData(),
&n, work.GetData(), &lwork, &info.GetInfoRef());
}
template <class Prop0, class Allocator0,
class Allocator1,class Allocator2>
void SolveLQ(const Matrix<double, Prop0, ColMajor, Allocator0>& A,
const Vector<double, VectFull, Allocator1>& tau,
Vector<double, VectFull, Allocator2>& b,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int k = tau.GetM();
int nrhs = 1, nb = b.GetM();
char side('L');
char trans('T');
int lwork = max(m, n);
Vector<double, VectFull, Allocator1> work(lwork);
// Solves L y = b.
double alpha(1);
cblas_dtrsm(CblasColMajor, CblasLeft, CblasLower, CblasNoTrans,
CblasNonUnit, m, nrhs,
alpha, A.GetData(), m, b.GetData(), b.GetM());
b.Resize(n);
for (int i = nb; i < n; i++)
b(i) = 0;
// Computes Q^t b.
dormlq_(&side, &trans, &n, &nrhs, &k, A.GetData(),
&m, tau.GetData(), b.GetData(),
&n, work.GetData(), &lwork, &info.GetInfoRef());
}
template <class Prop0, class Allocator0,
class Allocator1,class Allocator2>
void SolveLQ(const Matrix<complex<double>, Prop0, ColMajor, Allocator0>& A,
const Vector<complex<double>, VectFull, Allocator1>& tau,
Vector<complex<double>, VectFull, Allocator2>& b,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int k = tau.GetM();
int nrhs = 1, nb = b.GetM();
char side('L');
char trans('C');
int lwork = max(m, n);
Vector<complex<double>, VectFull, Allocator1> work(lwork);
// Solve L y = b.
complex<double> alpha(1);
cblas_ztrsm(CblasColMajor, CblasLeft, CblasLower, CblasNoTrans,
CblasNonUnit, m, nrhs,
&alpha, A.GetData(), m, b.GetData(), b.GetM());
b.Resize(n);
for (int i = nb; i < n; i++)
b(i) = 0;
// Computes Q^t.
zunmlq_(&side, &trans, &n, &nrhs, &k, A.GetData(),
&m, tau.GetData(), b.GetData(),
&n, work.GetData(), &lwork, &info.GetInfoRef());
}
/*** RowMajor ***/
template <class Prop0, class Allocator0,
class Allocator1,class Allocator2>
void SolveLQ(const Matrix<float, Prop0, RowMajor, Allocator0>& A,
const Vector<float, VectFull, Allocator1>& tau,
Vector<float, VectFull, Allocator2>& b,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int k = tau.GetM();
int nrhs = 1, nb = b.GetM();
char side('L');
char trans('N');
int lwork = max(m, n);
Vector<float, VectFull, Allocator1> work(lwork);
// Solves R^t x = b.
float alpha(1);
cblas_strsm(CblasColMajor, CblasLeft, CblasUpper, CblasTrans,
CblasNonUnit, b.GetM(), nrhs,
alpha, A.GetData(), A.GetN(), b.GetData(), b.GetM());
b.Resize(n);
for (int i = nb; i < n; i++)
b(i) = 0;
// Multiplies by Q.
sormqr_(&side, &trans, &n, &nrhs, &k, A.GetData(),
&n, tau.GetData(), b.GetData(),
&n, work.GetData(), &lwork, &info.GetInfoRef());
}
template <class Prop0, class Allocator0,
class Allocator1,class Allocator2>
void SolveLQ(const Matrix<double, Prop0, RowMajor, Allocator0>& A,
const Vector<double, VectFull, Allocator1>& tau,
Vector<double, VectFull, Allocator2>& b,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int k = tau.GetM();
int nrhs = 1, nb = b.GetM();
char side('L');
char trans('N');
int lwork = max(m, n);
Vector<double, VectFull, Allocator1> work(lwork);
// Solves R^t x = b.
double alpha(1);
cblas_dtrsm(CblasColMajor, CblasLeft, CblasUpper, CblasTrans,
CblasNonUnit, b.GetM(), nrhs,
alpha, A.GetData(), A.GetN(), b.GetData(), b.GetM());
b.Resize(n);
for (int i = nb; i < n; i++)
b(i) = 0;
// Multiplies by Q.
dormqr_(&side, &trans, &n, &nrhs, &k, A.GetData(),
&n, tau.GetData(), b.GetData(),
&n, work.GetData(), &lwork, &info.GetInfoRef());
}
template <class Prop0, class Allocator0,
class Allocator1,class Allocator2>
void SolveLQ(const Matrix<complex<double>, Prop0, RowMajor, Allocator0>& A,
const Vector<complex<double>, VectFull, Allocator1>& tau,
Vector<complex<double>, VectFull, Allocator2>& b,
LapackInfo& info = lapack_info)
{
int m = A.GetM();
int n = A.GetN();
int k = tau.GetM();
int nrhs = 1, nb = b.GetM();
char side('L');
char trans('C');
int lwork = max(m, n);
Vector<complex<double>, VectFull, Allocator1> work(lwork);
// Solves R^t x = b.
complex<double> alpha(1);
cblas_ztrsm(CblasColMajor, CblasLeft, CblasUpper, CblasTrans,
CblasNonUnit, b.GetM(), nrhs,
&alpha, A.GetData(), A.GetN(), b.GetData(), b.GetM());
b.Resize(n);
for (int i = nb; i < n; i++)
b(i) = 0;
// Computes Q b.
zunmqr_(&side, &trans, &n, &nrhs, &k, A.GetData(),
&n, tau.GetData(), b.GetData(),
&n, work.GetData(), &lwork, &info.GetInfoRef());
}
// SOLVELQ //
/////////////
} // end namespace
#define SELDON_FILE_LAPACK_LEAST_SQUARES_CXX
#endif