blob: 173f40b441f679f24d32cfa80c601fd959a62412 [file] [log] [blame]
Brian Silverman72890c22015-09-19 14:37:37 -04001// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
5//
6// This Source Code Form is subject to the terms of the Mozilla
7// Public License v. 2.0. If a copy of the MPL was not distributed
8// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
10#include "common.h"
11
Austin Schuh189376f2018-12-20 22:11:15 +110012template<typename Index, typename Scalar, int StorageOrder, bool ConjugateLhs, bool ConjugateRhs>
13struct general_matrix_vector_product_wrapper
14{
15 static void run(Index rows, Index cols,const Scalar *lhs, Index lhsStride, const Scalar *rhs, Index rhsIncr, Scalar* res, Index resIncr, Scalar alpha)
16 {
17 typedef internal::const_blas_data_mapper<Scalar,Index,StorageOrder> LhsMapper;
18 typedef internal::const_blas_data_mapper<Scalar,Index,RowMajor> RhsMapper;
19
20 internal::general_matrix_vector_product
21 <Index,Scalar,LhsMapper,StorageOrder,ConjugateLhs,Scalar,RhsMapper,ConjugateRhs>::run(
22 rows, cols, LhsMapper(lhs, lhsStride), RhsMapper(rhs, rhsIncr), res, resIncr, alpha);
23 }
24};
25
26int EIGEN_BLAS_FUNC(gemv)(const char *opa, const int *m, const int *n, const RealScalar *palpha,
27 const RealScalar *pa, const int *lda, const RealScalar *pb, const int *incb, const RealScalar *pbeta, RealScalar *pc, const int *incc)
Brian Silverman72890c22015-09-19 14:37:37 -040028{
29 typedef void (*functype)(int, int, const Scalar *, int, const Scalar *, int , Scalar *, int, Scalar);
Austin Schuh189376f2018-12-20 22:11:15 +110030 static const functype func[4] = {
31 // array index: NOTR
32 (general_matrix_vector_product_wrapper<int,Scalar,ColMajor,false,false>::run),
33 // array index: TR
34 (general_matrix_vector_product_wrapper<int,Scalar,RowMajor,false,false>::run),
35 // array index: ADJ
36 (general_matrix_vector_product_wrapper<int,Scalar,RowMajor,Conj ,false>::run),
37 0
38 };
Brian Silverman72890c22015-09-19 14:37:37 -040039
Austin Schuh189376f2018-12-20 22:11:15 +110040 const Scalar* a = reinterpret_cast<const Scalar*>(pa);
41 const Scalar* b = reinterpret_cast<const Scalar*>(pb);
Brian Silverman72890c22015-09-19 14:37:37 -040042 Scalar* c = reinterpret_cast<Scalar*>(pc);
Austin Schuh189376f2018-12-20 22:11:15 +110043 Scalar alpha = *reinterpret_cast<const Scalar*>(palpha);
44 Scalar beta = *reinterpret_cast<const Scalar*>(pbeta);
Brian Silverman72890c22015-09-19 14:37:37 -040045
46 // check arguments
47 int info = 0;
48 if(OP(*opa)==INVALID) info = 1;
49 else if(*m<0) info = 2;
50 else if(*n<0) info = 3;
51 else if(*lda<std::max(1,*m)) info = 6;
52 else if(*incb==0) info = 8;
53 else if(*incc==0) info = 11;
54 if(info)
55 return xerbla_(SCALAR_SUFFIX_UP"GEMV ",&info,6);
56
57 if(*m==0 || *n==0 || (alpha==Scalar(0) && beta==Scalar(1)))
58 return 0;
59
60 int actual_m = *m;
61 int actual_n = *n;
62 int code = OP(*opa);
63 if(code!=NOTR)
64 std::swap(actual_m,actual_n);
65
Austin Schuh189376f2018-12-20 22:11:15 +110066 const Scalar* actual_b = get_compact_vector(b,actual_n,*incb);
Brian Silverman72890c22015-09-19 14:37:37 -040067 Scalar* actual_c = get_compact_vector(c,actual_m,*incc);
68
69 if(beta!=Scalar(1))
70 {
Austin Schuh189376f2018-12-20 22:11:15 +110071 if(beta==Scalar(0)) make_vector(actual_c, actual_m).setZero();
72 else make_vector(actual_c, actual_m) *= beta;
Brian Silverman72890c22015-09-19 14:37:37 -040073 }
74
75 if(code>=4 || func[code]==0)
76 return 0;
77
78 func[code](actual_m, actual_n, a, *lda, actual_b, 1, actual_c, 1, alpha);
79
80 if(actual_b!=b) delete[] actual_b;
81 if(actual_c!=c) delete[] copy_back(actual_c,c,actual_m,*incc);
82
83 return 1;
84}
85
Austin Schuh189376f2018-12-20 22:11:15 +110086int 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)
Brian Silverman72890c22015-09-19 14:37:37 -040087{
88 typedef void (*functype)(int, const Scalar *, int, Scalar *);
Austin Schuh189376f2018-12-20 22:11:15 +110089 static const functype func[16] = {
90 // array index: NOTR | (UP << 2) | (NUNIT << 3)
91 (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|0, false,ColMajor>::run),
92 // array index: TR | (UP << 2) | (NUNIT << 3)
93 (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|0, false,RowMajor>::run),
94 // array index: ADJ | (UP << 2) | (NUNIT << 3)
95 (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|0, Conj, RowMajor>::run),
96 0,
97 // array index: NOTR | (LO << 2) | (NUNIT << 3)
98 (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|0, false,ColMajor>::run),
99 // array index: TR | (LO << 2) | (NUNIT << 3)
100 (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|0, false,RowMajor>::run),
101 // array index: ADJ | (LO << 2) | (NUNIT << 3)
102 (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|0, Conj, RowMajor>::run),
103 0,
104 // array index: NOTR | (UP << 2) | (UNIT << 3)
105 (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|UnitDiag,false,ColMajor>::run),
106 // array index: TR | (UP << 2) | (UNIT << 3)
107 (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|UnitDiag,false,RowMajor>::run),
108 // array index: ADJ | (UP << 2) | (UNIT << 3)
109 (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|UnitDiag,Conj, RowMajor>::run),
110 0,
111 // array index: NOTR | (LO << 2) | (UNIT << 3)
112 (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|UnitDiag,false,ColMajor>::run),
113 // array index: TR | (LO << 2) | (UNIT << 3)
114 (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|UnitDiag,false,RowMajor>::run),
115 // array index: ADJ | (LO << 2) | (UNIT << 3)
116 (internal::triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|UnitDiag,Conj, RowMajor>::run),
117 0
118 };
Brian Silverman72890c22015-09-19 14:37:37 -0400119
Austin Schuh189376f2018-12-20 22:11:15 +1100120 const Scalar* a = reinterpret_cast<const Scalar*>(pa);
Brian Silverman72890c22015-09-19 14:37:37 -0400121 Scalar* b = reinterpret_cast<Scalar*>(pb);
122
123 int info = 0;
124 if(UPLO(*uplo)==INVALID) info = 1;
125 else if(OP(*opa)==INVALID) info = 2;
126 else if(DIAG(*diag)==INVALID) info = 3;
127 else if(*n<0) info = 4;
128 else if(*lda<std::max(1,*n)) info = 6;
129 else if(*incb==0) info = 8;
130 if(info)
131 return xerbla_(SCALAR_SUFFIX_UP"TRSV ",&info,6);
132
133 Scalar* actual_b = get_compact_vector(b,*n,*incb);
134
135 int code = OP(*opa) | (UPLO(*uplo) << 2) | (DIAG(*diag) << 3);
136 func[code](*n, a, *lda, actual_b);
137
138 if(actual_b!=b) delete[] copy_back(actual_b,b,*n,*incb);
139
140 return 0;
141}
142
143
144
Austin Schuh189376f2018-12-20 22:11:15 +1100145int 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)
Brian Silverman72890c22015-09-19 14:37:37 -0400146{
147 typedef void (*functype)(int, int, const Scalar *, int, const Scalar *, int, Scalar *, int, const Scalar&);
Austin Schuh189376f2018-12-20 22:11:15 +1100148 static const functype func[16] = {
149 // array index: NOTR | (UP << 2) | (NUNIT << 3)
150 (internal::triangular_matrix_vector_product<int,Upper|0, Scalar,false,Scalar,false,ColMajor>::run),
151 // array index: TR | (UP << 2) | (NUNIT << 3)
152 (internal::triangular_matrix_vector_product<int,Lower|0, Scalar,false,Scalar,false,RowMajor>::run),
153 // array index: ADJ | (UP << 2) | (NUNIT << 3)
154 (internal::triangular_matrix_vector_product<int,Lower|0, Scalar,Conj, Scalar,false,RowMajor>::run),
155 0,
156 // array index: NOTR | (LO << 2) | (NUNIT << 3)
157 (internal::triangular_matrix_vector_product<int,Lower|0, Scalar,false,Scalar,false,ColMajor>::run),
158 // array index: TR | (LO << 2) | (NUNIT << 3)
159 (internal::triangular_matrix_vector_product<int,Upper|0, Scalar,false,Scalar,false,RowMajor>::run),
160 // array index: ADJ | (LO << 2) | (NUNIT << 3)
161 (internal::triangular_matrix_vector_product<int,Upper|0, Scalar,Conj, Scalar,false,RowMajor>::run),
162 0,
163 // array index: NOTR | (UP << 2) | (UNIT << 3)
164 (internal::triangular_matrix_vector_product<int,Upper|UnitDiag,Scalar,false,Scalar,false,ColMajor>::run),
165 // array index: TR | (UP << 2) | (UNIT << 3)
166 (internal::triangular_matrix_vector_product<int,Lower|UnitDiag,Scalar,false,Scalar,false,RowMajor>::run),
167 // array index: ADJ | (UP << 2) | (UNIT << 3)
168 (internal::triangular_matrix_vector_product<int,Lower|UnitDiag,Scalar,Conj, Scalar,false,RowMajor>::run),
169 0,
170 // array index: NOTR | (LO << 2) | (UNIT << 3)
171 (internal::triangular_matrix_vector_product<int,Lower|UnitDiag,Scalar,false,Scalar,false,ColMajor>::run),
172 // array index: TR | (LO << 2) | (UNIT << 3)
173 (internal::triangular_matrix_vector_product<int,Upper|UnitDiag,Scalar,false,Scalar,false,RowMajor>::run),
174 // array index: ADJ | (LO << 2) | (UNIT << 3)
175 (internal::triangular_matrix_vector_product<int,Upper|UnitDiag,Scalar,Conj, Scalar,false,RowMajor>::run),
176 0
177 };
Brian Silverman72890c22015-09-19 14:37:37 -0400178
Austin Schuh189376f2018-12-20 22:11:15 +1100179 const Scalar* a = reinterpret_cast<const Scalar*>(pa);
Brian Silverman72890c22015-09-19 14:37:37 -0400180 Scalar* b = reinterpret_cast<Scalar*>(pb);
181
182 int info = 0;
183 if(UPLO(*uplo)==INVALID) info = 1;
184 else if(OP(*opa)==INVALID) info = 2;
185 else if(DIAG(*diag)==INVALID) info = 3;
186 else if(*n<0) info = 4;
187 else if(*lda<std::max(1,*n)) info = 6;
188 else if(*incb==0) info = 8;
189 if(info)
190 return xerbla_(SCALAR_SUFFIX_UP"TRMV ",&info,6);
191
192 if(*n==0)
193 return 1;
194
195 Scalar* actual_b = get_compact_vector(b,*n,*incb);
196 Matrix<Scalar,Dynamic,1> res(*n);
197 res.setZero();
198
199 int code = OP(*opa) | (UPLO(*uplo) << 2) | (DIAG(*diag) << 3);
200 if(code>=16 || func[code]==0)
201 return 0;
202
203 func[code](*n, *n, a, *lda, actual_b, 1, res.data(), 1, Scalar(1));
204
205 copy_back(res.data(),b,*n,*incb);
206 if(actual_b!=b) delete[] actual_b;
207
208 return 1;
209}
210
211/** GBMV performs one of the matrix-vector operations
212 *
213 * y := alpha*A*x + beta*y, or y := alpha*A'*x + beta*y,
214 *
215 * where alpha and beta are scalars, x and y are vectors and A is an
216 * m by n band matrix, with kl sub-diagonals and ku super-diagonals.
217 */
218int EIGEN_BLAS_FUNC(gbmv)(char *trans, int *m, int *n, int *kl, int *ku, RealScalar *palpha, RealScalar *pa, int *lda,
219 RealScalar *px, int *incx, RealScalar *pbeta, RealScalar *py, int *incy)
220{
Austin Schuh189376f2018-12-20 22:11:15 +1100221 const Scalar* a = reinterpret_cast<const Scalar*>(pa);
222 const Scalar* x = reinterpret_cast<const Scalar*>(px);
Brian Silverman72890c22015-09-19 14:37:37 -0400223 Scalar* y = reinterpret_cast<Scalar*>(py);
Austin Schuh189376f2018-12-20 22:11:15 +1100224 Scalar alpha = *reinterpret_cast<const Scalar*>(palpha);
225 Scalar beta = *reinterpret_cast<const Scalar*>(pbeta);
Brian Silverman72890c22015-09-19 14:37:37 -0400226 int coeff_rows = *kl+*ku+1;
Austin Schuh189376f2018-12-20 22:11:15 +1100227
Brian Silverman72890c22015-09-19 14:37:37 -0400228 int info = 0;
229 if(OP(*trans)==INVALID) info = 1;
230 else if(*m<0) info = 2;
231 else if(*n<0) info = 3;
232 else if(*kl<0) info = 4;
233 else if(*ku<0) info = 5;
234 else if(*lda<coeff_rows) info = 8;
235 else if(*incx==0) info = 10;
236 else if(*incy==0) info = 13;
237 if(info)
238 return xerbla_(SCALAR_SUFFIX_UP"GBMV ",&info,6);
Austin Schuh189376f2018-12-20 22:11:15 +1100239
Brian Silverman72890c22015-09-19 14:37:37 -0400240 if(*m==0 || *n==0 || (alpha==Scalar(0) && beta==Scalar(1)))
241 return 0;
Austin Schuh189376f2018-12-20 22:11:15 +1100242
Brian Silverman72890c22015-09-19 14:37:37 -0400243 int actual_m = *m;
244 int actual_n = *n;
245 if(OP(*trans)!=NOTR)
246 std::swap(actual_m,actual_n);
Austin Schuh189376f2018-12-20 22:11:15 +1100247
248 const Scalar* actual_x = get_compact_vector(x,actual_n,*incx);
Brian Silverman72890c22015-09-19 14:37:37 -0400249 Scalar* actual_y = get_compact_vector(y,actual_m,*incy);
Austin Schuh189376f2018-12-20 22:11:15 +1100250
Brian Silverman72890c22015-09-19 14:37:37 -0400251 if(beta!=Scalar(1))
252 {
Austin Schuh189376f2018-12-20 22:11:15 +1100253 if(beta==Scalar(0)) make_vector(actual_y, actual_m).setZero();
254 else make_vector(actual_y, actual_m) *= beta;
Brian Silverman72890c22015-09-19 14:37:37 -0400255 }
Austin Schuh189376f2018-12-20 22:11:15 +1100256
257 ConstMatrixType mat_coeffs(a,coeff_rows,*n,*lda);
258
Brian Silverman72890c22015-09-19 14:37:37 -0400259 int nb = std::min(*n,(*m)+(*ku));
260 for(int j=0; j<nb; ++j)
261 {
262 int start = std::max(0,j - *ku);
263 int end = std::min((*m)-1,j + *kl);
264 int len = end - start + 1;
265 int offset = (*ku) - j + start;
266 if(OP(*trans)==NOTR)
Austin Schuh189376f2018-12-20 22:11:15 +1100267 make_vector(actual_y+start,len) += (alpha*actual_x[j]) * mat_coeffs.col(j).segment(offset,len);
Brian Silverman72890c22015-09-19 14:37:37 -0400268 else if(OP(*trans)==TR)
Austin Schuh189376f2018-12-20 22:11:15 +1100269 actual_y[j] += alpha * ( mat_coeffs.col(j).segment(offset,len).transpose() * make_vector(actual_x+start,len) ).value();
Brian Silverman72890c22015-09-19 14:37:37 -0400270 else
Austin Schuh189376f2018-12-20 22:11:15 +1100271 actual_y[j] += alpha * ( mat_coeffs.col(j).segment(offset,len).adjoint() * make_vector(actual_x+start,len) ).value();
272 }
273
Brian Silverman72890c22015-09-19 14:37:37 -0400274 if(actual_x!=x) delete[] actual_x;
275 if(actual_y!=y) delete[] copy_back(actual_y,y,actual_m,*incy);
Austin Schuh189376f2018-12-20 22:11:15 +1100276
Brian Silverman72890c22015-09-19 14:37:37 -0400277 return 0;
278}
279
280#if 0
281/** TBMV performs one of the matrix-vector operations
282 *
283 * x := A*x, or x := A'*x,
284 *
285 * where x is an n element vector and A is an n by n unit, or non-unit,
286 * upper or lower triangular band matrix, with ( k + 1 ) diagonals.
287 */
288int EIGEN_BLAS_FUNC(tbmv)(char *uplo, char *opa, char *diag, int *n, int *k, RealScalar *pa, int *lda, RealScalar *px, int *incx)
289{
290 Scalar* a = reinterpret_cast<Scalar*>(pa);
291 Scalar* x = reinterpret_cast<Scalar*>(px);
292 int coeff_rows = *k + 1;
Austin Schuh189376f2018-12-20 22:11:15 +1100293
Brian Silverman72890c22015-09-19 14:37:37 -0400294 int info = 0;
295 if(UPLO(*uplo)==INVALID) info = 1;
296 else if(OP(*opa)==INVALID) info = 2;
297 else if(DIAG(*diag)==INVALID) info = 3;
298 else if(*n<0) info = 4;
299 else if(*k<0) info = 5;
300 else if(*lda<coeff_rows) info = 7;
301 else if(*incx==0) info = 9;
302 if(info)
303 return xerbla_(SCALAR_SUFFIX_UP"TBMV ",&info,6);
Austin Schuh189376f2018-12-20 22:11:15 +1100304
Brian Silverman72890c22015-09-19 14:37:37 -0400305 if(*n==0)
306 return 0;
Austin Schuh189376f2018-12-20 22:11:15 +1100307
Brian Silverman72890c22015-09-19 14:37:37 -0400308 int actual_n = *n;
Austin Schuh189376f2018-12-20 22:11:15 +1100309
Brian Silverman72890c22015-09-19 14:37:37 -0400310 Scalar* actual_x = get_compact_vector(x,actual_n,*incx);
Austin Schuh189376f2018-12-20 22:11:15 +1100311
Brian Silverman72890c22015-09-19 14:37:37 -0400312 MatrixType mat_coeffs(a,coeff_rows,*n,*lda);
Austin Schuh189376f2018-12-20 22:11:15 +1100313
Brian Silverman72890c22015-09-19 14:37:37 -0400314 int ku = UPLO(*uplo)==UPPER ? *k : 0;
315 int kl = UPLO(*uplo)==LOWER ? *k : 0;
Austin Schuh189376f2018-12-20 22:11:15 +1100316
Brian Silverman72890c22015-09-19 14:37:37 -0400317 for(int j=0; j<*n; ++j)
318 {
319 int start = std::max(0,j - ku);
320 int end = std::min((*m)-1,j + kl);
321 int len = end - start + 1;
322 int offset = (ku) - j + start;
Austin Schuh189376f2018-12-20 22:11:15 +1100323
Brian Silverman72890c22015-09-19 14:37:37 -0400324 if(OP(*trans)==NOTR)
Austin Schuh189376f2018-12-20 22:11:15 +1100325 make_vector(actual_y+start,len) += (alpha*actual_x[j]) * mat_coeffs.col(j).segment(offset,len);
Brian Silverman72890c22015-09-19 14:37:37 -0400326 else if(OP(*trans)==TR)
Austin Schuh189376f2018-12-20 22:11:15 +1100327 actual_y[j] += alpha * ( mat_coeffs.col(j).segment(offset,len).transpose() * make_vector(actual_x+start,len) ).value();
Brian Silverman72890c22015-09-19 14:37:37 -0400328 else
Austin Schuh189376f2018-12-20 22:11:15 +1100329 actual_y[j] += alpha * ( mat_coeffs.col(j).segment(offset,len).adjoint() * make_vector(actual_x+start,len) ).value();
330 }
331
Brian Silverman72890c22015-09-19 14:37:37 -0400332 if(actual_x!=x) delete[] actual_x;
333 if(actual_y!=y) delete[] copy_back(actual_y,y,actual_m,*incy);
Austin Schuh189376f2018-12-20 22:11:15 +1100334
Brian Silverman72890c22015-09-19 14:37:37 -0400335 return 0;
336}
337#endif
338
339/** DTBSV solves one of the systems of equations
340 *
341 * A*x = b, or A'*x = b,
342 *
343 * where b and x are n element vectors and A is an n by n unit, or
344 * non-unit, upper or lower triangular band matrix, with ( k + 1 )
345 * diagonals.
346 *
347 * No test for singularity or near-singularity is included in this
348 * routine. Such tests must be performed before calling this routine.
349 */
350int EIGEN_BLAS_FUNC(tbsv)(char *uplo, char *op, char *diag, int *n, int *k, RealScalar *pa, int *lda, RealScalar *px, int *incx)
351{
352 typedef void (*functype)(int, int, const Scalar *, int, Scalar *);
Austin Schuh189376f2018-12-20 22:11:15 +1100353 static const functype func[16] = {
354 // array index: NOTR | (UP << 2) | (NUNIT << 3)
355 (internal::band_solve_triangular_selector<int,Upper|0, Scalar,false,Scalar,ColMajor>::run),
356 // array index: TR | (UP << 2) | (NUNIT << 3)
357 (internal::band_solve_triangular_selector<int,Lower|0, Scalar,false,Scalar,RowMajor>::run),
358 // array index: ADJ | (UP << 2) | (NUNIT << 3)
359 (internal::band_solve_triangular_selector<int,Lower|0, Scalar,Conj, Scalar,RowMajor>::run),
360 0,
361 // array index: NOTR | (LO << 2) | (NUNIT << 3)
362 (internal::band_solve_triangular_selector<int,Lower|0, Scalar,false,Scalar,ColMajor>::run),
363 // array index: TR | (LO << 2) | (NUNIT << 3)
364 (internal::band_solve_triangular_selector<int,Upper|0, Scalar,false,Scalar,RowMajor>::run),
365 // array index: ADJ | (LO << 2) | (NUNIT << 3)
366 (internal::band_solve_triangular_selector<int,Upper|0, Scalar,Conj, Scalar,RowMajor>::run),
367 0,
368 // array index: NOTR | (UP << 2) | (UNIT << 3)
369 (internal::band_solve_triangular_selector<int,Upper|UnitDiag,Scalar,false,Scalar,ColMajor>::run),
370 // array index: TR | (UP << 2) | (UNIT << 3)
371 (internal::band_solve_triangular_selector<int,Lower|UnitDiag,Scalar,false,Scalar,RowMajor>::run),
372 // array index: ADJ | (UP << 2) | (UNIT << 3)
373 (internal::band_solve_triangular_selector<int,Lower|UnitDiag,Scalar,Conj, Scalar,RowMajor>::run),
374 0,
375 // array index: NOTR | (LO << 2) | (UNIT << 3)
376 (internal::band_solve_triangular_selector<int,Lower|UnitDiag,Scalar,false,Scalar,ColMajor>::run),
377 // array index: TR | (LO << 2) | (UNIT << 3)
378 (internal::band_solve_triangular_selector<int,Upper|UnitDiag,Scalar,false,Scalar,RowMajor>::run),
379 // array index: ADJ | (LO << 2) | (UNIT << 3)
380 (internal::band_solve_triangular_selector<int,Upper|UnitDiag,Scalar,Conj, Scalar,RowMajor>::run),
381 0,
382 };
Brian Silverman72890c22015-09-19 14:37:37 -0400383
384 Scalar* a = reinterpret_cast<Scalar*>(pa);
385 Scalar* x = reinterpret_cast<Scalar*>(px);
386 int coeff_rows = *k+1;
Austin Schuh189376f2018-12-20 22:11:15 +1100387
Brian Silverman72890c22015-09-19 14:37:37 -0400388 int info = 0;
389 if(UPLO(*uplo)==INVALID) info = 1;
390 else if(OP(*op)==INVALID) info = 2;
391 else if(DIAG(*diag)==INVALID) info = 3;
392 else if(*n<0) info = 4;
393 else if(*k<0) info = 5;
394 else if(*lda<coeff_rows) info = 7;
395 else if(*incx==0) info = 9;
396 if(info)
397 return xerbla_(SCALAR_SUFFIX_UP"TBSV ",&info,6);
Austin Schuh189376f2018-12-20 22:11:15 +1100398
Brian Silverman72890c22015-09-19 14:37:37 -0400399 if(*n==0 || (*k==0 && DIAG(*diag)==UNIT))
400 return 0;
Austin Schuh189376f2018-12-20 22:11:15 +1100401
Brian Silverman72890c22015-09-19 14:37:37 -0400402 int actual_n = *n;
Austin Schuh189376f2018-12-20 22:11:15 +1100403
Brian Silverman72890c22015-09-19 14:37:37 -0400404 Scalar* actual_x = get_compact_vector(x,actual_n,*incx);
Austin Schuh189376f2018-12-20 22:11:15 +1100405
Brian Silverman72890c22015-09-19 14:37:37 -0400406 int code = OP(*op) | (UPLO(*uplo) << 2) | (DIAG(*diag) << 3);
407 if(code>=16 || func[code]==0)
408 return 0;
409
410 func[code](*n, *k, a, *lda, actual_x);
Austin Schuh189376f2018-12-20 22:11:15 +1100411
Brian Silverman72890c22015-09-19 14:37:37 -0400412 if(actual_x!=x) delete[] copy_back(actual_x,x,actual_n,*incx);
Austin Schuh189376f2018-12-20 22:11:15 +1100413
Brian Silverman72890c22015-09-19 14:37:37 -0400414 return 0;
415}
416
417/** DTPMV performs one of the matrix-vector operations
418 *
419 * x := A*x, or x := A'*x,
420 *
421 * where x is an n element vector and A is an n by n unit, or non-unit,
422 * upper or lower triangular matrix, supplied in packed form.
423 */
424int EIGEN_BLAS_FUNC(tpmv)(char *uplo, char *opa, char *diag, int *n, RealScalar *pap, RealScalar *px, int *incx)
425{
426 typedef void (*functype)(int, const Scalar*, const Scalar*, Scalar*, Scalar);
Austin Schuh189376f2018-12-20 22:11:15 +1100427 static const functype func[16] = {
428 // array index: NOTR | (UP << 2) | (NUNIT << 3)
429 (internal::packed_triangular_matrix_vector_product<int,Upper|0, Scalar,false,Scalar,false,ColMajor>::run),
430 // array index: TR | (UP << 2) | (NUNIT << 3)
431 (internal::packed_triangular_matrix_vector_product<int,Lower|0, Scalar,false,Scalar,false,RowMajor>::run),
432 // array index: ADJ | (UP << 2) | (NUNIT << 3)
433 (internal::packed_triangular_matrix_vector_product<int,Lower|0, Scalar,Conj, Scalar,false,RowMajor>::run),
434 0,
435 // array index: NOTR | (LO << 2) | (NUNIT << 3)
436 (internal::packed_triangular_matrix_vector_product<int,Lower|0, Scalar,false,Scalar,false,ColMajor>::run),
437 // array index: TR | (LO << 2) | (NUNIT << 3)
438 (internal::packed_triangular_matrix_vector_product<int,Upper|0, Scalar,false,Scalar,false,RowMajor>::run),
439 // array index: ADJ | (LO << 2) | (NUNIT << 3)
440 (internal::packed_triangular_matrix_vector_product<int,Upper|0, Scalar,Conj, Scalar,false,RowMajor>::run),
441 0,
442 // array index: NOTR | (UP << 2) | (UNIT << 3)
443 (internal::packed_triangular_matrix_vector_product<int,Upper|UnitDiag,Scalar,false,Scalar,false,ColMajor>::run),
444 // array index: TR | (UP << 2) | (UNIT << 3)
445 (internal::packed_triangular_matrix_vector_product<int,Lower|UnitDiag,Scalar,false,Scalar,false,RowMajor>::run),
446 // array index: ADJ | (UP << 2) | (UNIT << 3)
447 (internal::packed_triangular_matrix_vector_product<int,Lower|UnitDiag,Scalar,Conj, Scalar,false,RowMajor>::run),
448 0,
449 // array index: NOTR | (LO << 2) | (UNIT << 3)
450 (internal::packed_triangular_matrix_vector_product<int,Lower|UnitDiag,Scalar,false,Scalar,false,ColMajor>::run),
451 // array index: TR | (LO << 2) | (UNIT << 3)
452 (internal::packed_triangular_matrix_vector_product<int,Upper|UnitDiag,Scalar,false,Scalar,false,RowMajor>::run),
453 // array index: ADJ | (LO << 2) | (UNIT << 3)
454 (internal::packed_triangular_matrix_vector_product<int,Upper|UnitDiag,Scalar,Conj, Scalar,false,RowMajor>::run),
455 0
456 };
Brian Silverman72890c22015-09-19 14:37:37 -0400457
458 Scalar* ap = reinterpret_cast<Scalar*>(pap);
459 Scalar* x = reinterpret_cast<Scalar*>(px);
460
461 int info = 0;
462 if(UPLO(*uplo)==INVALID) info = 1;
463 else if(OP(*opa)==INVALID) info = 2;
464 else if(DIAG(*diag)==INVALID) info = 3;
465 else if(*n<0) info = 4;
466 else if(*incx==0) info = 7;
467 if(info)
468 return xerbla_(SCALAR_SUFFIX_UP"TPMV ",&info,6);
469
470 if(*n==0)
471 return 1;
472
473 Scalar* actual_x = get_compact_vector(x,*n,*incx);
474 Matrix<Scalar,Dynamic,1> res(*n);
475 res.setZero();
476
477 int code = OP(*opa) | (UPLO(*uplo) << 2) | (DIAG(*diag) << 3);
478 if(code>=16 || func[code]==0)
479 return 0;
480
481 func[code](*n, ap, actual_x, res.data(), Scalar(1));
482
483 copy_back(res.data(),x,*n,*incx);
484 if(actual_x!=x) delete[] actual_x;
485
486 return 1;
487}
488
489/** DTPSV solves one of the systems of equations
490 *
491 * A*x = b, or A'*x = b,
492 *
493 * where b and x are n element vectors and A is an n by n unit, or
494 * non-unit, upper or lower triangular matrix, supplied in packed form.
495 *
496 * No test for singularity or near-singularity is included in this
497 * routine. Such tests must be performed before calling this routine.
498 */
499int EIGEN_BLAS_FUNC(tpsv)(char *uplo, char *opa, char *diag, int *n, RealScalar *pap, RealScalar *px, int *incx)
500{
501 typedef void (*functype)(int, const Scalar*, Scalar*);
Austin Schuh189376f2018-12-20 22:11:15 +1100502 static const functype func[16] = {
503 // array index: NOTR | (UP << 2) | (NUNIT << 3)
504 (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|0, false,ColMajor>::run),
505 // array index: TR | (UP << 2) | (NUNIT << 3)
506 (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|0, false,RowMajor>::run),
507 // array index: ADJ | (UP << 2) | (NUNIT << 3)
508 (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|0, Conj, RowMajor>::run),
509 0,
510 // array index: NOTR | (LO << 2) | (NUNIT << 3)
511 (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|0, false,ColMajor>::run),
512 // array index: TR | (LO << 2) | (NUNIT << 3)
513 (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|0, false,RowMajor>::run),
514 // array index: ADJ | (LO << 2) | (NUNIT << 3)
515 (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|0, Conj, RowMajor>::run),
516 0,
517 // array index: NOTR | (UP << 2) | (UNIT << 3)
518 (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|UnitDiag,false,ColMajor>::run),
519 // array index: TR | (UP << 2) | (UNIT << 3)
520 (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|UnitDiag,false,RowMajor>::run),
521 // array index: ADJ | (UP << 2) | (UNIT << 3)
522 (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|UnitDiag,Conj, RowMajor>::run),
523 0,
524 // array index: NOTR | (LO << 2) | (UNIT << 3)
525 (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Lower|UnitDiag,false,ColMajor>::run),
526 // array index: TR | (LO << 2) | (UNIT << 3)
527 (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|UnitDiag,false,RowMajor>::run),
528 // array index: ADJ | (LO << 2) | (UNIT << 3)
529 (internal::packed_triangular_solve_vector<Scalar,Scalar,int,OnTheLeft, Upper|UnitDiag,Conj, RowMajor>::run),
530 0
531 };
Brian Silverman72890c22015-09-19 14:37:37 -0400532
533 Scalar* ap = reinterpret_cast<Scalar*>(pap);
534 Scalar* x = reinterpret_cast<Scalar*>(px);
535
536 int info = 0;
537 if(UPLO(*uplo)==INVALID) info = 1;
538 else if(OP(*opa)==INVALID) info = 2;
539 else if(DIAG(*diag)==INVALID) info = 3;
540 else if(*n<0) info = 4;
541 else if(*incx==0) info = 7;
542 if(info)
543 return xerbla_(SCALAR_SUFFIX_UP"TPSV ",&info,6);
544
545 Scalar* actual_x = get_compact_vector(x,*n,*incx);
546
547 int code = OP(*opa) | (UPLO(*uplo) << 2) | (DIAG(*diag) << 3);
548 func[code](*n, ap, actual_x);
549
550 if(actual_x!=x) delete[] copy_back(actual_x,x,*n,*incx);
551
552 return 1;
553}