ExpTmp.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 
00031 /*
00032  *  Todo:
00033  *  There may be special needs to do conversion between Mat<DenseMatCon> and Mat<XXXVecCon>
00034  *  So that less temporaries will be needed
00035  */
00036 
00037 #ifdef _MSC_VER
00038 #   pragma once
00039 #   pragma warning( push )
00040 #   pragma warning( disable : 4100 4786 )
00041 #endif  // _MSC_VER
00042 
00043 #ifndef _EXMAT_EXPTMP_H
00044 #define _EXMAT_EXPTMP_H
00045 
00046 #include "loki/HierarchyGenerators.h"
00047 #include "Expression.h"
00048 #include "ExpTree.h"
00049 #include "Tag2Exp.h"
00050 
00051 #include <iostream>
00052 #include <vector>
00053 #include <deque>
00054 
00055 #include "SIMD/SIMDAlignment.h"
00056 
00057 
00058 namespace exmat {
00059 
00061 
00065     template<class Con, unsigned int IsFree_>
00066     struct TmpListEntry : public Con {
00067         typedef Con container_type;
00068         enum {
00069             IsFree = IsFree_
00070         };
00071     };
00072 
00074 
00079     template<class TL, class TC, size_t Index_, size_t TarIndex_>
00080     struct GetTmp {
00081     private:
00082         template<unsigned int Index>
00083         struct DefaultTmp {
00084             typedef typename ::Loki::TL::TypeAt<TTYPENAME TL::tmp_list, Index>::Result return_type;
00085             template<class TmpList> static EXMAT_INLINE2
00086             return_type&
00087             GetTmpAt(::Loki::Tuple<TmpList>& obj, TC& tCon) {
00088                 return ::Loki::Field<Index>(obj);
00089             }
00090         };
00091         template<unsigned int Index>
00092         struct TarConTmp {
00093             typedef TC return_type;
00094             template<class TmpList> static EXMAT_INLINE2
00095             return_type&
00096             GetTmpAt(::Loki::Tuple<TmpList>& obj, TC& tCon) {
00097                 return tCon;
00098             }
00099         };
00100     public:
00101         typedef typename IF<
00102             (Index_ == TarIndex_),
00103             TarConTmp<Index_>,
00104             DefaultTmp<Index_>
00105         >::RET RET;
00106     };
00107 
00109 
00112     template<class TmpList, int Index>
00113     class ReleaseTmpAt {
00114         struct NullT{
00115             typedef ::Loki::NullType container_type;
00116         };
00117         typedef typename ::Loki::TL::TypeAtNonStrict<TmpList, (unsigned int)Index, NullT>::Result TA;
00118         typedef typename TA::container_type container_type;
00119         typedef TmpListEntry<container_type, true> FreeT;
00120     public:
00121         typedef typename ::Loki::TL::ReplaceAt<TmpList, Index, FreeT>::Result RET;
00122     };
00123 
00125 
00129     template<class DyTmpCon>
00130     struct DynamicTmpList {
00131         EXMAT_INLINE1 DynamicTmpList() {
00132             // Reserve some space, to prevent excessive memory allocation
00133             ConList.reserve(10);
00134             AvlList.reserve(10);
00135             FreeList.reserve(10);
00136         }
00138 
00139         EXMAT_INLINE1 DyTmpCon& CastToCon() {
00140             size_t i;
00141             if(AccessQue.size() >= 3) {
00142                 i = AccessQue.front();
00143                 AccessQue.pop_front();
00144                 AccessQue.push_back(i);
00145             }
00146             i = AccessQue.front();
00147             AccessQue.pop_front();
00148             FreeList.push_back(i);
00149             //std::cout << "free\n";
00150             //print();
00151             return ConList[i];
00152         }
00153         EXMAT_INLINE2 operator DyTmpCon&() {
00154             return CastToCon();
00155         }
00156         EXMAT_INLINE2 operator const DyTmpCon&() {
00157             return CastToCon();
00158         }
00160 
00161         template<class Exp> EXMAT_INLINE2
00162         DyTmpCon& AssignNoAna(const Exp& A) {
00163             return (this->assign(A));
00164         }
00165 
00166         template<class Exp> EXMAT_INLINE1
00167         DynamicTmpList<DyTmpCon>& operator=(const Exp& A) {
00168             this->assign(A);
00169             return *this;
00170         }
00171 
00172         // Internal function for assignment
00173         template<class Exp> EXMAT_INLINE2
00174         DyTmpCon& assign(const Exp& A) {
00175             int idx = -1;
00176             size_t i;
00177             // Find the first available tmp that match the dimension of A
00178             for(i=0; i<ConList.size(); ++i) {
00179                 if(!AvlList[i] || ConList[i].rows() != A.rows() || ConList[i].cols() != A.cols())
00180                     continue;
00181                 ConList[i] = A;
00182                 //cout << "Use dyn idx = " << i << " with value:\n" << ConList[i] << endl;
00183                 AvlList[i] = false;
00184                 AccessQue.push_back(i);
00185                 idx = int(i);
00186                 break;
00187             }
00188             // If no tmp available, then create one
00189             if(idx == -1) {
00190                 AccessQue.push_back(ConList.size());
00191                 idx = ConList.size();
00192                 ConList.push_back(DyTmpCon(A));
00193                 AvlList.push_back(false);
00194                 //cout << "Creating dyn idx = " << idx << " with value:\n" << ConList[idx] << endl;
00195             }
00196 
00197             // Free all pending free list
00198             for(i=0; i<FreeList.size(); ++i)
00199                 AvlList[FreeList[i]] = true;
00200             FreeList.clear();
00201 
00202             return ConList[idx];
00203         }
00204 
00205         void print() {
00206             int i;
00207             for(i=0; i<AvlList.size(); ++i)
00208                 std::cout << AvlList[i] << ", ";
00209             std::cout << std::endl;
00210             for(i=0; i<AccessQue.size(); ++i)
00211                 std::cout << AccessQue[i] << ", ";
00212             std::cout << std::endl;
00213             for(i=0; i<FreeList.size(); ++i)
00214                 std::cout << FreeList[i] << ", ";
00215             std::cout << std::endl;
00216             std::cout << std::endl;
00217         }
00218         std::vector<DyTmpCon> ConList;  // List of container
00219         std::vector<bool> AvlList;      // Availability list
00220         std::deque<size_t> AccessQue;   // Track the accessing sequence
00221         std::vector<size_t> FreeList;   // Tmps that are pending to free
00222     };
00223 
00224 namespace PNS {
00226 
00231     template<class TList>
00232     struct ReplaceTmp
00233     {
00234     private:
00235         typedef typename TList::Head Head;
00236         typedef typename TList::Tail Tail;
00237 
00238         typedef typename Head::container_type container_type;
00239         enum {
00240             IsStaticRow = (container_type::ROWS > 0),
00241             IsStaticCol = (container_type::COLS > 0),
00242             IsLeftRowVec = (container_type::ROWS == 1),
00243             IsLeftColVec = (container_type::COLS == 1)
00244         };
00245         typedef typename IF<
00246             !IsStaticRow || !IsStaticCol,
00247             DynamicTmpList<container_type>,
00248             container_type
00249         >::RET replacing_type;
00250     public:
00252         typedef Loki::Typelist<replacing_type, typename ReplaceTmp<Tail>::Result> Result;
00253     };
00254 
00256     template <>
00257     struct ReplaceTmp<Loki::NullType> {
00259         typedef Loki::NullType Result;
00260     };
00261 };
00262 
00263 
00265 
00268     template<class TmpList>
00269     struct TmpInstance : public ::Loki::Tuple<TmpList> {
00270         typedef TmpList tmp_list;
00271         EXMAT_INLINE2 TmpInstance() {}
00272     };
00273 
00274 
00275     // Forward declarations
00276     template<class Exp, class TmpList, class TarConType, class ForceUseTmp,
00277         int IsRootNode=false, bool NeedTmp_=false>
00278     struct TmpAnalyserUnaNode;
00279     template<class Exp, class TmpList, class TarConType, class ForceUseTmp,
00280         int IsRootNode=false, bool NeedTmp_=false>
00281     struct TmpAnalyserBinNode;
00282 
00283 
00285 
00289     template<class Exp_, class TmpList, class TarConType, class ForceUseTmp, int IsRootNode, bool NeedTmp_>
00290     struct TmpAnalyserUnaNode {
00291         typedef Exp_ Exp;
00292         enum {
00294             IsCBin = IsDerivedFrom<typename Exp::super_type,BinExpTag>::RET,
00296             IsCUna = IsDerivedFrom<typename Exp::super_type,UnaExpTag>::RET,
00298             IsCLeaf = (!IsCBin && !IsCUna),
00300             CNeedTmp = false,
00302             IsDynamicTmp = (Exp::ROWS == 0) || (Exp::COLS == 0),
00303             IsTarConDynamic = (TarConType::ROWS == 0 || TarConType::COLS == 0)
00304         };
00305 
00306         typedef typename Exp::exp_tag exp_tag;
00308         typedef typename IF<
00309             IsRootNode == int(true),
00310             TarConType,                 // We sure the temp_type of the root node
00311             TTYPENAME Exp::temp_type    // must be the target container type
00312         >::RET temp_type;
00313 
00314         private:
00315         typedef TmpListEntry<temp_type, true> E1;   // Free entry
00316         typedef typename IF<                        // Used entry
00317             IsDynamicTmp,       // Dynamic temp is always available at compile time
00318             TmpListEntry<temp_type, true>,
00319             TmpListEntry<temp_type, false>
00320         >::RET E2;
00321         public:
00322 
00324         typedef typename IF<
00325             IsCLeaf,
00326             LeafeNode<typename Exp::super_type>,
00327         typename IF<
00328             IsCUna,
00329             TmpAnalyserUnaNode<typename Exp::super_type, TmpList, TarConType, ForceUseTmp>,
00330             TmpAnalyserBinNode<typename Exp::super_type, TmpList, TarConType, ForceUseTmp>
00331         >::RET>::RET child;
00332 
00333         private:
00334         typedef typename IF<
00335             IsCLeaf,
00336             TmpList,
00337         typename IF<
00338             IsCUna,
00339             TTYPENAME child::tmp_list,
00340             TTYPENAME child::tmp_list
00341         >::RET>::RET cTL;
00342         public:
00343 
00347         typedef typename IF<
00348             NeedTmp_,
00349             temp_type,
00350             Mat<
00351 #if (HAVE_TT_PARAMETER)
00352                 TTYPENAME RefillUnaExp<TTYPENAME Exp::rep_type,
00353 #else
00354                 TTYPENAME Tag2UnaExp<exp_tag,
00355 #endif
00356                     TTYPENAME child::node_exp::rep_type,
00357                     TTYPENAME Exp::extra_param_type
00358                 >::RET,
00359                 EmptyErrorChecker
00360             >
00361         >::RET node_exp;
00362 
00363         private:
00364         // Request one temp for itself
00365         enum {
00367             PreTmpIndex = ::Loki::TL::IndexOf<cTL, E1>::value
00368         };
00369         typedef typename IF<
00370             PreTmpIndex == -1,      // Not enough temp in the list
00371             // Append new temp to list
00372             typename ::Loki::TL::Append<cTL, E2>::Result,
00373             // Mark the tmp to be unavailable
00374             typename ::Loki::TL::ReplaceAt<cTL, PreTmpIndex, E2>::Result
00375         >::RET PreRed_list;
00376         public:
00377 
00378         enum {
00379             CTmpIndex = child::TmpIndex,
00380             TmpIndex =
00381                 IsRootNode && IsTarConDynamic ?
00382                 0 :
00383                 !NeedTmp_ && !IsRootNode?
00384                 -1 : (
00385                     // New temp been added to Tlist?
00386                     (PreTmpIndex == -1) ?
00387                     // If yes then the index is the last
00388                     ::Loki::TL::Length<PreRed_list>::value-1 :
00389                     // Otherwise use PreTmpIndex
00390                     PreTmpIndex
00391                 )
00392         };
00393 
00394         private:
00395         // Release the child's temp
00396         typedef typename ReleaseTmpAt<PreRed_list, CTmpIndex>::RET CRed_list;
00397         public:
00398 
00400         typedef typename IF<
00401             NeedTmp_, CRed_list, cTL
00402         >::RET tmp_list;
00403 
00404 
00406         template<class Tag> static void print(Tag) {
00407             child::print(TTYPENAME child::exp_tag());
00408             std::cout << Tag::name() << ", to index: " << TmpIndex << std::endl;
00409         }
00410 
00412 
00416 
00417         template<class TInst, class TargetCon, class TarConIndex> EXMAT_INLINE2
00418         static const node_exp& getNodeObj(const Exp& exp, TInst& tmpInst,
00419             TargetCon& tCon, Int2Type<0+2*1>, TarConIndex)
00420         {
00421             enum {
00422                 TIdx = TarConIndex::RET
00423             };
00424             typedef Mat<
00425 #if (HAVE_TT_PARAMETER)
00426                 TTYPENAME RefillUnaExp<TTYPENAME Exp::rep_type,
00427 #else
00428                 TTYPENAME Tag2UnaExp<exp_tag,
00429 #endif
00430                     TTYPENAME child::node_exp::rep_type,
00431                     TTYPENAME Exp::extra_param_type
00432                 >::RET,
00433                 EmptyErrorChecker
00434             > expT;
00435             typedef typename GetTmp<TInst, TargetCon, TmpIndex, TIdx>::RET GT;
00436             typedef typename GT::return_type RT;
00437             // Use node_exp::rep_type to prevent the problem of different error checker,
00438             // at this point the cast operator of DynamicTmpList will be called
00439             return *((const node_exp*)(&
00440                 GT::GetTmpAt(tmpInst, tCon).AssignNoAna(expT(
00441                     exp,
00442                     child::getNodeObj(
00443                         *((const typename child::Exp*)(&exp.rep)),
00444                         tmpInst, tCon,
00445                     Int2Type<IsCLeaf+2*CNeedTmp>(), TarConIndex())
00446                 ))
00447             ));
00448         }
00449         // Create an unary node
00450         template<class TInst, class TargetCon, class TarConIndex> EXMAT_INLINE2
00451         static const node_exp getNodeObj(const Exp& exp, TInst& tmpInst,
00452             TargetCon& tCon, Int2Type<0+2*0>, TarConIndex)
00453         {
00454             return node_exp(
00455                 exp,
00456                 child::getNodeObj(
00457                     *((const typename child::Exp*)(&exp.rep)),
00458                     tmpInst, tCon,
00459                     Int2Type<IsCLeaf+2*CNeedTmp>(), TarConIndex())
00460             );
00461         }
00463 
00465         template<class TInst, class TargetCon, class TarConIndex> EXMAT_INLINE2
00466         static void ass_root(const Exp& exp, TInst& tmpInst,
00467             TargetCon& tCon, TarConIndex)
00468         {
00469             tCon.AssignNoAna(
00470                 getNodeObj(exp, tmpInst, tCon, Int2Type<0+2*0>(), TarConIndex())
00471             );
00472         }
00473     };
00474 
00475 
00477 
00481     template<class Exp_, class TmpList, class TarConType, class ForceUseTmp, int IsRootNode, bool NeedTmp_>
00482     struct TmpAnalyserBinNode {
00483         typedef Exp_ Exp;
00484         enum {
00486             Forced = ForceUseTmp::RET,
00488             IsLinearExp = Exp::IsLinear,
00489             IsLLinear = Exp::left_type::IsLinear,
00490             IsRLinear = Exp::right_type::IsLinear,
00491             IsSIMDExp = IsDerivedFrom<Exp,SIMDTag>::RET,
00492             IsLCon = (Exp::left_type::EXPLevel == 0),
00493             IsRCon = (Exp::right_type::EXPLevel == 0),
00495             IsLBin = IsDerivedFrom<typename Exp::left_type,BinExpTag>::RET,
00497             IsRBin = IsDerivedFrom<typename Exp::right_type,BinExpTag>::RET,
00499             IsLUna = IsDerivedFrom<typename Exp::left_type,UnaExpTag>::RET,
00501             IsRUna = IsDerivedFrom<typename Exp::right_type,UnaExpTag>::RET,
00502             IsLSIMD = IsDerivedFrom<typename Exp::left_type,SIMDTag>::RET,
00503             IsRSIMD = IsDerivedFrom<typename Exp::right_type,SIMDTag>::RET,
00505             LNeedTmp =
00506                 Forced ? IsLBin : (
00507                     (!IsLinearExp && Exp::COLS!=1) ||
00508                     (IsSIMDExp && !IsLinearExp) || (IsLSIMD && !IsLLinear)
00509                 ) && (!IsLCon), //<- Container always need no temp
00511             RNeedTmp =
00512                 Forced ? IsRBin : (
00513                     (!IsLinearExp) ||
00514                     (IsSIMDExp && !IsLinearExp) || (IsRSIMD && !IsRLinear)
00515                 ) && (!IsRCon), //<- Container always need no temp
00517             IsLLeaf =
00518                 Forced ? IsLCon :
00519                 (Exp::left_type::IsLinearRecursive && !LNeedTmp) || (!IsLUna && !IsLBin),
00521             IsRLeaf =
00522                 Forced ? IsRCon :
00523                 (Exp::right_type::IsLinearRecursive && !RNeedTmp) || (!IsRUna && !IsRBin),
00525             IsDynamicTmp = (Exp::ROWS == 0) || (Exp::COLS == 0),
00526             IsTarConDynamic = (TarConType::ROWS == 0 || TarConType::COLS == 0)
00527         };
00528 
00529         typedef typename Exp::exp_tag exp_tag;
00531         typedef typename IF<
00532             IsRootNode == int(true),
00533             TarConType,                 // We sure the temp_type of the root node
00534             TTYPENAME Exp::temp_type    // must be the target container type
00535         >::RET temp_type;
00536 
00537         private:
00538         typedef TmpListEntry<temp_type, true> E1;   // Free entry
00539         typedef typename IF<                        // Used entry
00540             IsDynamicTmp,       // Dynamic temp is always available at compile time
00541             TmpListEntry<temp_type, true>,
00542             TmpListEntry<temp_type, false>
00543         >::RET E2;
00544         public:
00545 
00547         typedef typename IF<
00548             IsLLeaf,
00549             LeafeNode<typename Exp::left_type>,
00550         typename IF<
00551             IsLUna,
00552             TmpAnalyserUnaNode<typename Exp::left_type, TmpList, TarConType, ForceUseTmp, false, LNeedTmp>,
00553             TmpAnalyserBinNode<typename Exp::left_type, TmpList, TarConType, ForceUseTmp, false, LNeedTmp>
00554         >::RET>::RET left_child;
00555 
00556         private:
00557         typedef typename IF<
00558             IsLLeaf,
00559             TmpList,
00560         typename IF<
00561             IsLUna,
00562             TTYPENAME left_child::tmp_list,
00563             TTYPENAME left_child::tmp_list
00564         >::RET>::RET lTL;
00565         public:
00566 
00568         typedef typename IF<
00569             IsRLeaf,
00570             LeafeNode<typename Exp::right_type>,
00571         typename IF<
00572             IsRUna,
00573             TmpAnalyserUnaNode<typename Exp::right_type, lTL, TarConType, ForceUseTmp, false, RNeedTmp>,
00574             TmpAnalyserBinNode<typename Exp::right_type, lTL, TarConType, ForceUseTmp, false, RNeedTmp>
00575         >::RET>::RET right_child;
00576 
00577         private:
00578         typedef typename IF<
00579             IsRLeaf,
00580             lTL,
00581         typename IF<
00582             IsRUna,
00583             TTYPENAME right_child::tmp_list,
00584             TTYPENAME right_child::tmp_list
00585         >::RET>::RET rTL;
00586         public:
00587 
00591         typedef typename IF<
00592             NeedTmp_,
00593             temp_type,
00594             Mat<
00595 #if (HAVE_TT_PARAMETER)
00596             TTYPENAME RefillBinExp<TTYPENAME Exp::rep_type,
00597 #else
00598             TTYPENAME Tag2BinExp<exp_tag,
00599 #endif
00600                     TTYPENAME left_child::node_exp::rep_type,
00601                     TTYPENAME right_child::node_exp::rep_type>::RET,
00602                 EmptyErrorChecker
00603             >
00604         >::RET node_exp;
00605 
00606         private:
00607         // Request one temp for itself
00608         enum {
00610             PreTmpIndex = ::Loki::TL::IndexOf<rTL, E1>::value
00611         };
00612         typedef typename IF<
00613             PreTmpIndex == -1,      // Not enough temp in the list
00614             // Append new temp to list
00615             typename ::Loki::TL::Append<rTL, E2>::Result,
00616             // Mark the tmp to be unavailable
00617             typename ::Loki::TL::ReplaceAt<rTL, PreTmpIndex, E2>::Result
00618         >::RET PreRed_list;
00619         public:
00620 
00621         enum {
00622             LTmpIndex = left_child::TmpIndex,
00623             RTmpIndex = right_child::TmpIndex,
00624             TmpIndex =
00625                 IsRootNode && IsTarConDynamic ?
00626                 0 :
00627                 !NeedTmp_ && !IsRootNode ?
00628                 -1 : (
00629                     // New temp been added to Tlist?
00630                     (PreTmpIndex == -1) ?
00631                     // If yes then the index is the last
00632                     ::Loki::TL::Length<PreRed_list>::value-1 :
00633                     // Otherwise use PreTmpIndex
00634                     PreTmpIndex
00635                 )
00636         };
00637 
00638         private:
00639         // Release the left child's temp
00640         typedef typename ReleaseTmpAt<PreRed_list, LTmpIndex>::RET LRed_list;
00641         // Release the right child's temp
00642         typedef typename ReleaseTmpAt<LRed_list, RTmpIndex>::RET RRed_list;
00643         public:
00644 
00646         typedef typename IF<
00647             NeedTmp_, RRed_list, rTL
00648         >::RET tmp_list;
00649 
00650 
00652         template<class Tag> static void print(Tag) {
00653             left_child::print(TTYPENAME left_child::exp_tag());
00654             right_child::print(TTYPENAME right_child::exp_tag());
00655             std::cout << Tag::name() << ", to index: " << TmpIndex << std::endl;
00656             std::cout << "LNeedTmp: " << LNeedTmp << "\n";
00657             std::cout << "RNeedTmp: " << RNeedTmp << "\n";
00658             std::cout << "IsLLeaf: " << IsLLeaf << "\n";
00659             std::cout << "IsRLeaf: " << IsRLeaf << "\n";
00660 //          cout << typeid(Exp).name() << " ";
00661         }
00662 
00664 
00668 
00669         template<class TInst, class TargetCon, class TarConIndex> EXMAT_INLINE2
00670         static const node_exp& getNodeObj(const Exp& exp, TInst& tmpInst,
00671             TargetCon& tCon, Int2Type<0+2*1>, TarConIndex)
00672         {
00673             enum {
00674                 TIdx = TarConIndex::RET
00675             };
00676             typedef Mat<
00677 #if (HAVE_TT_PARAMETER)
00678                 TTYPENAME RefillBinExp<TTYPENAME Exp::rep_type,
00679 #else
00680                 TTYPENAME Tag2BinExp<exp_tag,
00681 #endif
00682                     TTYPENAME left_child::node_exp::rep_type,
00683                     TTYPENAME right_child::node_exp::rep_type>::RET,
00684                 EmptyErrorChecker
00685             > expT;
00686             typedef typename GetTmp<TInst, TargetCon, TmpIndex, TIdx>::RET GT;
00687             // Force the left child node to be evaluated first
00688             const typename left_child::node_exp& ln =
00689                 left_child::getNodeObj(
00690                     // Casting must be used, otherwise temporary will be passed
00691                     // instead of reference. The will happen especially for SIMD exp
00692                     *((const typename left_child::Exp*)(&exp.leftOp)),
00693                     tmpInst, tCon,
00694                     Int2Type<IsLLeaf+2*LNeedTmp>(), TarConIndex());
00695             // The error checker between TargetCon and node_exp may be different.
00696             // The container type may also be the same but presented differently.
00697             // Therefore we cast the pointer explicitly.
00698             return *((const node_exp*)(&
00699                 GT::GetTmpAt(tmpInst, tCon).AssignNoAna(expT(
00700                     ln,
00701                     right_child::getNodeObj(
00702                         *((const typename right_child::Exp*)(&exp.rightOp)),
00703                         tmpInst, tCon,
00704                         Int2Type<IsRLeaf+2*RNeedTmp>(), TarConIndex()
00705                     )
00706                 ))
00707             ));
00708         }
00710         template<class TInst, class TargetCon, class TarConIndex> EXMAT_INLINE2
00711         static const node_exp getNodeObj(const Exp& exp, TInst& tmpInst,
00712             TargetCon& tCon, Int2Type<0+2*0>, TarConIndex)
00713         {
00714             // Force the left child node to be evaluated first
00715             const typename left_child::node_exp& ln =
00716                 left_child::getNodeObj(
00717                     *((const typename left_child::Exp*)(&exp.leftOp)),
00718                     tmpInst, tCon,
00719                     Int2Type<IsLLeaf+2*LNeedTmp>(), TarConIndex());
00720             return node_exp(
00721                 ln,
00722                 right_child::getNodeObj(
00723                     *((const typename right_child::Exp*)(&exp.rightOp)),
00724                     tmpInst, tCon,
00725                     Int2Type<IsRLeaf+2*RNeedTmp>(), TarConIndex()
00726                 )
00727             );
00728         }
00730 
00732         template<class TInst, class TargetCon, class TarConIndex> EXMAT_INLINE2
00733         static void ass_root(const Exp& exp, TInst& tmpInst,
00734             TargetCon& tCon, TarConIndex)
00735         {
00736             tCon.AssignNoAna(
00737                 getNodeObj(exp, tmpInst, tCon, Int2Type<0+2*0>(), TarConIndex())
00738             );
00739         }
00740     };
00741 
00745 
00746     template<class Exp, class Con, class ErrChk1, class ErrChk2, class ForceUseTmp> EXMAT_INLINE2
00747     static void parseExp_inner(Mat<Con, ErrChk1>& mat,
00748         const Mat<Exp, ErrChk2>& exp, Int2Type<1+2*0>, ForceUseTmp) {
00749         typedef Mat<Con, ErrChk1> TarConType;
00750         enum {
00751             // This target index only valid for static target con
00752             TargetIndex = TmpAnalyserUnaNode<Exp, Loki::NullType, TarConType, ForceUseTmp, true>::TmpIndex,
00753             // is the target container dynamic?
00754             IsTarConDynamic =
00755                 (Con::ROWS == 0 || Con::COLS == 0)
00756         };
00757         // Define the unavailable target container
00758         typedef TmpListEntry<Mat<Con, EmptyErrorChecker>, false> UnAvailableTarCon;
00759         // Insert the UnAvailableTarCon into the analyzer,
00760         // so that the target con will always occupied the list at index 0,
00761         // if the target con is dynamic
00762         typedef typename IF<
00763             IsTarConDynamic,
00764             LOKI_TYPELIST_1(UnAvailableTarCon),
00765             Loki::NullType
00766         >::RET tmplist;
00767         // Replace the type in tmp list, simplify static tmp, warp dynamic tmp with DynamicTmpList
00768         typedef typename exmat::PNS::ReplaceTmp<
00769             TTYPENAME TmpAnalyserUnaNode<Exp, tmplist, TarConType, ForceUseTmp, true>::tmp_list
00770         >::Result ReplacedTList;
00771         // Create instance of the tmp list
00772         TmpInstance<ReplacedTList> tmpInstance;
00773 //      cout << "TargetIndex: " << TargetIndex << endl;
00774 //      TmpAnalyserUnaNode<Exp, tmplist, TarConType, ForceUseTmp, true>::print(TTYPENAME Exp::exp_tag());
00775         TmpAnalyserUnaNode<Exp, tmplist, TarConType, ForceUseTmp, true>::
00776 			ass_root(exp, tmpInstance, mat, Int2Type<TargetIndex>());
00777     }
00778 
00780     template<class Exp, class Con, class ErrChk1, class ErrChk2, class ForceUseTmp> EXMAT_INLINE2
00781     static void parseExp_inner(Mat<Con, ErrChk1>& mat,
00782         const Mat<Exp, ErrChk2>& exp, Int2Type<0+2*1>, ForceUseTmp)
00783     {
00784         typedef Mat<Con, ErrChk1> TarConType;
00785         enum {
00786             // This target index only valid for static target con
00787             TargetIndex = TmpAnalyserBinNode<Exp, Loki::NullType, TarConType, ForceUseTmp, true>::TmpIndex,
00788             // is the target container dynamic?
00789             IsTarConDynamic =
00790                 (Con::ROWS == 0 || Con::COLS == 0)
00791         };
00792         // Define the unavailable target container
00793         typedef TmpListEntry<Mat<Con, EmptyErrorChecker>, false> UnAvailableTarCon;
00794         // Insert the UnAvailableTarCon into the analyzer,
00795         // so that the target con will always occupied the list at index 0,
00796         // if the target con is dynamic
00797         typedef typename IF<
00798             IsTarConDynamic,
00799             LOKI_TYPELIST_1(UnAvailableTarCon),
00800             Loki::NullType
00801         >::RET tmplist;
00802         // Replace the type in tmp list, simplify static tmp, warp dynamic tmp with DynamicTmpList
00803         typedef typename exmat::PNS::ReplaceTmp<
00804             TTYPENAME TmpAnalyserBinNode<Exp, tmplist, TarConType, ForceUseTmp, true>::tmp_list
00805         >::Result ReplacedTList;
00806         // Create instance of the tmp list
00807         EXMAT_VAR_ALIGN(TmpInstance<ReplacedTList> tmpInstance, EXMAT_SIMD_DEFAULT_ALIGN);
00808 //      cout << "TargetIndex: " << TargetIndex << endl;
00809 //      TmpAnalyserBinNode<Exp, tmplist, TarConType, ForceUseTmp, true>::print(TTYPENAME Exp::exp_tag());
00810         TmpAnalyserBinNode<Exp, tmplist, TarConType, ForceUseTmp, true>::
00811 			ass_root(exp, tmpInstance, mat, Int2Type<TargetIndex>());
00812     }
00813 
00815     template<class Exp, class Con, class ErrChk1, class ErrChk2, class ForceUseTmp> EXMAT_INLINE2
00816     static void parseExp_inner(Mat<Con, ErrChk1>& mat,
00817         const Mat<Exp, ErrChk2>& exp, Int2Type<0+2*0>, ForceUseTmp)
00818     {
00819         mat.AssignNoAna(exp);
00820     }
00822 
00823 
00825     template<class Exp, class Con, class ErrChk1, class ErrChk2> EXMAT_INLINE2
00826     static void parseExp(Mat<Con, ErrChk1>& mat, const Mat<Exp, ErrChk2>& exp) {
00827         enum {
00828             IsUna = IsDerivedFrom<Exp,UnaExpTag>::RET,
00829             IsBin = IsDerivedFrom<Exp,BinExpTag>::RET,
00830             // If the rhs is linear recursive, no tmp analysis is needed
00831             IsLinear = Exp::IsLinearRecursive,
00832             // Split the expression for SIMD container
00833 //          ForceUseTmp = IsDerivedFrom<Con,SIMDTag>::RET
00834             ForceUseTmp = false
00835         };
00836         parseExp_inner(mat, exp,
00837             Int2Type<
00838                 (IsLinear && !ForceUseTmp) ? 0 :
00839                 (IsUna+2*IsBin)
00840             >(),
00841             Int2Type<ForceUseTmp>()
00842         );
00843     }
00844 
00845 }   // namespace exmat
00846 
00847 #if _MSC_VER
00848 #   pragma warning( pop )
00849 #endif  // EXMAT_VC
00850 
00851 #endif  // _EXMAT_EXPTMP_H

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