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(gemm)(char *opa, char *opb, int *m, int *n, int *k, RealScalar *palpha, RealScalar *pa, int *lda, RealScalar *pb, int *ldb, RealScalar *pbeta, RealScalar *pc, int *ldc) 13 { 14 // std::cerr << "in gemm " << *opa << " " << *opb << " " << *m << " " << *n << " " << *k << " " << *lda << " " << *ldb << " " << *ldc << " " << *palpha << " " << *pbeta << "\n"; 15 typedef void (*functype)(DenseIndex, DenseIndex, DenseIndex, const Scalar *, DenseIndex, const Scalar *, DenseIndex, Scalar *, DenseIndex, Scalar, internal::level3_blocking<Scalar,Scalar>&, Eigen::internal::GemmParallelInfo<DenseIndex>*); 16 static functype func[12]; 17 18 static bool init = false; 19 if(!init) 20 { 21 for(int k=0; k<12; ++k) 22 func[k] = 0; 23 func[NOTR | (NOTR << 2)] = (internal::general_matrix_matrix_product<DenseIndex,Scalar,ColMajor,false,Scalar,ColMajor,false,ColMajor>::run); 24 func[TR | (NOTR << 2)] = (internal::general_matrix_matrix_product<DenseIndex,Scalar,RowMajor,false,Scalar,ColMajor,false,ColMajor>::run); 25 func[ADJ | (NOTR << 2)] = (internal::general_matrix_matrix_product<DenseIndex,Scalar,RowMajor,Conj, Scalar,ColMajor,false,ColMajor>::run); 26 func[NOTR | (TR << 2)] = (internal::general_matrix_matrix_product<DenseIndex,Scalar,ColMajor,false,Scalar,RowMajor,false,ColMajor>::run); 27 func[TR | (TR << 2)] = (internal::general_matrix_matrix_product<DenseIndex,Scalar,RowMajor,false,Scalar,RowMajor,false,ColMajor>::run); 28 func[ADJ | (TR << 2)] = (internal::general_matrix_matrix_product<DenseIndex,Scalar,RowMajor,Conj, Scalar,RowMajor,false,ColMajor>::run); 29 func[NOTR | (ADJ << 2)] = (internal::general_matrix_matrix_product<DenseIndex,Scalar,ColMajor,false,Scalar,RowMajor,Conj, ColMajor>::run); 30 func[TR | (ADJ << 2)] = (internal::general_matrix_matrix_product<DenseIndex,Scalar,RowMajor,false,Scalar,RowMajor,Conj, ColMajor>::run); 31 func[ADJ | (ADJ << 2)] = (internal::general_matrix_matrix_product<DenseIndex,Scalar,RowMajor,Conj, Scalar,RowMajor,Conj, ColMajor>::run); 32 init = true; 33 } 34 35 Scalar* a = reinterpret_cast<Scalar*>(pa); 36 Scalar* b = reinterpret_cast<Scalar*>(pb); 37 Scalar* c = reinterpret_cast<Scalar*>(pc); 38 Scalar alpha = *reinterpret_cast<Scalar*>(palpha); 39 Scalar beta = *reinterpret_cast<Scalar*>(pbeta); 40 41 int info = 0; 42 if(OP(*opa)==INVALID) info = 1; 43 else if(OP(*opb)==INVALID) info = 2; 44 else if(*m<0) info = 3; 45 else if(*n<0) info = 4; 46 else if(*k<0) info = 5; 47 else if(*lda<std::max(1,(OP(*opa)==NOTR)?*m:*k)) info = 8; 48 else if(*ldb<std::max(1,(OP(*opb)==NOTR)?*k:*n)) info = 10; 49 else if(*ldc<std::max(1,*m)) info = 13; 50 if(info) 51 return xerbla_(SCALAR_SUFFIX_UP"GEMM ",&info,6); 52 53 if(beta!=Scalar(1)) 54 { 55 if(beta==Scalar(0)) matrix(c, *m, *n, *ldc).setZero(); 56 else matrix(c, *m, *n, *ldc) *= beta; 57 } 58 59 internal::gemm_blocking_space<ColMajor,Scalar,Scalar,Dynamic,Dynamic,Dynamic> blocking(*m,*n,*k); 60 61 int code = OP(*opa) | (OP(*opb) << 2); 62 func[code](*m, *n, *k, a, *lda, b, *ldb, c, *ldc, alpha, blocking, 0); 63 return 0; 64 } 65 66 int EIGEN_BLAS_FUNC(trsm)(char *side, char *uplo, char *opa, char *diag, int *m, int *n, RealScalar *palpha, RealScalar *pa, int *lda, RealScalar *pb, int *ldb) 67 { 68 // std::cerr << "in trsm " << *side << " " << *uplo << " " << *opa << " " << *diag << " " << *m << "," << *n << " " << *palpha << " " << *lda << " " << *ldb<< "\n"; 69 typedef void (*functype)(DenseIndex, DenseIndex, const Scalar *, DenseIndex, Scalar *, DenseIndex, internal::level3_blocking<Scalar,Scalar>&); 70 static functype func[32]; 71 72 static bool init = false; 73 if(!init) 74 { 75 for(int k=0; k<32; ++k) 76 func[k] = 0; 77 78 func[NOTR | (LEFT << 2) | (UP << 3) | (NUNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheLeft, Upper|0, false,ColMajor,ColMajor>::run); 79 func[TR | (LEFT << 2) | (UP << 3) | (NUNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheLeft, Lower|0, false,RowMajor,ColMajor>::run); 80 func[ADJ | (LEFT << 2) | (UP << 3) | (NUNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheLeft, Lower|0, Conj, RowMajor,ColMajor>::run); 81 82 func[NOTR | (RIGHT << 2) | (UP << 3) | (NUNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheRight,Upper|0, false,ColMajor,ColMajor>::run); 83 func[TR | (RIGHT << 2) | (UP << 3) | (NUNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheRight,Lower|0, false,RowMajor,ColMajor>::run); 84 func[ADJ | (RIGHT << 2) | (UP << 3) | (NUNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheRight,Lower|0, Conj, RowMajor,ColMajor>::run); 85 86 func[NOTR | (LEFT << 2) | (LO << 3) | (NUNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheLeft, Lower|0, false,ColMajor,ColMajor>::run); 87 func[TR | (LEFT << 2) | (LO << 3) | (NUNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheLeft, Upper|0, false,RowMajor,ColMajor>::run); 88 func[ADJ | (LEFT << 2) | (LO << 3) | (NUNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheLeft, Upper|0, Conj, RowMajor,ColMajor>::run); 89 90 func[NOTR | (RIGHT << 2) | (LO << 3) | (NUNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheRight,Lower|0, false,ColMajor,ColMajor>::run); 91 func[TR | (RIGHT << 2) | (LO << 3) | (NUNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheRight,Upper|0, false,RowMajor,ColMajor>::run); 92 func[ADJ | (RIGHT << 2) | (LO << 3) | (NUNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheRight,Upper|0, Conj, RowMajor,ColMajor>::run); 93 94 95 func[NOTR | (LEFT << 2) | (UP << 3) | (UNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheLeft, Upper|UnitDiag,false,ColMajor,ColMajor>::run); 96 func[TR | (LEFT << 2) | (UP << 3) | (UNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheLeft, Lower|UnitDiag,false,RowMajor,ColMajor>::run); 97 func[ADJ | (LEFT << 2) | (UP << 3) | (UNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheLeft, Lower|UnitDiag,Conj, RowMajor,ColMajor>::run); 98 99 func[NOTR | (RIGHT << 2) | (UP << 3) | (UNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheRight,Upper|UnitDiag,false,ColMajor,ColMajor>::run); 100 func[TR | (RIGHT << 2) | (UP << 3) | (UNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheRight,Lower|UnitDiag,false,RowMajor,ColMajor>::run); 101 func[ADJ | (RIGHT << 2) | (UP << 3) | (UNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheRight,Lower|UnitDiag,Conj, RowMajor,ColMajor>::run); 102 103 func[NOTR | (LEFT << 2) | (LO << 3) | (UNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheLeft, Lower|UnitDiag,false,ColMajor,ColMajor>::run); 104 func[TR | (LEFT << 2) | (LO << 3) | (UNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheLeft, Upper|UnitDiag,false,RowMajor,ColMajor>::run); 105 func[ADJ | (LEFT << 2) | (LO << 3) | (UNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheLeft, Upper|UnitDiag,Conj, RowMajor,ColMajor>::run); 106 107 func[NOTR | (RIGHT << 2) | (LO << 3) | (UNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheRight,Lower|UnitDiag,false,ColMajor,ColMajor>::run); 108 func[TR | (RIGHT << 2) | (LO << 3) | (UNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheRight,Upper|UnitDiag,false,RowMajor,ColMajor>::run); 109 func[ADJ | (RIGHT << 2) | (LO << 3) | (UNIT << 4)] = (internal::triangular_solve_matrix<Scalar,DenseIndex,OnTheRight,Upper|UnitDiag,Conj, RowMajor,ColMajor>::run); 110 111 init = true; 112 } 113 114 Scalar* a = reinterpret_cast<Scalar*>(pa); 115 Scalar* b = reinterpret_cast<Scalar*>(pb); 116 Scalar alpha = *reinterpret_cast<Scalar*>(palpha); 117 118 int info = 0; 119 if(SIDE(*side)==INVALID) info = 1; 120 else if(UPLO(*uplo)==INVALID) info = 2; 121 else if(OP(*opa)==INVALID) info = 3; 122 else if(DIAG(*diag)==INVALID) info = 4; 123 else if(*m<0) info = 5; 124 else if(*n<0) info = 6; 125 else if(*lda<std::max(1,(SIDE(*side)==LEFT)?*m:*n)) info = 9; 126 else if(*ldb<std::max(1,*m)) info = 11; 127 if(info) 128 return xerbla_(SCALAR_SUFFIX_UP"TRSM ",&info,6); 129 130 int code = OP(*opa) | (SIDE(*side) << 2) | (UPLO(*uplo) << 3) | (DIAG(*diag) << 4); 131 132 if(SIDE(*side)==LEFT) 133 { 134 internal::gemm_blocking_space<ColMajor,Scalar,Scalar,Dynamic,Dynamic,Dynamic,4> blocking(*m,*n,*m); 135 func[code](*m, *n, a, *lda, b, *ldb, blocking); 136 } 137 else 138 { 139 internal::gemm_blocking_space<ColMajor,Scalar,Scalar,Dynamic,Dynamic,Dynamic,4> blocking(*m,*n,*n); 140 func[code](*n, *m, a, *lda, b, *ldb, blocking); 141 } 142 143 if(alpha!=Scalar(1)) 144 matrix(b,*m,*n,*ldb) *= alpha; 145 146 return 0; 147 } 148 149 150 // b = alpha*op(a)*b for side = 'L'or'l' 151 // b = alpha*b*op(a) for side = 'R'or'r' 152 int EIGEN_BLAS_FUNC(trmm)(char *side, char *uplo, char *opa, char *diag, int *m, int *n, RealScalar *palpha, RealScalar *pa, int *lda, RealScalar *pb, int *ldb) 153 { 154 // std::cerr << "in trmm " << *side << " " << *uplo << " " << *opa << " " << *diag << " " << *m << " " << *n << " " << *lda << " " << *ldb << " " << *palpha << "\n"; 155 typedef void (*functype)(DenseIndex, DenseIndex, DenseIndex, const Scalar *, DenseIndex, const Scalar *, DenseIndex, Scalar *, DenseIndex, Scalar, internal::level3_blocking<Scalar,Scalar>&); 156 static functype func[32]; 157 static bool init = false; 158 if(!init) 159 { 160 for(int k=0; k<32; ++k) 161 func[k] = 0; 162 163 func[NOTR | (LEFT << 2) | (UP << 3) | (NUNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Upper|0, true, ColMajor,false,ColMajor,false,ColMajor>::run); 164 func[TR | (LEFT << 2) | (UP << 3) | (NUNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Lower|0, true, RowMajor,false,ColMajor,false,ColMajor>::run); 165 func[ADJ | (LEFT << 2) | (UP << 3) | (NUNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Lower|0, true, RowMajor,Conj, ColMajor,false,ColMajor>::run); 166 167 func[NOTR | (RIGHT << 2) | (UP << 3) | (NUNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Upper|0, false,ColMajor,false,ColMajor,false,ColMajor>::run); 168 func[TR | (RIGHT << 2) | (UP << 3) | (NUNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Lower|0, false,ColMajor,false,RowMajor,false,ColMajor>::run); 169 func[ADJ | (RIGHT << 2) | (UP << 3) | (NUNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Lower|0, false,ColMajor,false,RowMajor,Conj, ColMajor>::run); 170 171 func[NOTR | (LEFT << 2) | (LO << 3) | (NUNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Lower|0, true, ColMajor,false,ColMajor,false,ColMajor>::run); 172 func[TR | (LEFT << 2) | (LO << 3) | (NUNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Upper|0, true, RowMajor,false,ColMajor,false,ColMajor>::run); 173 func[ADJ | (LEFT << 2) | (LO << 3) | (NUNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Upper|0, true, RowMajor,Conj, ColMajor,false,ColMajor>::run); 174 175 func[NOTR | (RIGHT << 2) | (LO << 3) | (NUNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Lower|0, false,ColMajor,false,ColMajor,false,ColMajor>::run); 176 func[TR | (RIGHT << 2) | (LO << 3) | (NUNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Upper|0, false,ColMajor,false,RowMajor,false,ColMajor>::run); 177 func[ADJ | (RIGHT << 2) | (LO << 3) | (NUNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Upper|0, false,ColMajor,false,RowMajor,Conj, ColMajor>::run); 178 179 func[NOTR | (LEFT << 2) | (UP << 3) | (UNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Upper|UnitDiag,true, ColMajor,false,ColMajor,false,ColMajor>::run); 180 func[TR | (LEFT << 2) | (UP << 3) | (UNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Lower|UnitDiag,true, RowMajor,false,ColMajor,false,ColMajor>::run); 181 func[ADJ | (LEFT << 2) | (UP << 3) | (UNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Lower|UnitDiag,true, RowMajor,Conj, ColMajor,false,ColMajor>::run); 182 183 func[NOTR | (RIGHT << 2) | (UP << 3) | (UNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Upper|UnitDiag,false,ColMajor,false,ColMajor,false,ColMajor>::run); 184 func[TR | (RIGHT << 2) | (UP << 3) | (UNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Lower|UnitDiag,false,ColMajor,false,RowMajor,false,ColMajor>::run); 185 func[ADJ | (RIGHT << 2) | (UP << 3) | (UNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Lower|UnitDiag,false,ColMajor,false,RowMajor,Conj, ColMajor>::run); 186 187 func[NOTR | (LEFT << 2) | (LO << 3) | (UNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Lower|UnitDiag,true, ColMajor,false,ColMajor,false,ColMajor>::run); 188 func[TR | (LEFT << 2) | (LO << 3) | (UNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Upper|UnitDiag,true, RowMajor,false,ColMajor,false,ColMajor>::run); 189 func[ADJ | (LEFT << 2) | (LO << 3) | (UNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Upper|UnitDiag,true, RowMajor,Conj, ColMajor,false,ColMajor>::run); 190 191 func[NOTR | (RIGHT << 2) | (LO << 3) | (UNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Lower|UnitDiag,false,ColMajor,false,ColMajor,false,ColMajor>::run); 192 func[TR | (RIGHT << 2) | (LO << 3) | (UNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Upper|UnitDiag,false,ColMajor,false,RowMajor,false,ColMajor>::run); 193 func[ADJ | (RIGHT << 2) | (LO << 3) | (UNIT << 4)] = (internal::product_triangular_matrix_matrix<Scalar,DenseIndex,Upper|UnitDiag,false,ColMajor,false,RowMajor,Conj, ColMajor>::run); 194 195 init = true; 196 } 197 198 Scalar* a = reinterpret_cast<Scalar*>(pa); 199 Scalar* b = reinterpret_cast<Scalar*>(pb); 200 Scalar alpha = *reinterpret_cast<Scalar*>(palpha); 201 202 int info = 0; 203 if(SIDE(*side)==INVALID) info = 1; 204 else if(UPLO(*uplo)==INVALID) info = 2; 205 else if(OP(*opa)==INVALID) info = 3; 206 else if(DIAG(*diag)==INVALID) info = 4; 207 else if(*m<0) info = 5; 208 else if(*n<0) info = 6; 209 else if(*lda<std::max(1,(SIDE(*side)==LEFT)?*m:*n)) info = 9; 210 else if(*ldb<std::max(1,*m)) info = 11; 211 if(info) 212 return xerbla_(SCALAR_SUFFIX_UP"TRMM ",&info,6); 213 214 int code = OP(*opa) | (SIDE(*side) << 2) | (UPLO(*uplo) << 3) | (DIAG(*diag) << 4); 215 216 if(*m==0 || *n==0) 217 return 1; 218 219 // FIXME find a way to avoid this copy 220 Matrix<Scalar,Dynamic,Dynamic,ColMajor> tmp = matrix(b,*m,*n,*ldb); 221 matrix(b,*m,*n,*ldb).setZero(); 222 223 if(SIDE(*side)==LEFT) 224 { 225 internal::gemm_blocking_space<ColMajor,Scalar,Scalar,Dynamic,Dynamic,Dynamic,4> blocking(*m,*n,*m); 226 func[code](*m, *n, *m, a, *lda, tmp.data(), tmp.outerStride(), b, *ldb, alpha, blocking); 227 } 228 else 229 { 230 internal::gemm_blocking_space<ColMajor,Scalar,Scalar,Dynamic,Dynamic,Dynamic,4> blocking(*m,*n,*n); 231 func[code](*m, *n, *n, tmp.data(), tmp.outerStride(), a, *lda, b, *ldb, alpha, blocking); 232 } 233 return 1; 234 } 235 236 // c = alpha*a*b + beta*c for side = 'L'or'l' 237 // c = alpha*b*a + beta*c for side = 'R'or'r 238 int EIGEN_BLAS_FUNC(symm)(char *side, char *uplo, int *m, int *n, RealScalar *palpha, RealScalar *pa, int *lda, RealScalar *pb, int *ldb, RealScalar *pbeta, RealScalar *pc, int *ldc) 239 { 240 // std::cerr << "in symm " << *side << " " << *uplo << " " << *m << "x" << *n << " lda:" << *lda << " ldb:" << *ldb << " ldc:" << *ldc << " alpha:" << *palpha << " beta:" << *pbeta << "\n"; 241 Scalar* a = reinterpret_cast<Scalar*>(pa); 242 Scalar* b = reinterpret_cast<Scalar*>(pb); 243 Scalar* c = reinterpret_cast<Scalar*>(pc); 244 Scalar alpha = *reinterpret_cast<Scalar*>(palpha); 245 Scalar beta = *reinterpret_cast<Scalar*>(pbeta); 246 247 int info = 0; 248 if(SIDE(*side)==INVALID) info = 1; 249 else if(UPLO(*uplo)==INVALID) info = 2; 250 else if(*m<0) info = 3; 251 else if(*n<0) info = 4; 252 else if(*lda<std::max(1,(SIDE(*side)==LEFT)?*m:*n)) info = 7; 253 else if(*ldb<std::max(1,*m)) info = 9; 254 else if(*ldc<std::max(1,*m)) info = 12; 255 if(info) 256 return xerbla_(SCALAR_SUFFIX_UP"SYMM ",&info,6); 257 258 if(beta!=Scalar(1)) 259 { 260 if(beta==Scalar(0)) matrix(c, *m, *n, *ldc).setZero(); 261 else matrix(c, *m, *n, *ldc) *= beta; 262 } 263 264 if(*m==0 || *n==0) 265 { 266 return 1; 267 } 268 269 #if ISCOMPLEX 270 // FIXME add support for symmetric complex matrix 271 int size = (SIDE(*side)==LEFT) ? (*m) : (*n); 272 Matrix<Scalar,Dynamic,Dynamic,ColMajor> matA(size,size); 273 if(UPLO(*uplo)==UP) 274 { 275 matA.triangularView<Upper>() = matrix(a,size,size,*lda); 276 matA.triangularView<Lower>() = matrix(a,size,size,*lda).transpose(); 277 } 278 else if(UPLO(*uplo)==LO) 279 { 280 matA.triangularView<Lower>() = matrix(a,size,size,*lda); 281 matA.triangularView<Upper>() = matrix(a,size,size,*lda).transpose(); 282 } 283 if(SIDE(*side)==LEFT) 284 matrix(c, *m, *n, *ldc) += alpha * matA * matrix(b, *m, *n, *ldb); 285 else if(SIDE(*side)==RIGHT) 286 matrix(c, *m, *n, *ldc) += alpha * matrix(b, *m, *n, *ldb) * matA; 287 #else 288 if(SIDE(*side)==LEFT) 289 if(UPLO(*uplo)==UP) internal::product_selfadjoint_matrix<Scalar, DenseIndex, RowMajor,true,false, ColMajor,false,false, ColMajor>::run(*m, *n, a, *lda, b, *ldb, c, *ldc, alpha); 290 else if(UPLO(*uplo)==LO) internal::product_selfadjoint_matrix<Scalar, DenseIndex, ColMajor,true,false, ColMajor,false,false, ColMajor>::run(*m, *n, a, *lda, b, *ldb, c, *ldc, alpha); 291 else return 0; 292 else if(SIDE(*side)==RIGHT) 293 if(UPLO(*uplo)==UP) internal::product_selfadjoint_matrix<Scalar, DenseIndex, ColMajor,false,false, RowMajor,true,false, ColMajor>::run(*m, *n, b, *ldb, a, *lda, c, *ldc, alpha); 294 else if(UPLO(*uplo)==LO) internal::product_selfadjoint_matrix<Scalar, DenseIndex, ColMajor,false,false, ColMajor,true,false, ColMajor>::run(*m, *n, b, *ldb, a, *lda, c, *ldc, alpha); 295 else return 0; 296 else 297 return 0; 298 #endif 299 300 return 0; 301 } 302 303 // c = alpha*a*a' + beta*c for op = 'N'or'n' 304 // c = alpha*a'*a + beta*c for op = 'T'or't','C'or'c' 305 int EIGEN_BLAS_FUNC(syrk)(char *uplo, char *op, int *n, int *k, RealScalar *palpha, RealScalar *pa, int *lda, RealScalar *pbeta, RealScalar *pc, int *ldc) 306 { 307 // std::cerr << "in syrk " << *uplo << " " << *op << " " << *n << " " << *k << " " << *palpha << " " << *lda << " " << *pbeta << " " << *ldc << "\n"; 308 typedef void (*functype)(DenseIndex, DenseIndex, const Scalar *, DenseIndex, const Scalar *, DenseIndex, Scalar *, DenseIndex, Scalar); 309 static functype func[8]; 310 311 static bool init = false; 312 if(!init) 313 { 314 for(int k=0; k<8; ++k) 315 func[k] = 0; 316 317 func[NOTR | (UP << 2)] = (internal::general_matrix_matrix_triangular_product<DenseIndex,Scalar,ColMajor,false,Scalar,RowMajor,ColMajor,Conj, Upper>::run); 318 func[TR | (UP << 2)] = (internal::general_matrix_matrix_triangular_product<DenseIndex,Scalar,RowMajor,false,Scalar,ColMajor,ColMajor,Conj, Upper>::run); 319 func[ADJ | (UP << 2)] = (internal::general_matrix_matrix_triangular_product<DenseIndex,Scalar,RowMajor,Conj, Scalar,ColMajor,ColMajor,false,Upper>::run); 320 321 func[NOTR | (LO << 2)] = (internal::general_matrix_matrix_triangular_product<DenseIndex,Scalar,ColMajor,false,Scalar,RowMajor,ColMajor,Conj, Lower>::run); 322 func[TR | (LO << 2)] = (internal::general_matrix_matrix_triangular_product<DenseIndex,Scalar,RowMajor,false,Scalar,ColMajor,ColMajor,Conj, Lower>::run); 323 func[ADJ | (LO << 2)] = (internal::general_matrix_matrix_triangular_product<DenseIndex,Scalar,RowMajor,Conj, Scalar,ColMajor,ColMajor,false,Lower>::run); 324 325 init = true; 326 } 327 328 Scalar* a = reinterpret_cast<Scalar*>(pa); 329 Scalar* c = reinterpret_cast<Scalar*>(pc); 330 Scalar alpha = *reinterpret_cast<Scalar*>(palpha); 331 Scalar beta = *reinterpret_cast<Scalar*>(pbeta); 332 333 int info = 0; 334 if(UPLO(*uplo)==INVALID) info = 1; 335 else if(OP(*op)==INVALID) info = 2; 336 else if(*n<0) info = 3; 337 else if(*k<0) info = 4; 338 else if(*lda<std::max(1,(OP(*op)==NOTR)?*n:*k)) info = 7; 339 else if(*ldc<std::max(1,*n)) info = 10; 340 if(info) 341 return xerbla_(SCALAR_SUFFIX_UP"SYRK ",&info,6); 342 343 if(beta!=Scalar(1)) 344 { 345 if(UPLO(*uplo)==UP) 346 if(beta==Scalar(0)) matrix(c, *n, *n, *ldc).triangularView<Upper>().setZero(); 347 else matrix(c, *n, *n, *ldc).triangularView<Upper>() *= beta; 348 else 349 if(beta==Scalar(0)) matrix(c, *n, *n, *ldc).triangularView<Lower>().setZero(); 350 else matrix(c, *n, *n, *ldc).triangularView<Lower>() *= beta; 351 } 352 353 #if ISCOMPLEX 354 // FIXME add support for symmetric complex matrix 355 if(UPLO(*uplo)==UP) 356 { 357 if(OP(*op)==NOTR) 358 matrix(c, *n, *n, *ldc).triangularView<Upper>() += alpha * matrix(a,*n,*k,*lda) * matrix(a,*n,*k,*lda).transpose(); 359 else 360 matrix(c, *n, *n, *ldc).triangularView<Upper>() += alpha * matrix(a,*k,*n,*lda).transpose() * matrix(a,*k,*n,*lda); 361 } 362 else 363 { 364 if(OP(*op)==NOTR) 365 matrix(c, *n, *n, *ldc).triangularView<Lower>() += alpha * matrix(a,*n,*k,*lda) * matrix(a,*n,*k,*lda).transpose(); 366 else 367 matrix(c, *n, *n, *ldc).triangularView<Lower>() += alpha * matrix(a,*k,*n,*lda).transpose() * matrix(a,*k,*n,*lda); 368 } 369 #else 370 int code = OP(*op) | (UPLO(*uplo) << 2); 371 func[code](*n, *k, a, *lda, a, *lda, c, *ldc, alpha); 372 #endif 373 374 return 0; 375 } 376 377 // c = alpha*a*b' + alpha*b*a' + beta*c for op = 'N'or'n' 378 // c = alpha*a'*b + alpha*b'*a + beta*c for op = 'T'or't' 379 int EIGEN_BLAS_FUNC(syr2k)(char *uplo, char *op, int *n, int *k, RealScalar *palpha, RealScalar *pa, int *lda, RealScalar *pb, int *ldb, RealScalar *pbeta, RealScalar *pc, int *ldc) 380 { 381 Scalar* a = reinterpret_cast<Scalar*>(pa); 382 Scalar* b = reinterpret_cast<Scalar*>(pb); 383 Scalar* c = reinterpret_cast<Scalar*>(pc); 384 Scalar alpha = *reinterpret_cast<Scalar*>(palpha); 385 Scalar beta = *reinterpret_cast<Scalar*>(pbeta); 386 387 int info = 0; 388 if(UPLO(*uplo)==INVALID) info = 1; 389 else if(OP(*op)==INVALID) info = 2; 390 else if(*n<0) info = 3; 391 else if(*k<0) info = 4; 392 else if(*lda<std::max(1,(OP(*op)==NOTR)?*n:*k)) info = 7; 393 else if(*ldb<std::max(1,(OP(*op)==NOTR)?*n:*k)) info = 9; 394 else if(*ldc<std::max(1,*n)) info = 12; 395 if(info) 396 return xerbla_(SCALAR_SUFFIX_UP"SYR2K",&info,6); 397 398 if(beta!=Scalar(1)) 399 { 400 if(UPLO(*uplo)==UP) 401 if(beta==Scalar(0)) matrix(c, *n, *n, *ldc).triangularView<Upper>().setZero(); 402 else matrix(c, *n, *n, *ldc).triangularView<Upper>() *= beta; 403 else 404 if(beta==Scalar(0)) matrix(c, *n, *n, *ldc).triangularView<Lower>().setZero(); 405 else matrix(c, *n, *n, *ldc).triangularView<Lower>() *= beta; 406 } 407 408 if(*k==0) 409 return 1; 410 411 if(OP(*op)==NOTR) 412 { 413 if(UPLO(*uplo)==UP) 414 { 415 matrix(c, *n, *n, *ldc).triangularView<Upper>() 416 += alpha *matrix(a, *n, *k, *lda)*matrix(b, *n, *k, *ldb).transpose() 417 + alpha*matrix(b, *n, *k, *ldb)*matrix(a, *n, *k, *lda).transpose(); 418 } 419 else if(UPLO(*uplo)==LO) 420 matrix(c, *n, *n, *ldc).triangularView<Lower>() 421 += alpha*matrix(a, *n, *k, *lda)*matrix(b, *n, *k, *ldb).transpose() 422 + alpha*matrix(b, *n, *k, *ldb)*matrix(a, *n, *k, *lda).transpose(); 423 } 424 else if(OP(*op)==TR || OP(*op)==ADJ) 425 { 426 if(UPLO(*uplo)==UP) 427 matrix(c, *n, *n, *ldc).triangularView<Upper>() 428 += alpha*matrix(a, *k, *n, *lda).transpose()*matrix(b, *k, *n, *ldb) 429 + alpha*matrix(b, *k, *n, *ldb).transpose()*matrix(a, *k, *n, *lda); 430 else if(UPLO(*uplo)==LO) 431 matrix(c, *n, *n, *ldc).triangularView<Lower>() 432 += alpha*matrix(a, *k, *n, *lda).transpose()*matrix(b, *k, *n, *ldb) 433 + alpha*matrix(b, *k, *n, *ldb).transpose()*matrix(a, *k, *n, *lda); 434 } 435 436 return 0; 437 } 438 439 440 #if ISCOMPLEX 441 442 // c = alpha*a*b + beta*c for side = 'L'or'l' 443 // c = alpha*b*a + beta*c for side = 'R'or'r 444 int EIGEN_BLAS_FUNC(hemm)(char *side, char *uplo, int *m, int *n, RealScalar *palpha, RealScalar *pa, int *lda, RealScalar *pb, int *ldb, RealScalar *pbeta, RealScalar *pc, int *ldc) 445 { 446 Scalar* a = reinterpret_cast<Scalar*>(pa); 447 Scalar* b = reinterpret_cast<Scalar*>(pb); 448 Scalar* c = reinterpret_cast<Scalar*>(pc); 449 Scalar alpha = *reinterpret_cast<Scalar*>(palpha); 450 Scalar beta = *reinterpret_cast<Scalar*>(pbeta); 451 452 // std::cerr << "in hemm " << *side << " " << *uplo << " " << *m << " " << *n << " " << alpha << " " << *lda << " " << beta << " " << *ldc << "\n"; 453 454 int info = 0; 455 if(SIDE(*side)==INVALID) info = 1; 456 else if(UPLO(*uplo)==INVALID) info = 2; 457 else if(*m<0) info = 3; 458 else if(*n<0) info = 4; 459 else if(*lda<std::max(1,(SIDE(*side)==LEFT)?*m:*n)) info = 7; 460 else if(*ldb<std::max(1,*m)) info = 9; 461 else if(*ldc<std::max(1,*m)) info = 12; 462 if(info) 463 return xerbla_(SCALAR_SUFFIX_UP"HEMM ",&info,6); 464 465 if(beta==Scalar(0)) matrix(c, *m, *n, *ldc).setZero(); 466 else if(beta!=Scalar(1)) matrix(c, *m, *n, *ldc) *= beta; 467 468 if(*m==0 || *n==0) 469 { 470 return 1; 471 } 472 473 if(SIDE(*side)==LEFT) 474 { 475 if(UPLO(*uplo)==UP) internal::product_selfadjoint_matrix<Scalar,DenseIndex,RowMajor,true,Conj, ColMajor,false,false, ColMajor> 476 ::run(*m, *n, a, *lda, b, *ldb, c, *ldc, alpha); 477 else if(UPLO(*uplo)==LO) internal::product_selfadjoint_matrix<Scalar,DenseIndex,ColMajor,true,false, ColMajor,false,false, ColMajor> 478 ::run(*m, *n, a, *lda, b, *ldb, c, *ldc, alpha); 479 else return 0; 480 } 481 else if(SIDE(*side)==RIGHT) 482 { 483 if(UPLO(*uplo)==UP) matrix(c,*m,*n,*ldc) += alpha * matrix(b,*m,*n,*ldb) * matrix(a,*n,*n,*lda).selfadjointView<Upper>();/*internal::product_selfadjoint_matrix<Scalar,DenseIndex,ColMajor,false,false, RowMajor,true,Conj, ColMajor> 484 ::run(*m, *n, b, *ldb, a, *lda, c, *ldc, alpha);*/ 485 else if(UPLO(*uplo)==LO) internal::product_selfadjoint_matrix<Scalar,DenseIndex,ColMajor,false,false, ColMajor,true,false, ColMajor> 486 ::run(*m, *n, b, *ldb, a, *lda, c, *ldc, alpha); 487 else return 0; 488 } 489 else 490 { 491 return 0; 492 } 493 494 return 0; 495 } 496 497 // c = alpha*a*conj(a') + beta*c for op = 'N'or'n' 498 // c = alpha*conj(a')*a + beta*c for op = 'C'or'c' 499 int EIGEN_BLAS_FUNC(herk)(char *uplo, char *op, int *n, int *k, RealScalar *palpha, RealScalar *pa, int *lda, RealScalar *pbeta, RealScalar *pc, int *ldc) 500 { 501 typedef void (*functype)(DenseIndex, DenseIndex, const Scalar *, DenseIndex, const Scalar *, DenseIndex, Scalar *, DenseIndex, Scalar); 502 static functype func[8]; 503 504 static bool init = false; 505 if(!init) 506 { 507 for(int k=0; k<8; ++k) 508 func[k] = 0; 509 510 func[NOTR | (UP << 2)] = (internal::general_matrix_matrix_triangular_product<DenseIndex,Scalar,ColMajor,false,Scalar,RowMajor,Conj, ColMajor,Upper>::run); 511 func[ADJ | (UP << 2)] = (internal::general_matrix_matrix_triangular_product<DenseIndex,Scalar,RowMajor,Conj, Scalar,ColMajor,false,ColMajor,Upper>::run); 512 513 func[NOTR | (LO << 2)] = (internal::general_matrix_matrix_triangular_product<DenseIndex,Scalar,ColMajor,false,Scalar,RowMajor,Conj, ColMajor,Lower>::run); 514 func[ADJ | (LO << 2)] = (internal::general_matrix_matrix_triangular_product<DenseIndex,Scalar,RowMajor,Conj, Scalar,ColMajor,false,ColMajor,Lower>::run); 515 516 init = true; 517 } 518 519 Scalar* a = reinterpret_cast<Scalar*>(pa); 520 Scalar* c = reinterpret_cast<Scalar*>(pc); 521 RealScalar alpha = *palpha; 522 RealScalar beta = *pbeta; 523 524 // std::cerr << "in herk " << *uplo << " " << *op << " " << *n << " " << *k << " " << alpha << " " << *lda << " " << beta << " " << *ldc << "\n"; 525 526 int info = 0; 527 if(UPLO(*uplo)==INVALID) info = 1; 528 else if((OP(*op)==INVALID) || (OP(*op)==TR)) info = 2; 529 else if(*n<0) info = 3; 530 else if(*k<0) info = 4; 531 else if(*lda<std::max(1,(OP(*op)==NOTR)?*n:*k)) info = 7; 532 else if(*ldc<std::max(1,*n)) info = 10; 533 if(info) 534 return xerbla_(SCALAR_SUFFIX_UP"HERK ",&info,6); 535 536 int code = OP(*op) | (UPLO(*uplo) << 2); 537 538 if(beta!=RealScalar(1)) 539 { 540 if(UPLO(*uplo)==UP) 541 if(beta==Scalar(0)) matrix(c, *n, *n, *ldc).triangularView<Upper>().setZero(); 542 else matrix(c, *n, *n, *ldc).triangularView<StrictlyUpper>() *= beta; 543 else 544 if(beta==Scalar(0)) matrix(c, *n, *n, *ldc).triangularView<Lower>().setZero(); 545 else matrix(c, *n, *n, *ldc).triangularView<StrictlyLower>() *= beta; 546 547 if(beta!=Scalar(0)) 548 { 549 matrix(c, *n, *n, *ldc).diagonal().real() *= beta; 550 matrix(c, *n, *n, *ldc).diagonal().imag().setZero(); 551 } 552 } 553 554 if(*k>0 && alpha!=RealScalar(0)) 555 { 556 func[code](*n, *k, a, *lda, a, *lda, c, *ldc, alpha); 557 matrix(c, *n, *n, *ldc).diagonal().imag().setZero(); 558 } 559 return 0; 560 } 561 562 // c = alpha*a*conj(b') + conj(alpha)*b*conj(a') + beta*c, for op = 'N'or'n' 563 // c = alpha*conj(a')*b + conj(alpha)*conj(b')*a + beta*c, for op = 'C'or'c' 564 int EIGEN_BLAS_FUNC(her2k)(char *uplo, char *op, int *n, int *k, RealScalar *palpha, RealScalar *pa, int *lda, RealScalar *pb, int *ldb, RealScalar *pbeta, RealScalar *pc, int *ldc) 565 { 566 Scalar* a = reinterpret_cast<Scalar*>(pa); 567 Scalar* b = reinterpret_cast<Scalar*>(pb); 568 Scalar* c = reinterpret_cast<Scalar*>(pc); 569 Scalar alpha = *reinterpret_cast<Scalar*>(palpha); 570 RealScalar beta = *pbeta; 571 572 int info = 0; 573 if(UPLO(*uplo)==INVALID) info = 1; 574 else if((OP(*op)==INVALID) || (OP(*op)==TR)) info = 2; 575 else if(*n<0) info = 3; 576 else if(*k<0) info = 4; 577 else if(*lda<std::max(1,(OP(*op)==NOTR)?*n:*k)) info = 7; 578 else if(*lda<std::max(1,(OP(*op)==NOTR)?*n:*k)) info = 9; 579 else if(*ldc<std::max(1,*n)) info = 12; 580 if(info) 581 return xerbla_(SCALAR_SUFFIX_UP"HER2K",&info,6); 582 583 if(beta!=RealScalar(1)) 584 { 585 if(UPLO(*uplo)==UP) 586 if(beta==Scalar(0)) matrix(c, *n, *n, *ldc).triangularView<Upper>().setZero(); 587 else matrix(c, *n, *n, *ldc).triangularView<StrictlyUpper>() *= beta; 588 else 589 if(beta==Scalar(0)) matrix(c, *n, *n, *ldc).triangularView<Lower>().setZero(); 590 else matrix(c, *n, *n, *ldc).triangularView<StrictlyLower>() *= beta; 591 592 if(beta!=Scalar(0)) 593 { 594 matrix(c, *n, *n, *ldc).diagonal().real() *= beta; 595 matrix(c, *n, *n, *ldc).diagonal().imag().setZero(); 596 } 597 } 598 else if(*k>0 && alpha!=Scalar(0)) 599 matrix(c, *n, *n, *ldc).diagonal().imag().setZero(); 600 601 if(*k==0) 602 return 1; 603 604 if(OP(*op)==NOTR) 605 { 606 if(UPLO(*uplo)==UP) 607 { 608 matrix(c, *n, *n, *ldc).triangularView<Upper>() 609 += alpha *matrix(a, *n, *k, *lda)*matrix(b, *n, *k, *ldb).adjoint() 610 + internal::conj(alpha)*matrix(b, *n, *k, *ldb)*matrix(a, *n, *k, *lda).adjoint(); 611 } 612 else if(UPLO(*uplo)==LO) 613 matrix(c, *n, *n, *ldc).triangularView<Lower>() 614 += alpha*matrix(a, *n, *k, *lda)*matrix(b, *n, *k, *ldb).adjoint() 615 + internal::conj(alpha)*matrix(b, *n, *k, *ldb)*matrix(a, *n, *k, *lda).adjoint(); 616 } 617 else if(OP(*op)==ADJ) 618 { 619 if(UPLO(*uplo)==UP) 620 matrix(c, *n, *n, *ldc).triangularView<Upper>() 621 += alpha*matrix(a, *k, *n, *lda).adjoint()*matrix(b, *k, *n, *ldb) 622 + internal::conj(alpha)*matrix(b, *k, *n, *ldb).adjoint()*matrix(a, *k, *n, *lda); 623 else if(UPLO(*uplo)==LO) 624 matrix(c, *n, *n, *ldc).triangularView<Lower>() 625 += alpha*matrix(a, *k, *n, *lda).adjoint()*matrix(b, *k, *n, *ldb) 626 + internal::conj(alpha)*matrix(b, *k, *n, *ldb).adjoint()*matrix(a, *k, *n, *lda); 627 } 628 629 return 1; 630 } 631 632 #endif // ISCOMPLEX 633