Expression.h

Go to the documentation of this file.
00001 /*
00002  * Expression Template Matrix Library
00003  *
00004  * Copyright (C) 2004 - 2006 Ricky Lung <mtlung@users.sourceforge.net>
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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     // Should use Rep::super_type:
00063     //typedef typename Rep::super_type  super_type;
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     // VC7.1, VC8 and GCC need this to allow force inlining
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         // Only both left and right can use reference then the final type can be reference
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     // -> row_type should be override by child expression
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     // -> Expression should return a new value, so reference will be treated as value
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     // Constant reference/value to the operand
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     // -> row_type should be override by child expression
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     // -> Expression should return a new value, so reference will be treated as value
00215     typedef value_type                      reference;
00216     typedef const value_type                const_reference;
00217     // --> Assume both operands' index_type are the same
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     // Constant reference/value to the operands
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         // Do Incompatibility check here
00305 #if EXMAT_STATIC_CHECK
00306         // Static check
00307         StaticAssert1(Left::ROWS == Right::ROWS, RowNotMatch);
00308         StaticAssert1(Left::COLS == Right::COLS, ColNotMatch);
00309 #endif  // EXMAT_STATIC_CHECK
00310 
00311         // Dynamic check
00312         if(!EXMAT_STATIC_CHECK || ROWS == 0 || COLS == 0) {
00313             // Check for scalar, which have zero dimension
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         // Do compatability check here
00400         // The check have been delaied to the child class, to allow customs
00401         // MulExp (eg. MulExp in G3D) without throwing exception. 
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;  // Tag indicating the type of expression
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     // Index function
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;  // Tag indicating the type of expression
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     // Index function
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         // Do compatability check here
00527 #if EXMAT_STATIC_CHECK
00528         // Static check
00529         StaticAssert(Left::ROWS == Right::COLS, LeftRowNotMatchRightCol);
00530         StaticAssert(Left::COLS == Right::ROWS, LeftColNotMatchRightRow);
00531 #endif  // EXMAT_STATIC_CHECK
00532         // Dynamic check
00533         if(!EXMAT_STATIC_CHECK || Left::COLS == 0 || Right::COLS == 0) {
00534             // Check for scalar, which have zero dimension
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     // Index function
00543     EXMAT_INLINE2 const_row_type operator[] (const index_type i) const {
00544         return const_row_type(*this, i);
00545     }
00546 
00547 protected:
00548     // Unrolling for inner_product
00549 #if HAVE_PARTIAL_SPECIALIZATION
00550     // Loop full unrolling template for the dot product
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         //    A's row               B's col
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     // Partial specialization to end the recursion
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     //  Overloaded function to choose the appropriate unroller
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;    // Tag indicating the type of expression
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     // Index function
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;    // Tag indicating the type of expression
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     // Index function
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 }   // namespace exmat
00707 
00708 #if _MSC_VER
00709 #   pragma warning( pop )
00710 #endif  // EXMAT_VC
00711 
00712 #endif  // _EXMAT_EXPRESSION_H

Generated on Sat May 6 23:11:57 2006 for Exmat by  doxygen 1.4.6-NO