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 : 4100 4127 4512 4786 )
00034 #endif // _MSC_VER
00035
00036 #ifndef _EXMAT_EXPRESSION_H
00037 #define _EXMAT_EXPRESSION_H
00038
00039 #include "PlatformSpec.h"
00040 #include "TypeTraits.h"
00041 #include "Container/Container.h"
00042 #include "loki/TypeTraits.h"
00043
00044 namespace exmat {
00045
00046
00048
00053 template<class Rep>
00054 struct ExpMat : public Rep {
00055 enum {
00056 IsLinear = Rep::IsLinear,
00057 IsLinearRecursive = Rep::IsLinearRecursive
00058 };
00059
00060 typedef ExpMat<Rep> self_type;
00061 typedef typename Rep::rep_type rep_type;
00062
00063
00064
00066
00067 template<typename T1> EXMAT_INLINE2
00068 ExpMat(T1& t1) : Rep(t1) {}
00069 template<typename T1, typename T2> EXMAT_INLINE2
00070 ExpMat(T1& t1, T2& t2) : Rep(t1, t2) {}
00071 template<typename T1, typename T2, typename T3> EXMAT_INLINE2
00072 ExpMat(T1& t1, T2& t2, T3& t3) : Rep(t1, t2, t3) {}
00073 template<typename T1, typename T2, typename T3, typename T4> EXMAT_INLINE2
00074 ExpMat(T1& t1, T2& t2, T3& t3, T4& t4) : Rep(t1, t2, t3, t4) {}
00075 template<typename T1, typename T2, typename T3, typename T4, typename T5> EXMAT_INLINE2
00076 ExpMat(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) : Rep(t1, t2, t3, t4, t5) {}
00077 #if EXMAT_GNUC || EXMAT_VC2003 || EXMAT_VC2005
00078
00079 EXMAT_INLINE2 ExpMat(const self_type& self) : Rep(self) {}
00080 #endif
00081 #if !EXMAT_VC6 && !EXMAT_VC7
00082 template<typename T1, typename T2> EXMAT_INLINE2
00083 ExpMat(const T1& t1, ScalarCon<T2> t2) : Rep(t1, t2) {}
00084 template<typename T1, typename T2> EXMAT_INLINE2
00085 ExpMat(ScalarCon<T1> t1, const T2& t2) : Rep(t1, t2) {}
00086 #endif // HAVE_PARTIAL_SPECIALIZATION
00087
00088
00090 template<typename T1> EXMAT_INLINE2
00091 ExpMat& operator=(const T1& t1) {
00092 (*static_cast<Rep*>(this)) = t1;
00093 return *this;
00094 }
00095 };
00096
00097
00099
00102 template<class EXP>
00103 struct ExpRow {
00104 typedef typename EXP::value_type value_type;
00105 typedef typename EXP::index_type index_type;
00106
00107 EXMAT_INLINE2 ExpRow(const EXP& exp_, index_type i)
00108 : exp(exp_), row(i) {}
00109 EXMAT_INLINE2 value_type operator[](const index_type i) const {
00110 return exp.getAt(row, i);
00111 }
00112 const EXP& exp;
00113 index_type row;
00114 };
00115
00116
00120 template<class OperandType>
00121 struct OperandTypeChooser {
00122 typedef typename
00123 IF<
00124 HasTagOf<OperandType,ScalarTag>::RET ||
00125 HasTagOf<OperandType,UnaExpTag>::RET ||
00126 HasTagOf<OperandType,BinExpTag>::RET,
00127 const OperandType,
00128 const OperandType&
00129 >::RET RET;
00130 };
00131
00132
00137 template<class OpT1, class OpT2, typename VT>
00138 struct BinViewValueTypeChooser {
00139 enum {
00140 CanLRef = !(
00141 HasTagOf<OpT1,ScalarTag>::RET ||
00142 HasTagOf<OpT1,UnaExpTag>::RET ||
00143 HasTagOf<OpT1,BinExpTag>::RET),
00144 CanRRef = !(
00145 HasTagOf<OpT2,ScalarTag>::RET ||
00146 HasTagOf<OpT2,UnaExpTag>::RET ||
00147 HasTagOf<OpT2,BinExpTag>::RET)
00148 };
00149 typedef typename
00150 IF<
00151
00152 CanLRef && CanRRef,
00153 VT&,
00154 VT
00155 >::RET RET;
00156 };
00157
00158
00162 template<typename T, int ROWS, int COLS, class Left, class Right>
00163 struct GetBinExpTmpType {
00164 typedef Mat<DenseMatCon<T,ROWS,COLS>, EmptyErrorChecker> RET;
00165 };
00166
00167
00169
00172 template<class Rep>
00173 struct UnaExp : public UnaExpTag {
00174 typedef UnaExp<Rep> self_type;
00175
00176 typedef NullTag row_type;
00177 typedef NullTag const_row_type;
00178 typedef typename Rep::col_type col_type;
00179 typedef typename Rep::value_type value_type;
00180 typedef NullTag iterator;
00181 typedef NullTag const_iterator;
00182
00183 typedef value_type reference;
00184 typedef const value_type const_reference;
00185 typedef typename Rep::index_type index_type;
00186 typedef typename Rep::param_type param_type;
00187 typedef typename Rep::const_param_type const_param_type;
00188
00189 typedef typename OperandTypeChooser<Rep>::RET OpType;
00190
00191 EXMAT_INLINE2 UnaExp(const self_type& self) : rep(self.rep) {}
00192 EXMAT_INLINE2 UnaExp(const Rep& r) : rep(r) {}
00193
00194
00195 OpType rep;
00196 };
00197
00198
00200
00203 template<class Left, class Right>
00204 struct BinExp : public BinExpTag {
00205 typedef BinExp<Left, Right> self_type;
00206 typedef NullTag rep_type;
00207
00208 typedef NullTag row_type;
00209 typedef NullTag const_row_type;
00210 typedef typename Left::col_type col_type;
00211 typedef HEleType(typename Left::value_type, typename Right::value_type) value_type;
00212 typedef NullTag iterator;
00213 typedef NullTag const_iterator;
00214
00215 typedef value_type reference;
00216 typedef const value_type const_reference;
00217
00218 typedef typename Left::index_type index_type;
00219 typedef typename Loki::TypeTraits<value_type>::ParameterType param_type;
00220 typedef typename Loki::TypeTraits<const value_type>::ParameterType const_param_type;
00221
00222 typedef Left left_type;
00223 typedef Right right_type;
00224
00225 EXMAT_INLINE2 BinExp(const self_type& self)
00226 : leftOp(self.leftOp), rightOp(self.rightOp) {}
00227 EXMAT_INLINE2 BinExp(const Left& l, const Right& r)
00228 : leftOp(l), rightOp(r) {}
00229
00230 typedef typename OperandTypeChooser<Left>::RET lOpType;
00231 typedef typename OperandTypeChooser<Right>::RET rOpType;
00232
00233
00234 lOpType leftOp;
00235 rOpType rightOp;
00236 };
00237
00238
00240
00243 template<class Left, class Right>
00244 struct LinearBinExpSize {
00245 enum {
00246 ROWS =
00247 (int(Left::ROWS) == 0 && int(Right::ROWS) == 0) ?
00248 0 : (
00249 int(Left::ROWS) == 0 ? int(Right::ROWS) :
00250 int(Left::ROWS)
00251 ),
00252 COLS =
00253 (int(Left::COLS) == 0 && int(Right::COLS) == 0) ?
00254 0 : (
00255 int(Left::COLS) == 0 ? int(Right::COLS) :
00256 int(Left::COLS)
00257 )
00258 };
00259 };
00260
00261
00263
00266 template<class Left, class Right>
00267 struct LinBinExp : public BinExp<Left, Right>
00268 {
00269 typedef BinExp<Left, Right> super_type;
00270 typedef LinBinExp<Left, Right> self_type;
00271 typedef typename super_type::value_type value_type;
00272
00273 enum {
00274 ROWS = LinearBinExpSize<Left, Right>::ROWS,
00275 COLS = LinearBinExpSize<Left, Right>::COLS,
00276 IsLinear = true,
00277 IsLinearRecursive = IsLinear && Left::IsLinearRecursive && Right::IsLinearRecursive
00278 };
00279
00281 using super_type::leftOp;
00282 using super_type::rightOp;
00283
00285 typedef typename GetBinExpTmpType<value_type,ROWS,COLS,Left,Right>::RET temp_type;
00286
00288 enum {
00290 TNOP = (ROWS != 0 && COLS != 0) && (Left::TNOP >= 0 && Left::TNOP >= 0) ?
00291 Left::TNOP + Right::TNOP + ROWS*COLS : -1,
00293 ENOP = (ROWS != 0 && COLS != 0) && (Left::TNOP >= 0 && Left::TNOP >= 0) ?
00294 Left::ENOP + Right::ENOP + 1 : -1,
00295 EXPLevel = Left::EXPLevel + Right::EXPLevel + 2
00296 };
00297
00298 EXMAT_INLINE2 LinBinExp(const self_type& self)
00299 : super_type(self.leftOp, self.rightOp) {}
00300
00301 EXMAT_INLINE2 LinBinExp(const Left& l, const Right& r)
00302 : super_type(l, r)
00303 {
00304
00305 #if EXMAT_STATIC_CHECK
00306
00307 StaticAssert1(Left::ROWS == Right::ROWS, RowNotMatch);
00308 StaticAssert1(Left::COLS == Right::COLS, ColNotMatch);
00309 #endif // EXMAT_STATIC_CHECK
00310
00311
00312 if(!EXMAT_STATIC_CHECK || ROWS == 0 || COLS == 0) {
00313
00314 if(!( leftOp.rows() == 0 || rightOp.rows() == 0 ||
00315 leftOp.cols() == 0 || rightOp.cols() == 0))
00316 DefaultErrorChecker::AssertCompat(leftOp.rows() == rightOp.rows() && leftOp.cols() == rightOp.cols());
00317 }
00318 }
00319
00320 EXMAT_INLINE2 size_t size() const {
00321 return rows() * cols();
00322 }
00323 EXMAT_INLINE2 size_t rows() const {
00324 return ROWS != 0 ? ROWS : (
00325 leftOp.rows() > rightOp.rows() ?
00326 leftOp.rows() : rightOp.rows());
00327 }
00328 EXMAT_INLINE2 size_t cols() const {
00329 return COLS != 0 ? COLS : (
00330 leftOp.cols() > rightOp.cols() ?
00331 leftOp.cols() : rightOp.cols());
00332 }
00333 };
00334
00335
00337
00340 template<class Left, class Right>
00341 struct MulBinExpSize {
00342 enum {
00343 ROWS = Left::ROWS,
00344 COLS = Right::COLS,
00345 MulDotSize =
00346 (int(Left::COLS) == 0 && int(Right::ROWS) == 0) ?
00347 0 : (
00348 int(Left::COLS) == 0 ? int(Right::ROWS) :
00349 int(Left::COLS)
00350 )
00351 };
00352 };
00353
00354
00356
00359 template<class Left, class Right>
00360 struct MulBinExp : public BinExp<Left, Right>
00361 {
00362 typedef BinExp<Left, Right> super_type;
00363 typedef MulBinExp<Left, Right> self_type;
00365 typedef self_type rep_type;
00366 typedef typename super_type::value_type value_type;
00367
00368 enum {
00369 ROWS = MulBinExpSize<Left, Right>::ROWS,
00370 COLS = MulBinExpSize<Left, Right>::COLS,
00371 MulDotSize = MulBinExpSize<Left, Right>::MulDotSize,
00372 IsLinear = false,
00373 IsLinearRecursive = IsLinear
00374 };
00375
00377 using super_type::leftOp;
00378 using super_type::rightOp;
00379
00381 typedef typename GetBinExpTmpType<value_type,ROWS,COLS,Left,Right>::RET temp_type;
00382
00384 enum {
00386 TNOP = (ROWS != 0 && COLS != 0) && (Left::TNOP >= 0 && Left::TNOP >= 0) ?
00387 Left::TNOP + Right::TNOP + (ROWS*COLS)*(2*MulDotSize-1) : -1,
00389 ENOP = (ROWS != 0 && COLS != 0) && (Left::ENOP >= 0 && Left::ENOP >= 0) ?
00390 (Left::ENOP + Right::ENOP + 2)*MulDotSize-1 : -1,
00391 EXPLevel = Left::EXPLevel + Right::EXPLevel + 2
00392 };
00393
00394 EXMAT_INLINE2 MulBinExp(const self_type& self)
00395 : super_type(self) {}
00396 EXMAT_INLINE2 MulBinExp(const Left& l, const Right& r)
00397 : super_type(l, r)
00398 {
00399
00400
00401
00402 }
00403
00404 EXMAT_INLINE2 size_t size() const { return rows() * cols(); }
00405 EXMAT_INLINE2 size_t rows() const { return leftOp.rows(); }
00406 EXMAT_INLINE2 size_t cols() const { return rightOp.cols(); }
00407 };
00408
00409
00411
00416 template<class Left, class Right, class SpecTag=NullTag>
00417 class AddExp :
00418 public LinBinExp<Left, Right>,
00419 public AddExpTag
00420 {
00421 typedef LinBinExp<Left, Right> super_type;
00422 typedef AddExp<Left, Right, SpecTag> self_type;
00423 public:
00424 typedef self_type rep_type;
00425 typedef const ExpRow<self_type> const_row_type;
00426 typedef typename super_type::value_type value_type;
00427 typedef typename super_type::index_type index_type;
00428 typedef AddExpTag exp_tag;
00429
00431 using super_type::leftOp;
00432 using super_type::rightOp;
00433
00434 EXMAT_INLINE2 AddExp(const self_type& self)
00435 : super_type(self) {}
00436 EXMAT_INLINE2 AddExp(const Left& l, const Right& r)
00437 : super_type(l, r) {}
00438
00439
00440
00441 EXMAT_INLINE2 const_row_type operator[] (const index_type i) const {
00442 return const_row_type(*this, i);
00443 }
00444 EXMAT_INLINE2 value_type getAt(const index_type i) const {
00445 return (value_type)(leftOp.getAt(i)) + (value_type)(rightOp.getAt(i));
00446 }
00447 EXMAT_INLINE2 value_type getAt(const index_type i, const index_type j) const {
00448 return (value_type)(leftOp.getAt(i,j)) + (value_type)(rightOp.getAt(i,j));
00449 }
00450 };
00451
00453
00456 template<class Left, class Right, class SpecTag=NullTag>
00457 class SubExp :
00458 public LinBinExp<Left, Right>,
00459 public SubExpTag
00460 {
00461 typedef LinBinExp<Left, Right> super_type;
00462 typedef SubExp<Left, Right, SpecTag> self_type;
00463 public:
00464 typedef self_type rep_type;
00465 typedef const ExpRow<self_type> const_row_type;
00466 typedef typename super_type::value_type value_type;
00467 typedef typename super_type::index_type index_type;
00468 typedef SubExpTag exp_tag;
00469
00471 using super_type::leftOp;
00472 using super_type::rightOp;
00473
00474 EXMAT_INLINE2 SubExp(const self_type& self)
00475 : super_type(self) {}
00476 EXMAT_INLINE2 SubExp(const Left& l, const Right& r)
00477 : super_type(l, r) {}
00478
00479
00480
00481 EXMAT_INLINE2 const_row_type operator[] (const index_type i) const {
00482 return const_row_type(*this, i);
00483 }
00484 EXMAT_INLINE2 value_type getAt(const index_type i) const {
00485 return (value_type)(leftOp.getAt(i)) - (value_type)(rightOp.getAt(i));
00486 }
00487 EXMAT_INLINE2 value_type getAt(const index_type i, const index_type j) const {
00488 return (value_type)(leftOp.getAt(i,j)) - (value_type)(rightOp.getAt(i,j));
00489 }
00490 };
00491
00493
00496 template<class Left, class Right, class SpecTag=NullTag>
00497 class MulExp :
00498 public MulBinExp<Left, Right>,
00499 public MulExpTag
00500 {
00501 typedef MulBinExp<Left, Right> super_type;
00502 typedef MulExp<Left, Right, SpecTag> self_type;
00503 public:
00504 typedef self_type rep_type;
00505 typedef const ExpRow<self_type> const_row_type;
00506 typedef typename super_type::value_type value_type;
00507 typedef typename super_type::index_type index_type;
00508 typedef MulExpTag exp_tag;
00509
00511 using super_type::leftOp;
00512 using super_type::rightOp;
00513
00514 enum {
00515 TNOP = super_type::TNOP,
00516 ENOP = super_type::ENOP,
00517 MulDotSize = super_type::MulDotSize,
00518 EXPLevel = super_type::EXPLevel
00519 };
00520
00521 EXMAT_INLINE2 MulExp(const self_type& self)
00522 : super_type(self) {}
00523 EXMAT_INLINE2 MulExp(const Left& l, const Right& r)
00524 : super_type(l, r)
00525 {
00526
00527 #if EXMAT_STATIC_CHECK
00528
00529 StaticAssert(Left::ROWS == Right::COLS, LeftRowNotMatchRightCol);
00530 StaticAssert(Left::COLS == Right::ROWS, LeftColNotMatchRightRow);
00531 #endif // EXMAT_STATIC_CHECK
00532
00533 if(!EXMAT_STATIC_CHECK || Left::COLS == 0 || Right::COLS == 0) {
00534
00535 if(!( leftOp.rows() == 0 || rightOp.rows() == 0 ||
00536 leftOp.cols() == 0 || rightOp.cols() == 0))
00537 DefaultErrorChecker::AssertCompat(leftOp.cols() == rightOp.rows());
00538 }
00539 }
00540
00541
00542
00543 EXMAT_INLINE2 const_row_type operator[] (const index_type i) const {
00544 return const_row_type(*this, i);
00545 }
00546
00547 protected:
00548
00549 #if HAVE_PARTIAL_SPECIALIZATION
00550
00551 template<unsigned int I, class A, class B, typename value_type, typename index_type>
00552 struct MulDot_FullUnRoll {
00553 enum { go = (I-1) != 0 };
00554 static EXMAT_INLINE2 value_type
00555 exec(const A& a, const B& b, const index_type& ar, const index_type& bc) {
00556 return a.getAt(ar, I-1) * b.getAt(I-1, bc) +
00557 MulDot_FullUnRoll< go?(I-1):0, A, B, value_type, index_type >::exec(a, b, ar, bc);
00558 }
00559 };
00560
00561 template<class A, class B, typename value_type, typename index_type>
00562 struct MulDot_FullUnRoll<0, A, B, value_type, index_type> {
00563 static EXMAT_INLINE2 value_type
00564 exec(const A& a, const B& b, const index_type& ar, const index_type& bc) {
00565 return value_type(0);
00566 }
00567 };
00568 #else // Workaround for MSVC6
00569 template<unsigned int SIZE, class A, class B, typename value_type, typename index_type>
00570 struct MulDot_FullUnRoll {
00571 template<unsigned int I> struct inner {
00572 enum { go = (I-1) != 0 };
00573 static EXMAT_INLINE2 value_type
00574 exec(const A& a, const B& b, const index_type& ar, const index_type& bc) {
00575 return a.getAt(ar, I-1) * b.getAt(I-1, bc) +
00576 inner< go?(I-1):0 >::exec(a, b, ar, bc);
00577 }
00578 };
00579 template<> struct inner<0> {
00580 static EXMAT_INLINE2 value_type
00581 exec(const A& a, const B& b, const index_type& ar, const index_type& bc) {
00582 return value_type(0);
00583 }
00584 };
00585 static EXMAT_INLINE2 value_type
00586 exec(const A& a, const B& b, const index_type& ar, const index_type& bc) {
00587 return inner<SIZE>::exec(a, b, ar, bc);
00588 }
00589 };
00590 #endif // HAVE_PARTIAL_SPECIALIZATION
00591
00592
00593
00594 EXMAT_INLINE2 value_type
00595 MulDot(const index_type& i, const index_type& j, Int2Type<true>) const {
00596 return MulDot_FullUnRoll<MulDotSize, Left, Right, value_type, index_type>::
00597 exec(leftOp, rightOp, i, j);
00598 }
00599 EXMAT_INLINE2 value_type
00600 MulDot(const index_type& i, const index_type& j, Int2Type<false>) const {
00601 value_type sum = value_type(0);
00602 for(index_type k=leftOp.cols(); k--; ) {
00603 sum += (value_type)(leftOp.getAt(i,k)) * (value_type)(rightOp.getAt(k,j));
00604 }
00605 return sum;
00606 }
00607
00608 public:
00609 EXMAT_INLINE2 value_type getAt(const index_type i) const {
00611 return getAt(i/this->cols(), i%this->cols());
00612 }
00613 EXMAT_INLINE2 value_type getAt(const index_type i, const index_type j) const {
00614 #if ENABLE_UNROLLING
00615 enum {
00616 CanUnroll = (MulDotSize > 0) && (ENOP < MulDotSize * MAX_MULDOTUROLL_ENOP)
00617 };
00618 return MulDot(i, j, Int2Type<CanUnroll>());
00619 #else
00620 return MulDot(i, j, Int2Type<false>());
00621 #endif
00622 }
00623 };
00624
00626
00629 template<class Left, class Right, class SpecTag=NullTag>
00630 class ScalarMulExp :
00631 public LinBinExp<Left, Right>,
00632 public ScalarMulExpTag
00633 {
00634 typedef LinBinExp<Left, Right> super_type;
00635 typedef ScalarMulExp<Left, Right, SpecTag> self_type;
00636 public:
00637 typedef self_type rep_type;
00638 typedef const ExpRow<self_type> const_row_type;
00639 typedef typename super_type::value_type value_type;
00640 typedef typename super_type::index_type index_type;
00641 typedef ScalarMulExpTag exp_tag;
00642
00644 using super_type::leftOp;
00645 using super_type::rightOp;
00646
00647 EXMAT_INLINE2 ScalarMulExp(const self_type& self)
00648 : super_type(self) {}
00649 EXMAT_INLINE2 ScalarMulExp(const Left& l, const Right& r)
00650 : super_type(l, r) {}
00651
00652
00653
00654 EXMAT_INLINE2 const_row_type operator[] (const index_type i) const {
00655 return const_row_type(*this, i);
00656 }
00657 EXMAT_INLINE2 value_type getAt(const index_type i) const {
00658 return (value_type)(leftOp.getAt(i)) * (value_type)(rightOp.getAt(i));
00659 }
00660 EXMAT_INLINE2 value_type getAt(const index_type i, const index_type j) const {
00661 return (value_type)(leftOp.getAt(i,j)) * (value_type)(rightOp.getAt(i,j));
00662 }
00663 };
00664
00666
00669 template<class Left, class Right, class SpecTag=NullTag>
00670 class ScalarDivExp :
00671 public LinBinExp<Left, Right>,
00672 public ScalarDivExpTag
00673 {
00674 typedef LinBinExp<Left, Right> super_type;
00675 typedef ScalarDivExp<Left, Right, SpecTag> self_type;
00676 public:
00677 typedef self_type rep_type;
00678 typedef const ExpRow<self_type> const_row_type;
00679 typedef typename super_type::value_type value_type;
00680 typedef typename super_type::index_type index_type;
00681 typedef ScalarDivExpTag exp_tag;
00682
00684 using super_type::leftOp;
00685 using super_type::rightOp;
00686
00687 EXMAT_INLINE2 ScalarDivExp(const self_type& self)
00688 : super_type(self) {}
00689 EXMAT_INLINE2 ScalarDivExp(const Left& l, const Right& r)
00690 : super_type(l, r) {}
00691
00692
00693
00694 EXMAT_INLINE2 const_row_type operator[] (const index_type i) const {
00695 return const_row_type(*this, i);
00696 }
00697 EXMAT_INLINE2 value_type getAt(const index_type i) const {
00698 return (value_type)(leftOp.getAt(i)) / (value_type)(rightOp.getAt(i));
00699 }
00700 EXMAT_INLINE2 value_type getAt(const index_type i, const index_type j) const {
00701 return (value_type)(leftOp.getAt(i,j)) / (value_type)(rightOp.getAt(i,j));
00702 }
00703 };
00704
00705
00706 }
00707
00708 #if _MSC_VER
00709 # pragma warning( pop )
00710 #endif // EXMAT_VC
00711
00712 #endif // _EXMAT_EXPRESSION_H