1*bf2c3715SXin Li // This file is part of Eigen, a lightweight C++ template library
2*bf2c3715SXin Li // for linear algebra.
3*bf2c3715SXin Li //
4*bf2c3715SXin Li // Copyright (C) 2009-2010 Gael Guennebaud <[email protected]>
5*bf2c3715SXin Li //
6*bf2c3715SXin Li // This Source Code Form is subject to the terms of the Mozilla
7*bf2c3715SXin Li // Public License v. 2.0. If a copy of the MPL was not distributed
8*bf2c3715SXin Li // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9*bf2c3715SXin Li
10*bf2c3715SXin Li #include "common.h"
11*bf2c3715SXin Li
12*bf2c3715SXin Li template<typename Index, typename Scalar, int StorageOrder, bool ConjugateLhs, bool ConjugateRhs>
13*bf2c3715SXin Li struct general_matrix_vector_product_wrapper
14*bf2c3715SXin Li {
rungeneral_matrix_vector_product_wrapper15*bf2c3715SXin Li static void run(Index rows, Index cols,const Scalar *lhs, Index lhsStride, const Scalar *rhs, Index rhsIncr, Scalar* res, Index resIncr, Scalar alpha)
16*bf2c3715SXin Li {
17*bf2c3715SXin Li typedef internal::const_blas_data_mapper<Scalar,Index,StorageOrder> LhsMapper;
18*bf2c3715SXin Li typedef internal::const_blas_data_mapper<Scalar,Index,RowMajor> RhsMapper;
19*bf2c3715SXin Li
20*bf2c3715SXin Li internal::general_matrix_vector_product
21*bf2c3715SXin Li <Index,Scalar,LhsMapper,StorageOrder,ConjugateLhs,Scalar,RhsMapper,ConjugateRhs>::run(
22*bf2c3715SXin Li rows, cols, LhsMapper(lhs, lhsStride), RhsMapper(rhs, rhsIncr), res, resIncr, alpha);
23*bf2c3715SXin Li }
24*bf2c3715SXin Li };
25*bf2c3715SXin Li
EIGEN_BLAS_FUNC(gemv)26*bf2c3715SXin Li int EIGEN_BLAS_FUNC(gemv)(const char *opa, const int *m, const int *n, const RealScalar *palpha,
27*bf2c3715SXin Li const RealScalar *pa, const int *lda, const RealScalar *pb, const int *incb, const RealScalar *pbeta, RealScalar *pc, const int *incc)
28*bf2c3715SXin Li {
29*bf2c3715SXin Li typedef void (*functype)(int, int, const Scalar *, int, const Scalar *, int , Scalar *, int, Scalar);
30*bf2c3715SXin Li static const functype func[4] = {
31*bf2c3715SXin Li // array index: NOTR
32*bf2c3715SXin Li (general_matrix_vector_product_wrapper<int,Scalar,ColMajor,false,false>::run),
33*bf2c3715SXin Li // array index: TR
34*bf2c3715SXin Li (general_matrix_vector_product_wrapper<int,Scalar,RowMajor,false,false>::run),
35*bf2c3715SXin Li // array index: ADJ
36*bf2c3715SXin Li (general_matrix_vector_product_wrapper<int,Scalar,RowMajor,Conj ,false>::run),
37*bf2c3715SXin Li 0
38*bf2c3715SXin Li };
39*bf2c3715SXin Li
40*bf2c3715SXin Li const Scalar* a = reinterpret_cast<const Scalar*>(pa);
41*bf2c3715SXin Li const Scalar* b = reinterpret_cast<const Scalar*>(pb);
42*bf2c3715SXin Li Scalar* c = reinterpret_cast<Scalar*>(pc);
43*bf2c3715SXin Li Scalar alpha = *reinterpret_cast<const Scalar*>(palpha);
44*bf2c3715SXin Li Scalar beta = *reinterpret_cast<const Scalar*>(pbeta);
45*bf2c3715SXin Li
46*bf2c3715SXin Li // check arguments
47*bf2c3715SXin Li int info = 0;
48*bf2c3715SXin Li if(OP(*opa)==INVALID) info = 1;
49*bf2c3715SXin Li else if(*m<0) info = 2;
50*bf2c3715SXin Li else if(*n<0) info = 3;
51*bf2c3715SXin Li else if(*lda<std::max(1,*m)) info = 6;
52*bf2c3715SXin Li else if(*incb==0) info = 8;
53*bf2c3715SXin Li else if(*incc==0) info = 11;
54*bf2c3715SXin Li if(info)
55*bf2c3715SXin Li return xerbla_(SCALAR_SUFFIX_UP"GEMV ",&info,6);
56*bf2c3715SXin Li
57*bf2c3715SXin Li if(*m==0 || *n==0 || (alpha==Scalar(0) && beta==Scalar(1)))
58*bf2c3715SXin Li return 0;
59*bf2c3715SXin Li
60*bf2c3715SXin Li int actual_m = *m;
61*bf2c3715SXin Li int actual_n = *n;
62*bf2c3715SXin Li int code = OP(*opa);
63*bf2c3715SXin Li if(code!=NOTR)
64*bf2c3715SXin Li std::swap(actual_m,actual_n);
65*bf2c3715SXin Li
66*bf2c3715SXin Li const Scalar* actual_b = get_compact_vector(b,actual_n,*incb);
67*bf2c3715SXin Li Scalar* actual_c = get_compact_vector(c,actual_m,*incc);
68*bf2c3715SXin Li
69*bf2c3715SXin Li if(beta!=Scalar(1))
70*bf2c3715SXin Li {
71*bf2c3715SXin Li if(beta==Scalar(0)) make_vector(actual_c, actual_m).setZero();
72*bf2c3715SXin Li else make_vector(actual_c, actual_m) *= beta;
73*bf2c3715SXin Li }
74*bf2c3715SXin Li
75*bf2c3715SXin Li if(code>=4 || func[code]==0)
76*bf2c3715SXin Li return 0;
77*bf2c3715SXin Li
78*bf2c3715SXin Li func[code](actual_m, actual_n, a, *lda, actual_b, 1, actual_c, 1, alpha);
79*bf2c3715SXin Li
80*bf2c3715SXin Li if(actual_b!=b) delete[] actual_b;
81*bf2c3715SXin Li if(actual_c!=c) delete[] copy_back(actual_c,c,actual_m,*incc);
82*bf2c3715SXin Li
83*bf2c3715SXin Li return 1;
84*bf2c3715SXin Li }
85*bf2c3715SXin Li
EIGEN_BLAS_FUNC(trsv)86*bf2c3715SXin Li int EIGEN_BLAS_FUNC(trsv)(const char *uplo, const char *opa, const char *diag, const int *n, const RealScalar *pa, const int *lda, RealScalar *pb, const int *incb)
87*bf2c3715SXin Li {
88*bf2c3715SXin Li typedef void (*functype)(int, const Scalar *, int, Scalar *);
89*bf2c3715SXin Li static const functype func[16] = {
90*bf2c3715SXin Li // array index: NOTR | (UP << 2) | (NUNIT << 3)
91*bf2c3715SXin Li (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|0, false,ColMajor>::run),
92*bf2c3715SXin Li // array index: TR | (UP << 2) | (NUNIT << 3)
93*bf2c3715SXin Li (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|0, false,RowMajor>::run),
94*bf2c3715SXin Li // array index: ADJ | (UP << 2) | (NUNIT << 3)
95*bf2c3715SXin Li (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|0, Conj, RowMajor>::run),
96*bf2c3715SXin Li 0,
97*bf2c3715SXin Li // array index: NOTR | (LO << 2) | (NUNIT << 3)
98*bf2c3715SXin Li (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|0, false,ColMajor>::run),
99*bf2c3715SXin Li // array index: TR | (LO << 2) | (NUNIT << 3)
100*bf2c3715SXin Li (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|0, false,RowMajor>::run),
101*bf2c3715SXin Li // array index: ADJ | (LO << 2) | (NUNIT << 3)
102*bf2c3715SXin Li (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|0, Conj, RowMajor>::run),
103*bf2c3715SXin Li 0,
104*bf2c3715SXin Li // array index: NOTR | (UP << 2) | (UNIT << 3)
105*bf2c3715SXin Li (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|UnitDiag,false,ColMajor>::run),
106*bf2c3715SXin Li // array index: TR | (UP << 2) | (UNIT << 3)
107*bf2c3715SXin Li (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|UnitDiag,false,RowMajor>::run),
108*bf2c3715SXin Li // array index: ADJ | (UP << 2) | (UNIT << 3)
109*bf2c3715SXin Li (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|UnitDiag,Conj, RowMajor>::run),
110*bf2c3715SXin Li 0,
111*bf2c3715SXin Li // array index: NOTR | (LO << 2) | (UNIT << 3)
112*bf2c3715SXin Li (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|UnitDiag,false,ColMajor>::run),
113*bf2c3715SXin Li // array index: TR | (LO << 2) | (UNIT << 3)
114*bf2c3715SXin Li (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|UnitDiag,false,RowMajor>::run),
115*bf2c3715SXin Li // array index: ADJ | (LO << 2) | (UNIT << 3)
116*bf2c3715SXin Li (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|UnitDiag,Conj, RowMajor>::run),
117*bf2c3715SXin Li 0
118*bf2c3715SXin Li };
119*bf2c3715SXin Li
120*bf2c3715SXin Li const Scalar* a = reinterpret_cast<const Scalar*>(pa);
121*bf2c3715SXin Li Scalar* b = reinterpret_cast<Scalar*>(pb);
122*bf2c3715SXin Li
123*bf2c3715SXin Li int info = 0;
124*bf2c3715SXin Li if(UPLO(*uplo)==INVALID) info = 1;
125*bf2c3715SXin Li else if(OP(*opa)==INVALID) info = 2;
126*bf2c3715SXin Li else if(DIAG(*diag)==INVALID) info = 3;
127*bf2c3715SXin Li else if(*n<0) info = 4;
128*bf2c3715SXin Li else if(*lda<std::max(1,*n)) info = 6;
129*bf2c3715SXin Li else if(*incb==0) info = 8;
130*bf2c3715SXin Li if(info)
131*bf2c3715SXin Li return xerbla_(SCALAR_SUFFIX_UP"TRSV ",&info,6);
132*bf2c3715SXin Li
133*bf2c3715SXin Li Scalar* actual_b = get_compact_vector(b,*n,*incb);
134*bf2c3715SXin Li
135*bf2c3715SXin Li int code = OP(*opa) | (UPLO(*uplo) << 2) | (DIAG(*diag) << 3);
136*bf2c3715SXin Li func[code](*n, a, *lda, actual_b);
137*bf2c3715SXin Li
138*bf2c3715SXin Li if(actual_b!=b) delete[] copy_back(actual_b,b,*n,*incb);
139*bf2c3715SXin Li
140*bf2c3715SXin Li return 0;
141*bf2c3715SXin Li }
142*bf2c3715SXin Li
143*bf2c3715SXin Li
144*bf2c3715SXin Li
EIGEN_BLAS_FUNC(trmv)145*bf2c3715SXin Li int EIGEN_BLAS_FUNC(trmv)(const char *uplo, const char *opa, const char *diag, const int *n, const RealScalar *pa, const int *lda, RealScalar *pb, const int *incb)
146*bf2c3715SXin Li {
147*bf2c3715SXin Li typedef void (*functype)(int, int, const Scalar *, int, const Scalar *, int, Scalar *, int, const Scalar&);
148*bf2c3715SXin Li static const functype func[16] = {
149*bf2c3715SXin Li // array index: NOTR | (UP << 2) | (NUNIT << 3)
150*bf2c3715SXin Li (internal::triangular_matrix_vector_product<int,Upper|0, Scalar,false,Scalar,false,ColMajor>::run),
151*bf2c3715SXin Li // array index: TR | (UP << 2) | (NUNIT << 3)
152*bf2c3715SXin Li (internal::triangular_matrix_vector_product<int,Lower|0, Scalar,false,Scalar,false,RowMajor>::run),
153*bf2c3715SXin Li // array index: ADJ | (UP << 2) | (NUNIT << 3)
154*bf2c3715SXin Li (internal::triangular_matrix_vector_product<int,Lower|0, Scalar,Conj, Scalar,false,RowMajor>::run),
155*bf2c3715SXin Li 0,
156*bf2c3715SXin Li // array index: NOTR | (LO << 2) | (NUNIT << 3)
157*bf2c3715SXin Li (internal::triangular_matrix_vector_product<int,Lower|0, Scalar,false,Scalar,false,ColMajor>::run),
158*bf2c3715SXin Li // array index: TR | (LO << 2) | (NUNIT << 3)
159*bf2c3715SXin Li (internal::triangular_matrix_vector_product<int,Upper|0, Scalar,false,Scalar,false,RowMajor>::run),
160*bf2c3715SXin Li // array index: ADJ | (LO << 2) | (NUNIT << 3)
161*bf2c3715SXin Li (internal::triangular_matrix_vector_product<int,Upper|0, Scalar,Conj, Scalar,false,RowMajor>::run),
162*bf2c3715SXin Li 0,
163*bf2c3715SXin Li // array index: NOTR | (UP << 2) | (UNIT << 3)
164*bf2c3715SXin Li (internal::triangular_matrix_vector_product<int,Upper|UnitDiag,Scalar,false,Scalar,false,ColMajor>::run),
165*bf2c3715SXin Li // array index: TR | (UP << 2) | (UNIT << 3)
166*bf2c3715SXin Li (internal::triangular_matrix_vector_product<int,Lower|UnitDiag,Scalar,false,Scalar,false,RowMajor>::run),
167*bf2c3715SXin Li // array index: ADJ | (UP << 2) | (UNIT << 3)
168*bf2c3715SXin Li (internal::triangular_matrix_vector_product<int,Lower|UnitDiag,Scalar,Conj, Scalar,false,RowMajor>::run),
169*bf2c3715SXin Li 0,
170*bf2c3715SXin Li // array index: NOTR | (LO << 2) | (UNIT << 3)
171*bf2c3715SXin Li (internal::triangular_matrix_vector_product<int,Lower|UnitDiag,Scalar,false,Scalar,false,ColMajor>::run),
172*bf2c3715SXin Li // array index: TR | (LO << 2) | (UNIT << 3)
173*bf2c3715SXin Li (internal::triangular_matrix_vector_product<int,Upper|UnitDiag,Scalar,false,Scalar,false,RowMajor>::run),
174*bf2c3715SXin Li // array index: ADJ | (LO << 2) | (UNIT << 3)
175*bf2c3715SXin Li (internal::triangular_matrix_vector_product<int,Upper|UnitDiag,Scalar,Conj, Scalar,false,RowMajor>::run),
176*bf2c3715SXin Li 0
177*bf2c3715SXin Li };
178*bf2c3715SXin Li
179*bf2c3715SXin Li const Scalar* a = reinterpret_cast<const Scalar*>(pa);
180*bf2c3715SXin Li Scalar* b = reinterpret_cast<Scalar*>(pb);
181*bf2c3715SXin Li
182*bf2c3715SXin Li int info = 0;
183*bf2c3715SXin Li if(UPLO(*uplo)==INVALID) info = 1;
184*bf2c3715SXin Li else if(OP(*opa)==INVALID) info = 2;
185*bf2c3715SXin Li else if(DIAG(*diag)==INVALID) info = 3;
186*bf2c3715SXin Li else if(*n<0) info = 4;
187*bf2c3715SXin Li else if(*lda<std::max(1,*n)) info = 6;
188*bf2c3715SXin Li else if(*incb==0) info = 8;
189*bf2c3715SXin Li if(info)
190*bf2c3715SXin Li return xerbla_(SCALAR_SUFFIX_UP"TRMV ",&info,6);
191*bf2c3715SXin Li
192*bf2c3715SXin Li if(*n==0)
193*bf2c3715SXin Li return 1;
194*bf2c3715SXin Li
195*bf2c3715SXin Li Scalar* actual_b = get_compact_vector(b,*n,*incb);
196*bf2c3715SXin Li Matrix<Scalar,Dynamic,1> res(*n);
197*bf2c3715SXin Li res.setZero();
198*bf2c3715SXin Li
199*bf2c3715SXin Li int code = OP(*opa) | (UPLO(*uplo) << 2) | (DIAG(*diag) << 3);
200*bf2c3715SXin Li if(code>=16 || func[code]==0)
201*bf2c3715SXin Li return 0;
202*bf2c3715SXin Li
203*bf2c3715SXin Li func[code](*n, *n, a, *lda, actual_b, 1, res.data(), 1, Scalar(1));
204*bf2c3715SXin Li
205*bf2c3715SXin Li copy_back(res.data(),b,*n,*incb);
206*bf2c3715SXin Li if(actual_b!=b) delete[] actual_b;
207*bf2c3715SXin Li
208*bf2c3715SXin Li return 1;
209*bf2c3715SXin Li }
210*bf2c3715SXin Li
211*bf2c3715SXin Li /** GBMV performs one of the matrix-vector operations
212*bf2c3715SXin Li *
213*bf2c3715SXin Li * y := alpha*A*x + beta*y, or y := alpha*A'*x + beta*y,
214*bf2c3715SXin Li *
215*bf2c3715SXin Li * where alpha and beta are scalars, x and y are vectors and A is an
216*bf2c3715SXin Li * m by n band matrix, with kl sub-diagonals and ku super-diagonals.
217*bf2c3715SXin Li */
EIGEN_BLAS_FUNC(gbmv)218*bf2c3715SXin Li int EIGEN_BLAS_FUNC(gbmv)(char *trans, int *m, int *n, int *kl, int *ku, RealScalar *palpha, RealScalar *pa, int *lda,
219*bf2c3715SXin Li RealScalar *px, int *incx, RealScalar *pbeta, RealScalar *py, int *incy)
220*bf2c3715SXin Li {
221*bf2c3715SXin Li const Scalar* a = reinterpret_cast<const Scalar*>(pa);
222*bf2c3715SXin Li const Scalar* x = reinterpret_cast<const Scalar*>(px);
223*bf2c3715SXin Li Scalar* y = reinterpret_cast<Scalar*>(py);
224*bf2c3715SXin Li Scalar alpha = *reinterpret_cast<const Scalar*>(palpha);
225*bf2c3715SXin Li Scalar beta = *reinterpret_cast<const Scalar*>(pbeta);
226*bf2c3715SXin Li int coeff_rows = *kl+*ku+1;
227*bf2c3715SXin Li
228*bf2c3715SXin Li int info = 0;
229*bf2c3715SXin Li if(OP(*trans)==INVALID) info = 1;
230*bf2c3715SXin Li else if(*m<0) info = 2;
231*bf2c3715SXin Li else if(*n<0) info = 3;
232*bf2c3715SXin Li else if(*kl<0) info = 4;
233*bf2c3715SXin Li else if(*ku<0) info = 5;
234*bf2c3715SXin Li else if(*lda<coeff_rows) info = 8;
235*bf2c3715SXin Li else if(*incx==0) info = 10;
236*bf2c3715SXin Li else if(*incy==0) info = 13;
237*bf2c3715SXin Li if(info)
238*bf2c3715SXin Li return xerbla_(SCALAR_SUFFIX_UP"GBMV ",&info,6);
239*bf2c3715SXin Li
240*bf2c3715SXin Li if(*m==0 || *n==0 || (alpha==Scalar(0) && beta==Scalar(1)))
241*bf2c3715SXin Li return 0;
242*bf2c3715SXin Li
243*bf2c3715SXin Li int actual_m = *m;
244*bf2c3715SXin Li int actual_n = *n;
245*bf2c3715SXin Li if(OP(*trans)!=NOTR)
246*bf2c3715SXin Li std::swap(actual_m,actual_n);
247*bf2c3715SXin Li
248*bf2c3715SXin Li const Scalar* actual_x = get_compact_vector(x,actual_n,*incx);
249*bf2c3715SXin Li Scalar* actual_y = get_compact_vector(y,actual_m,*incy);
250*bf2c3715SXin Li
251*bf2c3715SXin Li if(beta!=Scalar(1))
252*bf2c3715SXin Li {
253*bf2c3715SXin Li if(beta==Scalar(0)) make_vector(actual_y, actual_m).setZero();
254*bf2c3715SXin Li else make_vector(actual_y, actual_m) *= beta;
255*bf2c3715SXin Li }
256*bf2c3715SXin Li
257*bf2c3715SXin Li ConstMatrixType mat_coeffs(a,coeff_rows,*n,*lda);
258*bf2c3715SXin Li
259*bf2c3715SXin Li int nb = std::min(*n,(*m)+(*ku));
260*bf2c3715SXin Li for(int j=0; j<nb; ++j)
261*bf2c3715SXin Li {
262*bf2c3715SXin Li int start = std::max(0,j - *ku);
263*bf2c3715SXin Li int end = std::min((*m)-1,j + *kl);
264*bf2c3715SXin Li int len = end - start + 1;
265*bf2c3715SXin Li int offset = (*ku) - j + start;
266*bf2c3715SXin Li if(OP(*trans)==NOTR)
267*bf2c3715SXin Li make_vector(actual_y+start,len) += (alpha*actual_x[j]) * mat_coeffs.col(j).segment(offset,len);
268*bf2c3715SXin Li else if(OP(*trans)==TR)
269*bf2c3715SXin Li actual_y[j] += alpha * ( mat_coeffs.col(j).segment(offset,len).transpose() * make_vector(actual_x+start,len) ).value();
270*bf2c3715SXin Li else
271*bf2c3715SXin Li actual_y[j] += alpha * ( mat_coeffs.col(j).segment(offset,len).adjoint() * make_vector(actual_x+start,len) ).value();
272*bf2c3715SXin Li }
273*bf2c3715SXin Li
274*bf2c3715SXin Li if(actual_x!=x) delete[] actual_x;
275*bf2c3715SXin Li if(actual_y!=y) delete[] copy_back(actual_y,y,actual_m,*incy);
276*bf2c3715SXin Li
277*bf2c3715SXin Li return 0;
278*bf2c3715SXin Li }
279*bf2c3715SXin Li
280*bf2c3715SXin Li #if 0
281*bf2c3715SXin Li /** TBMV performs one of the matrix-vector operations
282*bf2c3715SXin Li *
283*bf2c3715SXin Li * x := A*x, or x := A'*x,
284*bf2c3715SXin Li *
285*bf2c3715SXin Li * where x is an n element vector and A is an n by n unit, or non-unit,
286*bf2c3715SXin Li * upper or lower triangular band matrix, with ( k + 1 ) diagonals.
287*bf2c3715SXin Li */
288*bf2c3715SXin Li int EIGEN_BLAS_FUNC(tbmv)(char *uplo, char *opa, char *diag, int *n, int *k, RealScalar *pa, int *lda, RealScalar *px, int *incx)
289*bf2c3715SXin Li {
290*bf2c3715SXin Li Scalar* a = reinterpret_cast<Scalar*>(pa);
291*bf2c3715SXin Li Scalar* x = reinterpret_cast<Scalar*>(px);
292*bf2c3715SXin Li int coeff_rows = *k + 1;
293*bf2c3715SXin Li
294*bf2c3715SXin Li int info = 0;
295*bf2c3715SXin Li if(UPLO(*uplo)==INVALID) info = 1;
296*bf2c3715SXin Li else if(OP(*opa)==INVALID) info = 2;
297*bf2c3715SXin Li else if(DIAG(*diag)==INVALID) info = 3;
298*bf2c3715SXin Li else if(*n<0) info = 4;
299*bf2c3715SXin Li else if(*k<0) info = 5;
300*bf2c3715SXin Li else if(*lda<coeff_rows) info = 7;
301*bf2c3715SXin Li else if(*incx==0) info = 9;
302*bf2c3715SXin Li if(info)
303*bf2c3715SXin Li return xerbla_(SCALAR_SUFFIX_UP"TBMV ",&info,6);
304*bf2c3715SXin Li
305*bf2c3715SXin Li if(*n==0)
306*bf2c3715SXin Li return 0;
307*bf2c3715SXin Li
308*bf2c3715SXin Li int actual_n = *n;
309*bf2c3715SXin Li
310*bf2c3715SXin Li Scalar* actual_x = get_compact_vector(x,actual_n,*incx);
311*bf2c3715SXin Li
312*bf2c3715SXin Li MatrixType mat_coeffs(a,coeff_rows,*n,*lda);
313*bf2c3715SXin Li
314*bf2c3715SXin Li int ku = UPLO(*uplo)==UPPER ? *k : 0;
315*bf2c3715SXin Li int kl = UPLO(*uplo)==LOWER ? *k : 0;
316*bf2c3715SXin Li
317*bf2c3715SXin Li for(int j=0; j<*n; ++j)
318*bf2c3715SXin Li {
319*bf2c3715SXin Li int start = std::max(0,j - ku);
320*bf2c3715SXin Li int end = std::min((*m)-1,j + kl);
321*bf2c3715SXin Li int len = end - start + 1;
322*bf2c3715SXin Li int offset = (ku) - j + start;
323*bf2c3715SXin Li
324*bf2c3715SXin Li if(OP(*trans)==NOTR)
325*bf2c3715SXin Li make_vector(actual_y+start,len) += (alpha*actual_x[j]) * mat_coeffs.col(j).segment(offset,len);
326*bf2c3715SXin Li else if(OP(*trans)==TR)
327*bf2c3715SXin Li actual_y[j] += alpha * ( mat_coeffs.col(j).segment(offset,len).transpose() * make_vector(actual_x+start,len) ).value();
328*bf2c3715SXin Li else
329*bf2c3715SXin Li actual_y[j] += alpha * ( mat_coeffs.col(j).segment(offset,len).adjoint() * make_vector(actual_x+start,len) ).value();
330*bf2c3715SXin Li }
331*bf2c3715SXin Li
332*bf2c3715SXin Li if(actual_x!=x) delete[] actual_x;
333*bf2c3715SXin Li if(actual_y!=y) delete[] copy_back(actual_y,y,actual_m,*incy);
334*bf2c3715SXin Li
335*bf2c3715SXin Li return 0;
336*bf2c3715SXin Li }
337*bf2c3715SXin Li #endif
338*bf2c3715SXin Li
339*bf2c3715SXin Li /** DTBSV solves one of the systems of equations
340*bf2c3715SXin Li *
341*bf2c3715SXin Li * A*x = b, or A'*x = b,
342*bf2c3715SXin Li *
343*bf2c3715SXin Li * where b and x are n element vectors and A is an n by n unit, or
344*bf2c3715SXin Li * non-unit, upper or lower triangular band matrix, with ( k + 1 )
345*bf2c3715SXin Li * diagonals.
346*bf2c3715SXin Li *
347*bf2c3715SXin Li * No test for singularity or near-singularity is included in this
348*bf2c3715SXin Li * routine. Such tests must be performed before calling this routine.
349*bf2c3715SXin Li */
EIGEN_BLAS_FUNC(tbsv)350*bf2c3715SXin Li int EIGEN_BLAS_FUNC(tbsv)(char *uplo, char *op, char *diag, int *n, int *k, RealScalar *pa, int *lda, RealScalar *px, int *incx)
351*bf2c3715SXin Li {
352*bf2c3715SXin Li typedef void (*functype)(int, int, const Scalar *, int, Scalar *);
353*bf2c3715SXin Li static const functype func[16] = {
354*bf2c3715SXin Li // array index: NOTR | (UP << 2) | (NUNIT << 3)
355*bf2c3715SXin Li (internal::band_solve_triangular_selector<int,Upper|0, Scalar,false,Scalar,ColMajor>::run),
356*bf2c3715SXin Li // array index: TR | (UP << 2) | (NUNIT << 3)
357*bf2c3715SXin Li (internal::band_solve_triangular_selector<int,Lower|0, Scalar,false,Scalar,RowMajor>::run),
358*bf2c3715SXin Li // array index: ADJ | (UP << 2) | (NUNIT << 3)
359*bf2c3715SXin Li (internal::band_solve_triangular_selector<int,Lower|0, Scalar,Conj, Scalar,RowMajor>::run),
360*bf2c3715SXin Li 0,
361*bf2c3715SXin Li // array index: NOTR | (LO << 2) | (NUNIT << 3)
362*bf2c3715SXin Li (internal::band_solve_triangular_selector<int,Lower|0, Scalar,false,Scalar,ColMajor>::run),
363*bf2c3715SXin Li // array index: TR | (LO << 2) | (NUNIT << 3)
364*bf2c3715SXin Li (internal::band_solve_triangular_selector<int,Upper|0, Scalar,false,Scalar,RowMajor>::run),
365*bf2c3715SXin Li // array index: ADJ | (LO << 2) | (NUNIT << 3)
366*bf2c3715SXin Li (internal::band_solve_triangular_selector<int,Upper|0, Scalar,Conj, Scalar,RowMajor>::run),
367*bf2c3715SXin Li 0,
368*bf2c3715SXin Li // array index: NOTR | (UP << 2) | (UNIT << 3)
369*bf2c3715SXin Li (internal::band_solve_triangular_selector<int,Upper|UnitDiag,Scalar,false,Scalar,ColMajor>::run),
370*bf2c3715SXin Li // array index: TR | (UP << 2) | (UNIT << 3)
371*bf2c3715SXin Li (internal::band_solve_triangular_selector<int,Lower|UnitDiag,Scalar,false,Scalar,RowMajor>::run),
372*bf2c3715SXin Li // array index: ADJ | (UP << 2) | (UNIT << 3)
373*bf2c3715SXin Li (internal::band_solve_triangular_selector<int,Lower|UnitDiag,Scalar,Conj, Scalar,RowMajor>::run),
374*bf2c3715SXin Li 0,
375*bf2c3715SXin Li // array index: NOTR | (LO << 2) | (UNIT << 3)
376*bf2c3715SXin Li (internal::band_solve_triangular_selector<int,Lower|UnitDiag,Scalar,false,Scalar,ColMajor>::run),
377*bf2c3715SXin Li // array index: TR | (LO << 2) | (UNIT << 3)
378*bf2c3715SXin Li (internal::band_solve_triangular_selector<int,Upper|UnitDiag,Scalar,false,Scalar,RowMajor>::run),
379*bf2c3715SXin Li // array index: ADJ | (LO << 2) | (UNIT << 3)
380*bf2c3715SXin Li (internal::band_solve_triangular_selector<int,Upper|UnitDiag,Scalar,Conj, Scalar,RowMajor>::run),
381*bf2c3715SXin Li 0,
382*bf2c3715SXin Li };
383*bf2c3715SXin Li
384*bf2c3715SXin Li Scalar* a = reinterpret_cast<Scalar*>(pa);
385*bf2c3715SXin Li Scalar* x = reinterpret_cast<Scalar*>(px);
386*bf2c3715SXin Li int coeff_rows = *k+1;
387*bf2c3715SXin Li
388*bf2c3715SXin Li int info = 0;
389*bf2c3715SXin Li if(UPLO(*uplo)==INVALID) info = 1;
390*bf2c3715SXin Li else if(OP(*op)==INVALID) info = 2;
391*bf2c3715SXin Li else if(DIAG(*diag)==INVALID) info = 3;
392*bf2c3715SXin Li else if(*n<0) info = 4;
393*bf2c3715SXin Li else if(*k<0) info = 5;
394*bf2c3715SXin Li else if(*lda<coeff_rows) info = 7;
395*bf2c3715SXin Li else if(*incx==0) info = 9;
396*bf2c3715SXin Li if(info)
397*bf2c3715SXin Li return xerbla_(SCALAR_SUFFIX_UP"TBSV ",&info,6);
398*bf2c3715SXin Li
399*bf2c3715SXin Li if(*n==0 || (*k==0 && DIAG(*diag)==UNIT))
400*bf2c3715SXin Li return 0;
401*bf2c3715SXin Li
402*bf2c3715SXin Li int actual_n = *n;
403*bf2c3715SXin Li
404*bf2c3715SXin Li Scalar* actual_x = get_compact_vector(x,actual_n,*incx);
405*bf2c3715SXin Li
406*bf2c3715SXin Li int code = OP(*op) | (UPLO(*uplo) << 2) | (DIAG(*diag) << 3);
407*bf2c3715SXin Li if(code>=16 || func[code]==0)
408*bf2c3715SXin Li return 0;
409*bf2c3715SXin Li
410*bf2c3715SXin Li func[code](*n, *k, a, *lda, actual_x);
411*bf2c3715SXin Li
412*bf2c3715SXin Li if(actual_x!=x) delete[] copy_back(actual_x,x,actual_n,*incx);
413*bf2c3715SXin Li
414*bf2c3715SXin Li return 0;
415*bf2c3715SXin Li }
416*bf2c3715SXin Li
417*bf2c3715SXin Li /** DTPMV performs one of the matrix-vector operations
418*bf2c3715SXin Li *
419*bf2c3715SXin Li * x := A*x, or x := A'*x,
420*bf2c3715SXin Li *
421*bf2c3715SXin Li * where x is an n element vector and A is an n by n unit, or non-unit,
422*bf2c3715SXin Li * upper or lower triangular matrix, supplied in packed form.
423*bf2c3715SXin Li */
EIGEN_BLAS_FUNC(tpmv)424*bf2c3715SXin Li int EIGEN_BLAS_FUNC(tpmv)(char *uplo, char *opa, char *diag, int *n, RealScalar *pap, RealScalar *px, int *incx)
425*bf2c3715SXin Li {
426*bf2c3715SXin Li typedef void (*functype)(int, const Scalar*, const Scalar*, Scalar*, Scalar);
427*bf2c3715SXin Li static const functype func[16] = {
428*bf2c3715SXin Li // array index: NOTR | (UP << 2) | (NUNIT << 3)
429*bf2c3715SXin Li (internal::packed_triangular_matrix_vector_product<int,Upper|0, Scalar,false,Scalar,false,ColMajor>::run),
430*bf2c3715SXin Li // array index: TR | (UP << 2) | (NUNIT << 3)
431*bf2c3715SXin Li (internal::packed_triangular_matrix_vector_product<int,Lower|0, Scalar,false,Scalar,false,RowMajor>::run),
432*bf2c3715SXin Li // array index: ADJ | (UP << 2) | (NUNIT << 3)
433*bf2c3715SXin Li (internal::packed_triangular_matrix_vector_product<int,Lower|0, Scalar,Conj, Scalar,false,RowMajor>::run),
434*bf2c3715SXin Li 0,
435*bf2c3715SXin Li // array index: NOTR | (LO << 2) | (NUNIT << 3)
436*bf2c3715SXin Li (internal::packed_triangular_matrix_vector_product<int,Lower|0, Scalar,false,Scalar,false,ColMajor>::run),
437*bf2c3715SXin Li // array index: TR | (LO << 2) | (NUNIT << 3)
438*bf2c3715SXin Li (internal::packed_triangular_matrix_vector_product<int,Upper|0, Scalar,false,Scalar,false,RowMajor>::run),
439*bf2c3715SXin Li // array index: ADJ | (LO << 2) | (NUNIT << 3)
440*bf2c3715SXin Li (internal::packed_triangular_matrix_vector_product<int,Upper|0, Scalar,Conj, Scalar,false,RowMajor>::run),
441*bf2c3715SXin Li 0,
442*bf2c3715SXin Li // array index: NOTR | (UP << 2) | (UNIT << 3)
443*bf2c3715SXin Li (internal::packed_triangular_matrix_vector_product<int,Upper|UnitDiag,Scalar,false,Scalar,false,ColMajor>::run),
444*bf2c3715SXin Li // array index: TR | (UP << 2) | (UNIT << 3)
445*bf2c3715SXin Li (internal::packed_triangular_matrix_vector_product<int,Lower|UnitDiag,Scalar,false,Scalar,false,RowMajor>::run),
446*bf2c3715SXin Li // array index: ADJ | (UP << 2) | (UNIT << 3)
447*bf2c3715SXin Li (internal::packed_triangular_matrix_vector_product<int,Lower|UnitDiag,Scalar,Conj, Scalar,false,RowMajor>::run),
448*bf2c3715SXin Li 0,
449*bf2c3715SXin Li // array index: NOTR | (LO << 2) | (UNIT << 3)
450*bf2c3715SXin Li (internal::packed_triangular_matrix_vector_product<int,Lower|UnitDiag,Scalar,false,Scalar,false,ColMajor>::run),
451*bf2c3715SXin Li // array index: TR | (LO << 2) | (UNIT << 3)
452*bf2c3715SXin Li (internal::packed_triangular_matrix_vector_product<int,Upper|UnitDiag,Scalar,false,Scalar,false,RowMajor>::run),
453*bf2c3715SXin Li // array index: ADJ | (LO << 2) | (UNIT << 3)
454*bf2c3715SXin Li (internal::packed_triangular_matrix_vector_product<int,Upper|UnitDiag,Scalar,Conj, Scalar,false,RowMajor>::run),
455*bf2c3715SXin Li 0
456*bf2c3715SXin Li };
457*bf2c3715SXin Li
458*bf2c3715SXin Li Scalar* ap = reinterpret_cast<Scalar*>(pap);
459*bf2c3715SXin Li Scalar* x = reinterpret_cast<Scalar*>(px);
460*bf2c3715SXin Li
461*bf2c3715SXin Li int info = 0;
462*bf2c3715SXin Li if(UPLO(*uplo)==INVALID) info = 1;
463*bf2c3715SXin Li else if(OP(*opa)==INVALID) info = 2;
464*bf2c3715SXin Li else if(DIAG(*diag)==INVALID) info = 3;
465*bf2c3715SXin Li else if(*n<0) info = 4;
466*bf2c3715SXin Li else if(*incx==0) info = 7;
467*bf2c3715SXin Li if(info)
468*bf2c3715SXin Li return xerbla_(SCALAR_SUFFIX_UP"TPMV ",&info,6);
469*bf2c3715SXin Li
470*bf2c3715SXin Li if(*n==0)
471*bf2c3715SXin Li return 1;
472*bf2c3715SXin Li
473*bf2c3715SXin Li Scalar* actual_x = get_compact_vector(x,*n,*incx);
474*bf2c3715SXin Li Matrix<Scalar,Dynamic,1> res(*n);
475*bf2c3715SXin Li res.setZero();
476*bf2c3715SXin Li
477*bf2c3715SXin Li int code = OP(*opa) | (UPLO(*uplo) << 2) | (DIAG(*diag) << 3);
478*bf2c3715SXin Li if(code>=16 || func[code]==0)
479*bf2c3715SXin Li return 0;
480*bf2c3715SXin Li
481*bf2c3715SXin Li func[code](*n, ap, actual_x, res.data(), Scalar(1));
482*bf2c3715SXin Li
483*bf2c3715SXin Li copy_back(res.data(),x,*n,*incx);
484*bf2c3715SXin Li if(actual_x!=x) delete[] actual_x;
485*bf2c3715SXin Li
486*bf2c3715SXin Li return 1;
487*bf2c3715SXin Li }
488*bf2c3715SXin Li
489*bf2c3715SXin Li /** DTPSV solves one of the systems of equations
490*bf2c3715SXin Li *
491*bf2c3715SXin Li * A*x = b, or A'*x = b,
492*bf2c3715SXin Li *
493*bf2c3715SXin Li * where b and x are n element vectors and A is an n by n unit, or
494*bf2c3715SXin Li * non-unit, upper or lower triangular matrix, supplied in packed form.
495*bf2c3715SXin Li *
496*bf2c3715SXin Li * No test for singularity or near-singularity is included in this
497*bf2c3715SXin Li * routine. Such tests must be performed before calling this routine.
498*bf2c3715SXin Li */
EIGEN_BLAS_FUNC(tpsv)499*bf2c3715SXin Li int EIGEN_BLAS_FUNC(tpsv)(char *uplo, char *opa, char *diag, int *n, RealScalar *pap, RealScalar *px, int *incx)
500*bf2c3715SXin Li {
501*bf2c3715SXin Li typedef void (*functype)(int, const Scalar*, Scalar*);
502*bf2c3715SXin Li static const functype func[16] = {
503*bf2c3715SXin Li // array index: NOTR | (UP << 2) | (NUNIT << 3)
504*bf2c3715SXin Li (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|0, false,ColMajor>::run),
505*bf2c3715SXin Li // array index: TR | (UP << 2) | (NUNIT << 3)
506*bf2c3715SXin Li (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|0, false,RowMajor>::run),
507*bf2c3715SXin Li // array index: ADJ | (UP << 2) | (NUNIT << 3)
508*bf2c3715SXin Li (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|0, Conj, RowMajor>::run),
509*bf2c3715SXin Li 0,
510*bf2c3715SXin Li // array index: NOTR | (LO << 2) | (NUNIT << 3)
511*bf2c3715SXin Li (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|0, false,ColMajor>::run),
512*bf2c3715SXin Li // array index: TR | (LO << 2) | (NUNIT << 3)
513*bf2c3715SXin Li (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|0, false,RowMajor>::run),
514*bf2c3715SXin Li // array index: ADJ | (LO << 2) | (NUNIT << 3)
515*bf2c3715SXin Li (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|0, Conj, RowMajor>::run),
516*bf2c3715SXin Li 0,
517*bf2c3715SXin Li // array index: NOTR | (UP << 2) | (UNIT << 3)
518*bf2c3715SXin Li (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|UnitDiag,false,ColMajor>::run),
519*bf2c3715SXin Li // array index: TR | (UP << 2) | (UNIT << 3)
520*bf2c3715SXin Li (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|UnitDiag,false,RowMajor>::run),
521*bf2c3715SXin Li // array index: ADJ | (UP << 2) | (UNIT << 3)
522*bf2c3715SXin Li (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|UnitDiag,Conj, RowMajor>::run),
523*bf2c3715SXin Li 0,
524*bf2c3715SXin Li // array index: NOTR | (LO << 2) | (UNIT << 3)
525*bf2c3715SXin Li (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|UnitDiag,false,ColMajor>::run),
526*bf2c3715SXin Li // array index: TR | (LO << 2) | (UNIT << 3)
527*bf2c3715SXin Li (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|UnitDiag,false,RowMajor>::run),
528*bf2c3715SXin Li // array index: ADJ | (LO << 2) | (UNIT << 3)
529*bf2c3715SXin Li (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|UnitDiag,Conj, RowMajor>::run),
530*bf2c3715SXin Li 0
531*bf2c3715SXin Li };
532*bf2c3715SXin Li
533*bf2c3715SXin Li Scalar* ap = reinterpret_cast<Scalar*>(pap);
534*bf2c3715SXin Li Scalar* x = reinterpret_cast<Scalar*>(px);
535*bf2c3715SXin Li
536*bf2c3715SXin Li int info = 0;
537*bf2c3715SXin Li if(UPLO(*uplo)==INVALID) info = 1;
538*bf2c3715SXin Li else if(OP(*opa)==INVALID) info = 2;
539*bf2c3715SXin Li else if(DIAG(*diag)==INVALID) info = 3;
540*bf2c3715SXin Li else if(*n<0) info = 4;
541*bf2c3715SXin Li else if(*incx==0) info = 7;
542*bf2c3715SXin Li if(info)
543*bf2c3715SXin Li return xerbla_(SCALAR_SUFFIX_UP"TPSV ",&info,6);
544*bf2c3715SXin Li
545*bf2c3715SXin Li Scalar* actual_x = get_compact_vector(x,*n,*incx);
546*bf2c3715SXin Li
547*bf2c3715SXin Li int code = OP(*opa) | (UPLO(*uplo) << 2) | (DIAG(*diag) << 3);
548*bf2c3715SXin Li func[code](*n, ap, actual_x);
549*bf2c3715SXin Li
550*bf2c3715SXin Li if(actual_x!=x) delete[] copy_back(actual_x,x,*n,*incx);
551*bf2c3715SXin Li
552*bf2c3715SXin Li return 1;
553*bf2c3715SXin Li }
554