Home | History | Annotate | Download | only in blas
      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