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