MOAB
4.9.3pre
|
00001 // This file is part of Eigen, a lightweight C++ template library 00002 // for linear algebra. 00003 // 00004 // Copyright (C) 2009 Gael Guennebaud <[email protected]> 00005 // 00006 // This Source Code Form is subject to the terms of the Mozilla 00007 // Public License v. 2.0. If a copy of the MPL was not distributed 00008 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 00009 00010 #ifndef EIGEN_SELFADJOINT_MATRIX_MATRIX_H 00011 #define EIGEN_SELFADJOINT_MATRIX_MATRIX_H 00012 00013 namespace Eigen { 00014 00015 namespace internal { 00016 00017 // pack a selfadjoint block diagonal for use with the gebp_kernel 00018 template<typename Scalar, typename Index, int Pack1, int Pack2_dummy, int StorageOrder> 00019 struct symm_pack_lhs 00020 { 00021 template<int BlockRows> inline 00022 void pack(Scalar* blockA, const const_blas_data_mapper<Scalar,Index,StorageOrder>& lhs, Index cols, Index i, Index& count) 00023 { 00024 // normal copy 00025 for(Index k=0; k<i; k++) 00026 for(Index w=0; w<BlockRows; w++) 00027 blockA[count++] = lhs(i+w,k); // normal 00028 // symmetric copy 00029 Index h = 0; 00030 for(Index k=i; k<i+BlockRows; k++) 00031 { 00032 for(Index w=0; w<h; w++) 00033 blockA[count++] = numext::conj(lhs(k, i+w)); // transposed 00034 00035 blockA[count++] = numext::real(lhs(k,k)); // real (diagonal) 00036 00037 for(Index w=h+1; w<BlockRows; w++) 00038 blockA[count++] = lhs(i+w, k); // normal 00039 ++h; 00040 } 00041 // transposed copy 00042 for(Index k=i+BlockRows; k<cols; k++) 00043 for(Index w=0; w<BlockRows; w++) 00044 blockA[count++] = numext::conj(lhs(k, i+w)); // transposed 00045 } 00046 void operator()(Scalar* blockA, const Scalar* _lhs, Index lhsStride, Index cols, Index rows) 00047 { 00048 enum { PacketSize = packet_traits<Scalar>::size }; 00049 const_blas_data_mapper<Scalar,Index,StorageOrder> lhs(_lhs,lhsStride); 00050 Index count = 0; 00051 //Index peeled_mc3 = (rows/Pack1)*Pack1; 00052 00053 const Index peeled_mc3 = Pack1>=3*PacketSize ? (rows/(3*PacketSize))*(3*PacketSize) : 0; 00054 const Index peeled_mc2 = Pack1>=2*PacketSize ? peeled_mc3+((rows-peeled_mc3)/(2*PacketSize))*(2*PacketSize) : 0; 00055 const Index peeled_mc1 = Pack1>=1*PacketSize ? (rows/(1*PacketSize))*(1*PacketSize) : 0; 00056 00057 if(Pack1>=3*PacketSize) 00058 for(Index i=0; i<peeled_mc3; i+=3*PacketSize) 00059 pack<3*PacketSize>(blockA, lhs, cols, i, count); 00060 00061 if(Pack1>=2*PacketSize) 00062 for(Index i=peeled_mc3; i<peeled_mc2; i+=2*PacketSize) 00063 pack<2*PacketSize>(blockA, lhs, cols, i, count); 00064 00065 if(Pack1>=1*PacketSize) 00066 for(Index i=peeled_mc2; i<peeled_mc1; i+=1*PacketSize) 00067 pack<1*PacketSize>(blockA, lhs, cols, i, count); 00068 00069 // do the same with mr==1 00070 for(Index i=peeled_mc1; i<rows; i++) 00071 { 00072 for(Index k=0; k<i; k++) 00073 blockA[count++] = lhs(i, k); // normal 00074 00075 blockA[count++] = numext::real(lhs(i, i)); // real (diagonal) 00076 00077 for(Index k=i+1; k<cols; k++) 00078 blockA[count++] = numext::conj(lhs(k, i)); // transposed 00079 } 00080 } 00081 }; 00082 00083 template<typename Scalar, typename Index, int nr, int StorageOrder> 00084 struct symm_pack_rhs 00085 { 00086 enum { PacketSize = packet_traits<Scalar>::size }; 00087 void operator()(Scalar* blockB, const Scalar* _rhs, Index rhsStride, Index rows, Index cols, Index k2) 00088 { 00089 Index end_k = k2 + rows; 00090 Index count = 0; 00091 const_blas_data_mapper<Scalar,Index,StorageOrder> rhs(_rhs,rhsStride); 00092 Index packet_cols8 = nr>=8 ? (cols/8) * 8 : 0; 00093 Index packet_cols4 = nr>=4 ? (cols/4) * 4 : 0; 00094 00095 // first part: normal case 00096 for(Index j2=0; j2<k2; j2+=nr) 00097 { 00098 for(Index k=k2; k<end_k; k++) 00099 { 00100 blockB[count+0] = rhs(k,j2+0); 00101 blockB[count+1] = rhs(k,j2+1); 00102 if (nr>=4) 00103 { 00104 blockB[count+2] = rhs(k,j2+2); 00105 blockB[count+3] = rhs(k,j2+3); 00106 } 00107 if (nr>=8) 00108 { 00109 blockB[count+4] = rhs(k,j2+4); 00110 blockB[count+5] = rhs(k,j2+5); 00111 blockB[count+6] = rhs(k,j2+6); 00112 blockB[count+7] = rhs(k,j2+7); 00113 } 00114 count += nr; 00115 } 00116 } 00117 00118 // second part: diagonal block 00119 Index end8 = nr>=8 ? (std::min)(k2+rows,packet_cols8) : k2; 00120 if(nr>=8) 00121 { 00122 for(Index j2=k2; j2<end8; j2+=8) 00123 { 00124 // again we can split vertically in three different parts (transpose, symmetric, normal) 00125 // transpose 00126 for(Index k=k2; k<j2; k++) 00127 { 00128 blockB[count+0] = numext::conj(rhs(j2+0,k)); 00129 blockB[count+1] = numext::conj(rhs(j2+1,k)); 00130 blockB[count+2] = numext::conj(rhs(j2+2,k)); 00131 blockB[count+3] = numext::conj(rhs(j2+3,k)); 00132 blockB[count+4] = numext::conj(rhs(j2+4,k)); 00133 blockB[count+5] = numext::conj(rhs(j2+5,k)); 00134 blockB[count+6] = numext::conj(rhs(j2+6,k)); 00135 blockB[count+7] = numext::conj(rhs(j2+7,k)); 00136 count += 8; 00137 } 00138 // symmetric 00139 Index h = 0; 00140 for(Index k=j2; k<j2+8; k++) 00141 { 00142 // normal 00143 for (Index w=0 ; w<h; ++w) 00144 blockB[count+w] = rhs(k,j2+w); 00145 00146 blockB[count+h] = numext::real(rhs(k,k)); 00147 00148 // transpose 00149 for (Index w=h+1 ; w<8; ++w) 00150 blockB[count+w] = numext::conj(rhs(j2+w,k)); 00151 count += 8; 00152 ++h; 00153 } 00154 // normal 00155 for(Index k=j2+8; k<end_k; k++) 00156 { 00157 blockB[count+0] = rhs(k,j2+0); 00158 blockB[count+1] = rhs(k,j2+1); 00159 blockB[count+2] = rhs(k,j2+2); 00160 blockB[count+3] = rhs(k,j2+3); 00161 blockB[count+4] = rhs(k,j2+4); 00162 blockB[count+5] = rhs(k,j2+5); 00163 blockB[count+6] = rhs(k,j2+6); 00164 blockB[count+7] = rhs(k,j2+7); 00165 count += 8; 00166 } 00167 } 00168 } 00169 if(nr>=4) 00170 { 00171 for(Index j2=end8; j2<(std::min)(k2+rows,packet_cols4); j2+=4) 00172 { 00173 // again we can split vertically in three different parts (transpose, symmetric, normal) 00174 // transpose 00175 for(Index k=k2; k<j2; k++) 00176 { 00177 blockB[count+0] = numext::conj(rhs(j2+0,k)); 00178 blockB[count+1] = numext::conj(rhs(j2+1,k)); 00179 blockB[count+2] = numext::conj(rhs(j2+2,k)); 00180 blockB[count+3] = numext::conj(rhs(j2+3,k)); 00181 count += 4; 00182 } 00183 // symmetric 00184 Index h = 0; 00185 for(Index k=j2; k<j2+4; k++) 00186 { 00187 // normal 00188 for (Index w=0 ; w<h; ++w) 00189 blockB[count+w] = rhs(k,j2+w); 00190 00191 blockB[count+h] = numext::real(rhs(k,k)); 00192 00193 // transpose 00194 for (Index w=h+1 ; w<4; ++w) 00195 blockB[count+w] = numext::conj(rhs(j2+w,k)); 00196 count += 4; 00197 ++h; 00198 } 00199 // normal 00200 for(Index k=j2+4; k<end_k; k++) 00201 { 00202 blockB[count+0] = rhs(k,j2+0); 00203 blockB[count+1] = rhs(k,j2+1); 00204 blockB[count+2] = rhs(k,j2+2); 00205 blockB[count+3] = rhs(k,j2+3); 00206 count += 4; 00207 } 00208 } 00209 } 00210 00211 // third part: transposed 00212 if(nr>=8) 00213 { 00214 for(Index j2=k2+rows; j2<packet_cols8; j2+=8) 00215 { 00216 for(Index k=k2; k<end_k; k++) 00217 { 00218 blockB[count+0] = numext::conj(rhs(j2+0,k)); 00219 blockB[count+1] = numext::conj(rhs(j2+1,k)); 00220 blockB[count+2] = numext::conj(rhs(j2+2,k)); 00221 blockB[count+3] = numext::conj(rhs(j2+3,k)); 00222 blockB[count+4] = numext::conj(rhs(j2+4,k)); 00223 blockB[count+5] = numext::conj(rhs(j2+5,k)); 00224 blockB[count+6] = numext::conj(rhs(j2+6,k)); 00225 blockB[count+7] = numext::conj(rhs(j2+7,k)); 00226 count += 8; 00227 } 00228 } 00229 } 00230 if(nr>=4) 00231 { 00232 for(Index j2=(std::max)(packet_cols8,k2+rows); j2<packet_cols4; j2+=4) 00233 { 00234 for(Index k=k2; k<end_k; k++) 00235 { 00236 blockB[count+0] = numext::conj(rhs(j2+0,k)); 00237 blockB[count+1] = numext::conj(rhs(j2+1,k)); 00238 blockB[count+2] = numext::conj(rhs(j2+2,k)); 00239 blockB[count+3] = numext::conj(rhs(j2+3,k)); 00240 count += 4; 00241 } 00242 } 00243 } 00244 00245 // copy the remaining columns one at a time (=> the same with nr==1) 00246 for(Index j2=packet_cols4; j2<cols; ++j2) 00247 { 00248 // transpose 00249 Index half = (std::min)(end_k,j2); 00250 for(Index k=k2; k<half; k++) 00251 { 00252 blockB[count] = numext::conj(rhs(j2,k)); 00253 count += 1; 00254 } 00255 00256 if(half==j2 && half<k2+rows) 00257 { 00258 blockB[count] = numext::real(rhs(j2,j2)); 00259 count += 1; 00260 } 00261 else 00262 half--; 00263 00264 // normal 00265 for(Index k=half+1; k<k2+rows; k++) 00266 { 00267 blockB[count] = rhs(k,j2); 00268 count += 1; 00269 } 00270 } 00271 } 00272 }; 00273 00274 /* Optimized selfadjoint matrix * matrix (_SYMM) product built on top of 00275 * the general matrix matrix product. 00276 */ 00277 template <typename Scalar, typename Index, 00278 int LhsStorageOrder, bool LhsSelfAdjoint, bool ConjugateLhs, 00279 int RhsStorageOrder, bool RhsSelfAdjoint, bool ConjugateRhs, 00280 int ResStorageOrder> 00281 struct product_selfadjoint_matrix; 00282 00283 template <typename Scalar, typename Index, 00284 int LhsStorageOrder, bool LhsSelfAdjoint, bool ConjugateLhs, 00285 int RhsStorageOrder, bool RhsSelfAdjoint, bool ConjugateRhs> 00286 struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,LhsSelfAdjoint,ConjugateLhs, RhsStorageOrder,RhsSelfAdjoint,ConjugateRhs,RowMajor> 00287 { 00288 00289 static EIGEN_STRONG_INLINE void run( 00290 Index rows, Index cols, 00291 const Scalar* lhs, Index lhsStride, 00292 const Scalar* rhs, Index rhsStride, 00293 Scalar* res, Index resStride, 00294 const Scalar& alpha, level3_blocking<Scalar,Scalar>& blocking) 00295 { 00296 product_selfadjoint_matrix<Scalar, Index, 00297 EIGEN_LOGICAL_XOR(RhsSelfAdjoint,RhsStorageOrder==RowMajor) ? ColMajor : RowMajor, 00298 RhsSelfAdjoint, NumTraits<Scalar>::IsComplex && EIGEN_LOGICAL_XOR(RhsSelfAdjoint,ConjugateRhs), 00299 EIGEN_LOGICAL_XOR(LhsSelfAdjoint,LhsStorageOrder==RowMajor) ? ColMajor : RowMajor, 00300 LhsSelfAdjoint, NumTraits<Scalar>::IsComplex && EIGEN_LOGICAL_XOR(LhsSelfAdjoint,ConjugateLhs), 00301 ColMajor> 00302 ::run(cols, rows, rhs, rhsStride, lhs, lhsStride, res, resStride, alpha, blocking); 00303 } 00304 }; 00305 00306 template <typename Scalar, typename Index, 00307 int LhsStorageOrder, bool ConjugateLhs, 00308 int RhsStorageOrder, bool ConjugateRhs> 00309 struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,true,ConjugateLhs, RhsStorageOrder,false,ConjugateRhs,ColMajor> 00310 { 00311 00312 static EIGEN_DONT_INLINE void run( 00313 Index rows, Index cols, 00314 const Scalar* _lhs, Index lhsStride, 00315 const Scalar* _rhs, Index rhsStride, 00316 Scalar* res, Index resStride, 00317 const Scalar& alpha, level3_blocking<Scalar,Scalar>& blocking); 00318 }; 00319 00320 template <typename Scalar, typename Index, 00321 int LhsStorageOrder, bool ConjugateLhs, 00322 int RhsStorageOrder, bool ConjugateRhs> 00323 EIGEN_DONT_INLINE void product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,true,ConjugateLhs, RhsStorageOrder,false,ConjugateRhs,ColMajor>::run( 00324 Index rows, Index cols, 00325 const Scalar* _lhs, Index lhsStride, 00326 const Scalar* _rhs, Index rhsStride, 00327 Scalar* _res, Index resStride, 00328 const Scalar& alpha, level3_blocking<Scalar,Scalar>& blocking) 00329 { 00330 Index size = rows; 00331 00332 typedef gebp_traits<Scalar,Scalar> Traits; 00333 00334 typedef const_blas_data_mapper<Scalar, Index, LhsStorageOrder> LhsMapper; 00335 typedef const_blas_data_mapper<Scalar, Index, (LhsStorageOrder == RowMajor) ? ColMajor : RowMajor> LhsTransposeMapper; 00336 typedef const_blas_data_mapper<Scalar, Index, RhsStorageOrder> RhsMapper; 00337 typedef blas_data_mapper<typename Traits::ResScalar, Index, ColMajor> ResMapper; 00338 LhsMapper lhs(_lhs,lhsStride); 00339 LhsTransposeMapper lhs_transpose(_lhs,lhsStride); 00340 RhsMapper rhs(_rhs,rhsStride); 00341 ResMapper res(_res, resStride); 00342 00343 Index kc = blocking.kc(); // cache block size along the K direction 00344 Index mc = (std::min)(rows,blocking.mc()); // cache block size along the M direction 00345 // kc must be smaller than mc 00346 kc = (std::min)(kc,mc); 00347 std::size_t sizeA = kc*mc; 00348 std::size_t sizeB = kc*cols; 00349 ei_declare_aligned_stack_constructed_variable(Scalar, blockA, sizeA, blocking.blockA()); 00350 ei_declare_aligned_stack_constructed_variable(Scalar, blockB, sizeB, blocking.blockB()); 00351 00352 gebp_kernel<Scalar, Scalar, Index, ResMapper, Traits::mr, Traits::nr, ConjugateLhs, ConjugateRhs> gebp_kernel; 00353 symm_pack_lhs<Scalar, Index, Traits::mr, Traits::LhsProgress, LhsStorageOrder> pack_lhs; 00354 gemm_pack_rhs<Scalar, Index, RhsMapper, Traits::nr,RhsStorageOrder> pack_rhs; 00355 gemm_pack_lhs<Scalar, Index, LhsTransposeMapper, Traits::mr, Traits::LhsProgress, LhsStorageOrder==RowMajor?ColMajor:RowMajor, true> pack_lhs_transposed; 00356 00357 for(Index k2=0; k2<size; k2+=kc) 00358 { 00359 const Index actual_kc = (std::min)(k2+kc,size)-k2; 00360 00361 // we have selected one row panel of rhs and one column panel of lhs 00362 // pack rhs's panel into a sequential chunk of memory 00363 // and expand each coeff to a constant packet for further reuse 00364 pack_rhs(blockB, rhs.getSubMapper(k2,0), actual_kc, cols); 00365 00366 // the select lhs's panel has to be split in three different parts: 00367 // 1 - the transposed panel above the diagonal block => transposed packed copy 00368 // 2 - the diagonal block => special packed copy 00369 // 3 - the panel below the diagonal block => generic packed copy 00370 for(Index i2=0; i2<k2; i2+=mc) 00371 { 00372 const Index actual_mc = (std::min)(i2+mc,k2)-i2; 00373 // transposed packed copy 00374 pack_lhs_transposed(blockA, lhs_transpose.getSubMapper(i2, k2), actual_kc, actual_mc); 00375 00376 gebp_kernel(res.getSubMapper(i2, 0), blockA, blockB, actual_mc, actual_kc, cols, alpha); 00377 } 00378 // the block diagonal 00379 { 00380 const Index actual_mc = (std::min)(k2+kc,size)-k2; 00381 // symmetric packed copy 00382 pack_lhs(blockA, &lhs(k2,k2), lhsStride, actual_kc, actual_mc); 00383 00384 gebp_kernel(res.getSubMapper(k2, 0), blockA, blockB, actual_mc, actual_kc, cols, alpha); 00385 } 00386 00387 for(Index i2=k2+kc; i2<size; i2+=mc) 00388 { 00389 const Index actual_mc = (std::min)(i2+mc,size)-i2; 00390 gemm_pack_lhs<Scalar, Index, LhsMapper, Traits::mr, Traits::LhsProgress, LhsStorageOrder,false>() 00391 (blockA, lhs.getSubMapper(i2, k2), actual_kc, actual_mc); 00392 00393 gebp_kernel(res.getSubMapper(i2, 0), blockA, blockB, actual_mc, actual_kc, cols, alpha); 00394 } 00395 } 00396 } 00397 00398 // matrix * selfadjoint product 00399 template <typename Scalar, typename Index, 00400 int LhsStorageOrder, bool ConjugateLhs, 00401 int RhsStorageOrder, bool ConjugateRhs> 00402 struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,false,ConjugateLhs, RhsStorageOrder,true,ConjugateRhs,ColMajor> 00403 { 00404 00405 static EIGEN_DONT_INLINE void run( 00406 Index rows, Index cols, 00407 const Scalar* _lhs, Index lhsStride, 00408 const Scalar* _rhs, Index rhsStride, 00409 Scalar* res, Index resStride, 00410 const Scalar& alpha, level3_blocking<Scalar,Scalar>& blocking); 00411 }; 00412 00413 template <typename Scalar, typename Index, 00414 int LhsStorageOrder, bool ConjugateLhs, 00415 int RhsStorageOrder, bool ConjugateRhs> 00416 EIGEN_DONT_INLINE void product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,false,ConjugateLhs, RhsStorageOrder,true,ConjugateRhs,ColMajor>::run( 00417 Index rows, Index cols, 00418 const Scalar* _lhs, Index lhsStride, 00419 const Scalar* _rhs, Index rhsStride, 00420 Scalar* _res, Index resStride, 00421 const Scalar& alpha, level3_blocking<Scalar,Scalar>& blocking) 00422 { 00423 Index size = cols; 00424 00425 typedef gebp_traits<Scalar,Scalar> Traits; 00426 00427 typedef const_blas_data_mapper<Scalar, Index, LhsStorageOrder> LhsMapper; 00428 typedef blas_data_mapper<typename Traits::ResScalar, Index, ColMajor> ResMapper; 00429 LhsMapper lhs(_lhs,lhsStride); 00430 ResMapper res(_res,resStride); 00431 00432 Index kc = blocking.kc(); // cache block size along the K direction 00433 Index mc = (std::min)(rows,blocking.mc()); // cache block size along the M direction 00434 std::size_t sizeA = kc*mc; 00435 std::size_t sizeB = kc*cols; 00436 ei_declare_aligned_stack_constructed_variable(Scalar, blockA, sizeA, blocking.blockA()); 00437 ei_declare_aligned_stack_constructed_variable(Scalar, blockB, sizeB, blocking.blockB()); 00438 00439 gebp_kernel<Scalar, Scalar, Index, ResMapper, Traits::mr, Traits::nr, ConjugateLhs, ConjugateRhs> gebp_kernel; 00440 gemm_pack_lhs<Scalar, Index, LhsMapper, Traits::mr, Traits::LhsProgress, LhsStorageOrder> pack_lhs; 00441 symm_pack_rhs<Scalar, Index, Traits::nr,RhsStorageOrder> pack_rhs; 00442 00443 for(Index k2=0; k2<size; k2+=kc) 00444 { 00445 const Index actual_kc = (std::min)(k2+kc,size)-k2; 00446 00447 pack_rhs(blockB, _rhs, rhsStride, actual_kc, cols, k2); 00448 00449 // => GEPP 00450 for(Index i2=0; i2<rows; i2+=mc) 00451 { 00452 const Index actual_mc = (std::min)(i2+mc,rows)-i2; 00453 pack_lhs(blockA, lhs.getSubMapper(i2, k2), actual_kc, actual_mc); 00454 00455 gebp_kernel(res.getSubMapper(i2, 0), blockA, blockB, actual_mc, actual_kc, cols, alpha); 00456 } 00457 } 00458 } 00459 00460 } // end namespace internal 00461 00462 /*************************************************************************** 00463 * Wrapper to product_selfadjoint_matrix 00464 ***************************************************************************/ 00465 00466 namespace internal { 00467 00468 template<typename Lhs, int LhsMode, typename Rhs, int RhsMode> 00469 struct selfadjoint_product_impl<Lhs,LhsMode,false,Rhs,RhsMode,false> 00470 { 00471 typedef typename Product<Lhs,Rhs>::Scalar Scalar; 00472 00473 typedef internal::blas_traits<Lhs> LhsBlasTraits; 00474 typedef typename LhsBlasTraits::DirectLinearAccessType ActualLhsType; 00475 typedef internal::blas_traits<Rhs> RhsBlasTraits; 00476 typedef typename RhsBlasTraits::DirectLinearAccessType ActualRhsType; 00477 00478 enum { 00479 LhsIsUpper = (LhsMode&(Upper|Lower))==Upper, 00480 LhsIsSelfAdjoint = (LhsMode&SelfAdjoint)==SelfAdjoint, 00481 RhsIsUpper = (RhsMode&(Upper|Lower))==Upper, 00482 RhsIsSelfAdjoint = (RhsMode&SelfAdjoint)==SelfAdjoint 00483 }; 00484 00485 template<typename Dest> 00486 static void run(Dest &dst, const Lhs &a_lhs, const Rhs &a_rhs, const Scalar& alpha) 00487 { 00488 eigen_assert(dst.rows()==a_lhs.rows() && dst.cols()==a_rhs.cols()); 00489 00490 typename internal::add_const_on_value_type<ActualLhsType>::type lhs = LhsBlasTraits::extract(a_lhs); 00491 typename internal::add_const_on_value_type<ActualRhsType>::type rhs = RhsBlasTraits::extract(a_rhs); 00492 00493 Scalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(a_lhs) 00494 * RhsBlasTraits::extractScalarFactor(a_rhs); 00495 00496 typedef internal::gemm_blocking_space<(Dest::Flags&RowMajorBit) ? RowMajor : ColMajor,Scalar,Scalar, 00497 Lhs::MaxRowsAtCompileTime, Rhs::MaxColsAtCompileTime, Lhs::MaxColsAtCompileTime,1> BlockingType; 00498 00499 BlockingType blocking(lhs.rows(), rhs.cols(), lhs.cols(), 1, false); 00500 00501 internal::product_selfadjoint_matrix<Scalar, Index, 00502 EIGEN_LOGICAL_XOR(LhsIsUpper,internal::traits<Lhs>::Flags &RowMajorBit) ? RowMajor : ColMajor, LhsIsSelfAdjoint, 00503 NumTraits<Scalar>::IsComplex && EIGEN_LOGICAL_XOR(LhsIsUpper,bool(LhsBlasTraits::NeedToConjugate)), 00504 EIGEN_LOGICAL_XOR(RhsIsUpper,internal::traits<Rhs>::Flags &RowMajorBit) ? RowMajor : ColMajor, RhsIsSelfAdjoint, 00505 NumTraits<Scalar>::IsComplex && EIGEN_LOGICAL_XOR(RhsIsUpper,bool(RhsBlasTraits::NeedToConjugate)), 00506 internal::traits<Dest>::Flags&RowMajorBit ? RowMajor : ColMajor> 00507 ::run( 00508 lhs.rows(), rhs.cols(), // sizes 00509 &lhs.coeffRef(0,0), lhs.outerStride(), // lhs info 00510 &rhs.coeffRef(0,0), rhs.outerStride(), // rhs info 00511 &dst.coeffRef(0,0), dst.outerStride(), // result info 00512 actualAlpha, blocking // alpha 00513 ); 00514 } 00515 }; 00516 00517 } // end namespace internal 00518 00519 } // end namespace Eigen 00520 00521 #endif // EIGEN_SELFADJOINT_MATRIX_MATRIX_H