00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00030 #ifdef _MSC_VER
00031 # pragma once
00032 # pragma warning( push )
00033 # pragma warning( disable : 4512 4714 4786 )
00034 #endif // _MSC_VER
00035
00036 #ifndef _EXMAT_ASSIGNMENT_H
00037 #define _EXMAT_ASSIGNMENT_H
00038
00039 #include "Metaprogramming.h"
00040 #include "Expression.h"
00041 #include "Container/Container.h"
00042
00043 #include "ExpTmp.h"
00044 #include "AliasAnalyser.h"
00045
00046
00047 namespace exmat {
00048
00049 template<class Rep, class ErrChecker_> class Mat;
00050
00051 namespace PNS {
00052
00053
00057
00058 template<class MAT1, class MAT2>
00059 struct Assign_UnRollRowCol_ENV {
00060 EXMAT_INLINE2 Assign_UnRollRowCol_ENV(MAT1& A, const MAT2& B) : A_(A), B_(B) {}
00061 MAT1& A_;
00062 const MAT2& B_;
00063 };
00064 template<class MAT1, class MAT2>
00065 struct Assign_UnRoll_ENV {
00066 EXMAT_INLINE2 Assign_UnRoll_ENV(MAT1& A, const MAT2& B) : A_(A), B_(B) {}
00067 MAT1& A_;
00068 const MAT2& B_;
00069 typename MAT1::index_type i;
00070 };
00071
00073 template<class MAT1, class MAT2, int row_=0, int col_=0>
00074 struct Assign_UnRollRowCol_STAT {
00075 typedef LinearBinExpSize<MAT1, MAT2> BINEXPSize;
00076 enum {
00077 ROWS = BINEXPSize::ROWS,
00078 COLS = BINEXPSize::COLS,
00079 r = col_ == COLS ? row_+1 : row_,
00080 c = col_ < COLS ? col_ : 0
00081 };
00082 EXMAT_INLINE2 static void
00083 exec(Assign_UnRollRowCol_ENV<MAT1, MAT2>& env) {
00084 typedef typename MAT1::value_type value_type;
00085 env.A_.setAt(r, c) = (value_type)(env.B_.getAt(r, c));
00086 }
00087 typedef Assign_UnRollRowCol_STAT<MAT1, MAT2, r, c+1> Next;
00088 enum { Condition = (r < ROWS && c < COLS) };
00089 };
00090
00092 template<class MAT1, class MAT2, int r=0>
00093 struct Assign_UnRollRow_STAT {
00094 typedef LinearBinExpSize<MAT1, MAT2> BINEXPSize;
00095 enum {
00096 ROWS = BINEXPSize::ROWS
00097 };
00098 EXMAT_INLINE2 static void
00099 exec(Assign_UnRoll_ENV<MAT1, MAT2>& env) {
00100 env.A_.setAt(r, env.i) = env.B_.getAt(r, env.i);
00101 }
00102 typedef Assign_UnRollRow_STAT<MAT1, MAT2, r+1> Next;
00103 enum { Condition = (r < ROWS) };
00104 };
00105
00107 template<class MAT1, class MAT2, int c=0>
00108 struct Assign_UnRollCol_STAT {
00109 typedef LinearBinExpSize<MAT1, MAT2> BINEXPSize;
00110 enum {
00111 COLS = BINEXPSize::COLS
00112 };
00113 EXMAT_INLINE2 static void
00114 exec(Assign_UnRoll_ENV<MAT1, MAT2>& env) {
00115 env.A_.setAt(env.i, c) = env.B_.getAt(env.i, c);
00116 }
00117 typedef Assign_UnRollCol_STAT<MAT1, MAT2, c+1> Next;
00118 enum { Condition = (c < COLS) };
00119 };
00120
00122 template<class MAT1, class MAT2> EXMAT_INLINE2
00123 static void Assign_FullUnRoll(MAT1& A, const MAT2& B) {
00124 Assign_UnRollRowCol_ENV<MAT1, MAT2> env(A, B);
00125 EWHILE1<Assign_UnRollRowCol_STAT<MAT1, MAT2> >::exec(env);
00126 }
00128 template<class MAT1, class MAT2> EXMAT_INLINE2
00129 static void Assign_FullUnRollRow(MAT1& A, const MAT2& B) {
00130 Assign_UnRoll_ENV<MAT1, MAT2> env(A, B);
00131 typename MAT1::index_type cols_ = A.cols();
00132 for(env.i=0; env.i<cols_; ++env.i )
00133 EWHILE1<Assign_UnRollRow_STAT<MAT1, MAT2> >::exec(env);
00134 }
00136 template<class MAT1, class MAT2> EXMAT_INLINE2
00137 static void Assign_FullUnRollCol(MAT1& A, const MAT2& B) {
00138 Assign_UnRoll_ENV<MAT1, MAT2> env(A, B);
00139 typename MAT1::index_type rows_ = A.rows();
00140 for(env.i=0; env.i<rows_; ++env.i )
00141 EWHILE1<Assign_UnRollCol_STAT<MAT1, MAT2> >::exec(env);
00142 }
00146 template<class MAT1, class MAT2> EXMAT_INLINE1
00147 static void Assign_PartialUnRoll(MAT1& A, const MAT2& B) {
00148 typedef typename MAT1::index_type index_type;
00149 index_type rows_ = A.rows();
00150 index_type cols_ = A.cols();
00151 for(index_type i=0; i<rows_; ++i ) {
00152 register int n=(cols_+7)/8;
00153 int j = -1;
00154 switch(cols_%8) {
00155 case 0: do{ A.setAt(i, j) = B.getAt(i, ++j);
00156 case 7: A.setAt(i, j) = B.getAt(i, ++j);
00157 case 6: A.setAt(i, j) = B.getAt(i, ++j);
00158 case 5: A.setAt(i, j) = B.getAt(i, ++j);
00159 case 4: A.setAt(i, j) = B.getAt(i, ++j);
00160 case 3: A.setAt(i, j) = B.getAt(i, ++j);
00161 case 2: A.setAt(i, j) = B.getAt(i, ++j);
00162 case 1: A.setAt(i, j) = B.getAt(i, ++j);
00163 } while(--n>0);
00164 }
00165 }
00166 }
00168 template<class MAT1, class MAT2> EXMAT_INLINE1
00169 static void Assign_NoUnRoll(MAT1& A, const MAT2& B) {
00170 typedef typename MAT1::index_type index_type;
00171 typedef typename MAT1::value_type value_type;
00172 index_type rows_ = A.rows();
00173 index_type cols_ = A.cols();
00174 for(index_type i=0; i<rows_; ++i ) {
00175 for(index_type j=0; j<cols_; ++j )
00176 A.setAt(i, j) = value_type(B.getAt(i, j));
00177 }
00178 }
00180 template<class MAT1, class MAT2, int i=0>
00181 struct Assign_UnRollSIMDSTAT {
00182 enum {
00183 nUnits = MAT1::nUnit,
00184 };
00185 EXMAT_INLINE2 static void
00186 exec(Assign_UnRollRowCol_ENV<MAT1, MAT2>& env) {
00187 env.A_.setUnitAt(i) = env.B_.getUnitAt(i);
00188 }
00189 typedef Assign_UnRollSIMDSTAT<MAT1, MAT2, i+1> Next;
00190 enum { Condition = (i < nUnits) };
00191 };
00193 template<class MAT1, class MAT2> EXMAT_INLINE2
00194 static void Assign_FullUnRollSIMD(MAT1& A, const MAT2& B) {
00195 Assign_UnRollRowCol_ENV<MAT1, MAT2> env(A, B);
00196 EWHILE1<Assign_UnRollSIMDSTAT<MAT1, MAT2> >::exec(env);
00197 }
00199
00201 struct ASSIGN_TYPE {
00202 enum {
00203 Ass_NoUnRoll = 0,
00204 Ass_FullUnRollRow = 1,
00205 Ass_FullUnRollCol = 2,
00206 Ass_FullUnRoll = 3,
00207 Ass_SIMD = 4
00208 };
00209 };
00210
00211
00216 template<class MAT1, class MAT2> EXMAT_INLINE2 static
00217 void Assign(MAT1& A, const MAT2& B, Int2Type<ASSIGN_TYPE::Ass_FullUnRoll>) {
00218 #if ENABLE_UNROLLING
00219 Assign_FullUnRoll(A, B);
00220 #else
00221 Assign_NoUnRoll(A, B);
00222 #endif
00223 }
00224 template<class MAT1, class MAT2> EXMAT_INLINE2 static
00225 void Assign(MAT1& A, const MAT2& B, Int2Type<ASSIGN_TYPE::Ass_FullUnRollRow>) {
00226 #if ENABLE_UNROLLING
00227 Assign_FullUnRollRow(A, B);
00228 #else
00229 Assign_NoUnRoll(A, B);
00230 #endif
00231 }
00232 template<class MAT1, class MAT2> EXMAT_INLINE2 static
00233 void Assign(MAT1& A, const MAT2& B, Int2Type<ASSIGN_TYPE::Ass_FullUnRollCol>) {
00234 #if ENABLE_UNROLLING
00235 Assign_FullUnRollCol(A, B);
00236 #else
00237 Assign_NoUnRoll(A, B);
00238 #endif
00239 }
00240 template<class MAT1, class MAT2> EXMAT_INLINE2 static
00241 void Assign(MAT1& A, const MAT2& B, Int2Type<ASSIGN_TYPE::Ass_NoUnRoll>) {
00242 Assign_NoUnRoll(A, B);
00243
00244
00245 }
00246 template<class MAT1, class MAT2> EXMAT_INLINE2 static
00247 void Assign(MAT1& A, const MAT2& B, Int2Type<ASSIGN_TYPE::Ass_SIMD>) {
00248 enum {
00249 WholeAssign =
00250 IsDerivedFrom<MAT2, MulExpTag>::RET &&
00251 !MAT2::IsLinearRecursive &&
00252 MAT2::EXPLevel == 2,
00253 };
00254 Assign_SIMD_inner(A, B, Int2Type<WholeAssign>());
00255 }
00256 template<class MAT1, class MAT2> EXMAT_INLINE2 static
00257 void Assign_SIMD_inner(MAT1& A, const MAT2& B, Int2Type<true> WholeAssign) {
00258 #if EXMAT_ENABLE_SIMD
00259 typedef typename MAT1::value_type value_type;
00260 exmat::SIMD::SIMDMatMul(A, B.leftOp, B.rightOp, Type2Type<value_type>());
00261
00262 #else
00263 Assign_NoUnRoll(A, B);
00264 #endif // EXMAT_ENABLE_SIMD
00265 }
00266 template<class MAT1, class MAT2> EXMAT_INLINE2 static
00267 void Assign_SIMD_inner(MAT1& A, const MAT2& B, Int2Type<false> WholeAssign) {
00268 Assign_FullUnRollSIMD(A, B);
00269
00270
00271 }
00273
00274 };
00275
00276
00278 struct ASSIGN_ANALYSIS {
00279 enum {
00280 NONE = 1 << 0,
00281 ALIAS = 1 << 1,
00282 TEMPORARY = 1 << 2
00283 };
00284 };
00285
00286 template<class Mat1, class Mat2> EXMAT_INLINE2 static
00287 void CopyDimension_inner(Mat1& dest, const Mat2& src, Int2Type<false>, Int2Type<false>) {
00288 }
00289 template<class Mat1, class Mat2> EXMAT_INLINE0 static
00290 void CopyDimension_inner(Mat1& dest, const Mat2& src, Int2Type<true>, Int2Type<false>) {
00291 dest.resize(src.rows());
00292 }
00293 template<class Mat1, class Mat2> EXMAT_INLINE0 static
00294 void CopyDimension_inner(Mat1& dest, const Mat2& src, Int2Type<false>, Int2Type<true>) {
00295 dest.resize(src.cols());
00296 }
00297 template<class Mat1, class Mat2> EXMAT_INLINE0 static
00298 void CopyDimension_inner(Mat1& dest, const Mat2& src, Int2Type<true>, Int2Type<true>) {
00299 dest.resize(src.rows(), src.cols());
00300 }
00301
00302 template<class Mat1, class Mat2> EXMAT_INLINE0 static
00303 void CopyDimension(Mat1& dest, const Mat2& src) {
00304 CopyDimension_inner(dest, src, Int2Type<Mat1::ROWS==0>(), Int2Type<Mat1::COLS==0>());
00305 }
00306
00307 template<class Rep1, class Rep2, class EC1, class EC2> EXMAT_INLINE2 static
00308 void assign(Mat<Rep1,EC1>& dest, const Mat<Rep2,EC2>& exp, int assign_type=EXMAT_DEFAULT_ANALYSIS)
00309 {
00310 using namespace exmat::PNS;
00311 #if ENABLE_ALIAS_ANALYSIS
00312 if((assign_type & ASSIGN_ANALYSIS::ALIAS) != 0) {
00313 if(IsAliased(dest, exp)) {
00314 typename GetAliasTmpType<Mat<Rep1,EC1> >::RET tmp;
00315
00316 CopyDimension(tmp, dest);
00317
00318
00319
00320 # if EXMAT_VC6 || EXMAT_VC7 || EXMAT_VC2003 || EXMAT_VC2005 || EXMAT_GNUC
00321 # if ENABLE_TMP_ANALYSIS
00322 if((assign_type & ASSIGN_ANALYSIS::TEMPORARY) != 0)
00323 parseExp(tmp, exp);
00324 else
00325 # endif // ENABLE_TMP_ANALYSIS
00326 GetAliasTmpType<Mat<Rep1,EC1> >::RET::AssignDispatcher(tmp, exp);
00327 # else
00328
00329 assign(tmp, exp, (assign_type & ~ASSIGN_ANALYSIS::ALIAS));
00330 # endif
00331
00332 Mat<Rep1,EC1>::AssignDispatcher(dest, tmp);
00333 return;
00334 }
00335 }
00336 #endif // ENABLE_ALIAS_ANALYSIS
00337
00338 #if ENABLE_TMP_ANALYSIS
00339 if((assign_type & ASSIGN_ANALYSIS::TEMPORARY) != 0) {
00340 parseExp(dest, exp);
00341 return;
00342 }
00343 #endif // ENABLE_TMP_ANALYSIS
00344
00345 Mat<Rep1,EC1>::AssignDispatcher(dest, exp);
00346 }
00347
00348
00349 }
00350
00351 #if _MSC_VER
00352 # pragma warning( pop )
00353 #endif // EXMAT_VC
00354
00355 #endif // _EXMAT_ASSIGNMENT_H