1 // This file is part of Eigen, a lightweight C++ template library
4 // Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
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/.
12 template<typename Index
, typename Scalar
, int StorageOrder
, bool ConjugateLhs
, bool ConjugateRhs
>
13 struct general_matrix_vector_product_wrapper
15 static void run(Index rows
, Index cols
,const Scalar
*lhs
, Index lhsStride
, const Scalar
*rhs
, Index rhsIncr
, Scalar
* res
, Index resIncr
, Scalar alpha
)
17 typedef internal::const_blas_data_mapper
<Scalar
,Index
,StorageOrder
> LhsMapper
;
18 typedef internal::const_blas_data_mapper
<Scalar
,Index
,RowMajor
> RhsMapper
;
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
);
26 int 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
)
29 typedef void (*functype
)(int, int, const Scalar
*, int, const Scalar
*, int , Scalar
*, int, Scalar
);
30 static const functype func
[4] = {
32 (general_matrix_vector_product_wrapper
<int,Scalar
,ColMajor
,false,false>::run
),
34 (general_matrix_vector_product_wrapper
<int,Scalar
,RowMajor
,false,false>::run
),
36 (general_matrix_vector_product_wrapper
<int,Scalar
,RowMajor
,Conj
,false>::run
),
40 const Scalar
* a
= reinterpret_cast<const Scalar
*>(pa
);
41 const Scalar
* b
= reinterpret_cast<const Scalar
*>(pb
);
42 Scalar
* c
= reinterpret_cast<Scalar
*>(pc
);
43 Scalar alpha
= *reinterpret_cast<const Scalar
*>(palpha
);
44 Scalar beta
= *reinterpret_cast<const Scalar
*>(pbeta
);
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;
55 return xerbla_(SCALAR_SUFFIX_UP
"GEMV ",&info
,6);
57 if(*m
==0 || *n
==0 || (alpha
==Scalar(0) && beta
==Scalar(1)))
64 std::swap(actual_m
,actual_n
);
66 const Scalar
* actual_b
= get_compact_vector(b
,actual_n
,*incb
);
67 Scalar
* actual_c
= get_compact_vector(c
,actual_m
,*incc
);
71 if(beta
==Scalar(0)) make_vector(actual_c
, actual_m
).setZero();
72 else make_vector(actual_c
, actual_m
) *= beta
;
75 if(code
>=4 || func
[code
]==0)
78 func
[code
](actual_m
, actual_n
, a
, *lda
, actual_b
, 1, actual_c
, 1, alpha
);
80 if(actual_b
!=b
) delete[] actual_b
;
81 if(actual_c
!=c
) delete[] copy_back(actual_c
,c
,actual_m
,*incc
);
86 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
)
88 typedef void (*functype
)(int, const Scalar
*, int, Scalar
*);
89 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
),
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
),
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
),
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
),
120 const Scalar
* a
= reinterpret_cast<const Scalar
*>(pa
);
121 Scalar
* b
= reinterpret_cast<Scalar
*>(pb
);
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;
131 return xerbla_(SCALAR_SUFFIX_UP
"TRSV ",&info
,6);
133 Scalar
* actual_b
= get_compact_vector(b
,*n
,*incb
);
135 int code
= OP(*opa
) | (UPLO(*uplo
) << 2) | (DIAG(*diag
) << 3);
136 func
[code
](*n
, a
, *lda
, actual_b
);
138 if(actual_b
!=b
) delete[] copy_back(actual_b
,b
,*n
,*incb
);
145 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
)
147 typedef void (*functype
)(int, int, const Scalar
*, int, const Scalar
*, int, Scalar
*, int, const Scalar
&);
148 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
),
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
),
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
),
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
),
179 const Scalar
* a
= reinterpret_cast<const Scalar
*>(pa
);
180 Scalar
* b
= reinterpret_cast<Scalar
*>(pb
);
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;
190 return xerbla_(SCALAR_SUFFIX_UP
"TRMV ",&info
,6);
195 Scalar
* actual_b
= get_compact_vector(b
,*n
,*incb
);
196 Matrix
<Scalar
,Dynamic
,1> res(*n
);
199 int code
= OP(*opa
) | (UPLO(*uplo
) << 2) | (DIAG(*diag
) << 3);
200 if(code
>=16 || func
[code
]==0)
203 func
[code
](*n
, *n
, a
, *lda
, actual_b
, 1, res
.data(), 1, Scalar(1));
205 copy_back(res
.data(),b
,*n
,*incb
);
206 if(actual_b
!=b
) delete[] actual_b
;
211 /** GBMV performs one of the matrix-vector operations
213 * y := alpha*A*x + beta*y, or y := alpha*A'*x + beta*y,
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.
218 int 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
)
221 const Scalar
* a
= reinterpret_cast<const Scalar
*>(pa
);
222 const Scalar
* x
= reinterpret_cast<const Scalar
*>(px
);
223 Scalar
* y
= reinterpret_cast<Scalar
*>(py
);
224 Scalar alpha
= *reinterpret_cast<const Scalar
*>(palpha
);
225 Scalar beta
= *reinterpret_cast<const Scalar
*>(pbeta
);
226 int coeff_rows
= *kl
+*ku
+1;
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;
238 return xerbla_(SCALAR_SUFFIX_UP
"GBMV ",&info
,6);
240 if(*m
==0 || *n
==0 || (alpha
==Scalar(0) && beta
==Scalar(1)))
246 std::swap(actual_m
,actual_n
);
248 const Scalar
* actual_x
= get_compact_vector(x
,actual_n
,*incx
);
249 Scalar
* actual_y
= get_compact_vector(y
,actual_m
,*incy
);
253 if(beta
==Scalar(0)) make_vector(actual_y
, actual_m
).setZero();
254 else make_vector(actual_y
, actual_m
) *= beta
;
257 ConstMatrixType
mat_coeffs(a
,coeff_rows
,*n
,*lda
);
259 int nb
= std::min(*n
,(*m
)+(*ku
));
260 for(int j
=0; j
<nb
; ++j
)
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
;
267 make_vector(actual_y
+start
,len
) += (alpha
*actual_x
[j
]) * mat_coeffs
.col(j
).segment(offset
,len
);
268 else if(OP(*trans
)==TR
)
269 actual_y
[j
] += alpha
* ( mat_coeffs
.col(j
).segment(offset
,len
).transpose() * make_vector(actual_x
+start
,len
) ).value();
271 actual_y
[j
] += alpha
* ( mat_coeffs
.col(j
).segment(offset
,len
).adjoint() * make_vector(actual_x
+start
,len
) ).value();
274 if(actual_x
!=x
) delete[] actual_x
;
275 if(actual_y
!=y
) delete[] copy_back(actual_y
,y
,actual_m
,*incy
);
281 /** TBMV performs one of the matrix-vector operations
283 * x := A*x, or x := A'*x,
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.
288 int EIGEN_BLAS_FUNC(tbmv
)(char *uplo
, char *opa
, char *diag
, int *n
, int *k
, RealScalar
*pa
, int *lda
, RealScalar
*px
, int *incx
)
290 Scalar
* a
= reinterpret_cast<Scalar
*>(pa
);
291 Scalar
* x
= reinterpret_cast<Scalar
*>(px
);
292 int coeff_rows
= *k
+ 1;
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;
303 return xerbla_(SCALAR_SUFFIX_UP
"TBMV ",&info
,6);
310 Scalar
* actual_x
= get_compact_vector(x
,actual_n
,*incx
);
312 MatrixType
mat_coeffs(a
,coeff_rows
,*n
,*lda
);
314 int ku
= UPLO(*uplo
)==UPPER
? *k
: 0;
315 int kl
= UPLO(*uplo
)==LOWER
? *k
: 0;
317 for(int j
=0; j
<*n
; ++j
)
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
;
325 make_vector(actual_y
+start
,len
) += (alpha
*actual_x
[j
]) * mat_coeffs
.col(j
).segment(offset
,len
);
326 else if(OP(*trans
)==TR
)
327 actual_y
[j
] += alpha
* ( mat_coeffs
.col(j
).segment(offset
,len
).transpose() * make_vector(actual_x
+start
,len
) ).value();
329 actual_y
[j
] += alpha
* ( mat_coeffs
.col(j
).segment(offset
,len
).adjoint() * make_vector(actual_x
+start
,len
) ).value();
332 if(actual_x
!=x
) delete[] actual_x
;
333 if(actual_y
!=y
) delete[] copy_back(actual_y
,y
,actual_m
,*incy
);
339 /** DTBSV solves one of the systems of equations
341 * A*x = b, or A'*x = b,
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 )
347 * No test for singularity or near-singularity is included in this
348 * routine. Such tests must be performed before calling this routine.
350 int EIGEN_BLAS_FUNC(tbsv
)(char *uplo
, char *op
, char *diag
, int *n
, int *k
, RealScalar
*pa
, int *lda
, RealScalar
*px
, int *incx
)
352 typedef void (*functype
)(int, int, const Scalar
*, int, Scalar
*);
353 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
),
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
),
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
),
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
),
384 Scalar
* a
= reinterpret_cast<Scalar
*>(pa
);
385 Scalar
* x
= reinterpret_cast<Scalar
*>(px
);
386 int coeff_rows
= *k
+1;
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;
397 return xerbla_(SCALAR_SUFFIX_UP
"TBSV ",&info
,6);
399 if(*n
==0 || (*k
==0 && DIAG(*diag
)==UNIT
))
404 Scalar
* actual_x
= get_compact_vector(x
,actual_n
,*incx
);
406 int code
= OP(*op
) | (UPLO(*uplo
) << 2) | (DIAG(*diag
) << 3);
407 if(code
>=16 || func
[code
]==0)
410 func
[code
](*n
, *k
, a
, *lda
, actual_x
);
412 if(actual_x
!=x
) delete[] copy_back(actual_x
,x
,actual_n
,*incx
);
417 /** DTPMV performs one of the matrix-vector operations
419 * x := A*x, or x := A'*x,
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.
424 int EIGEN_BLAS_FUNC(tpmv
)(char *uplo
, char *opa
, char *diag
, int *n
, RealScalar
*pap
, RealScalar
*px
, int *incx
)
426 typedef void (*functype
)(int, const Scalar
*, const Scalar
*, Scalar
*, Scalar
);
427 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
),
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
),
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
),
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
),
458 Scalar
* ap
= reinterpret_cast<Scalar
*>(pap
);
459 Scalar
* x
= reinterpret_cast<Scalar
*>(px
);
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;
468 return xerbla_(SCALAR_SUFFIX_UP
"TPMV ",&info
,6);
473 Scalar
* actual_x
= get_compact_vector(x
,*n
,*incx
);
474 Matrix
<Scalar
,Dynamic
,1> res(*n
);
477 int code
= OP(*opa
) | (UPLO(*uplo
) << 2) | (DIAG(*diag
) << 3);
478 if(code
>=16 || func
[code
]==0)
481 func
[code
](*n
, ap
, actual_x
, res
.data(), Scalar(1));
483 copy_back(res
.data(),x
,*n
,*incx
);
484 if(actual_x
!=x
) delete[] actual_x
;
489 /** DTPSV solves one of the systems of equations
491 * A*x = b, or A'*x = b,
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.
496 * No test for singularity or near-singularity is included in this
497 * routine. Such tests must be performed before calling this routine.
499 int EIGEN_BLAS_FUNC(tpsv
)(char *uplo
, char *opa
, char *diag
, int *n
, RealScalar
*pap
, RealScalar
*px
, int *incx
)
501 typedef void (*functype
)(int, const Scalar
*, Scalar
*);
502 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
),
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
),
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
),
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
),
533 Scalar
* ap
= reinterpret_cast<Scalar
*>(pap
);
534 Scalar
* x
= reinterpret_cast<Scalar
*>(px
);
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;
543 return xerbla_(SCALAR_SUFFIX_UP
"TPSV ",&info
,6);
545 Scalar
* actual_x
= get_compact_vector(x
,*n
,*incx
);
547 int code
= OP(*opa
) | (UPLO(*uplo
) << 2) | (DIAG(*diag
) << 3);
548 func
[code
](*n
, ap
, actual_x
);
550 if(actual_x
!=x
) delete[] copy_back(actual_x
,x
,*n
,*incx
);