Metaprogramming.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 : 4512 4786 )
00034 #endif  // _MSC_VER
00035 
00036 #ifndef _EXMAT_METAPROGRAMMING_H
00037 #define _EXMAT_METAPROGRAMMING_H
00038 
00039 #include "PlatformSpec.h"
00040 #include "StaticAssert.h"
00041 #include "loki/TypeManip.h"
00042 
00043 namespace exmat {
00044 
00046 
00050 template<int v> struct Int2Type
00051 {   enum{ RET = v };    };
00052 
00054 
00057 template<class T> struct Type2Type
00058 {   typedef T RET;  };
00059 
00060 
00062 
00067 template<bool B>
00068 struct EnableIf_c {
00069     typedef void RET;
00070 };
00071 template<>
00072 struct EnableIf_c<true> {
00073     typedef void RET;
00074 };
00075 template<>
00076 struct EnableIf_c<false> {
00077 };
00078 template<bool B>
00079 struct DisableIf_c {
00080     typedef void RET;
00081 };
00082 template<>
00083 struct DisableIf_c<true> {};
00085 
00086 
00088 
00092 template<class Derived, class Base>
00093 class IsDerivedFrom {
00094     struct No {};
00095     struct Yes { No n_[3]; };
00096     struct Helper {
00097         static Yes Test(Base*);
00098         static No  Test(...);
00099     };
00100 public:
00101     enum {
00102         RET = sizeof(Yes) ==
00103             sizeof( Helper::Test(static_cast<Derived*>(0)))
00104     };
00105 };
00106 
00107 
00109 
00112 template<typename T1, typename T2>
00113 struct ISSAMETYPE {
00114     enum {
00115 #ifdef EXMAT_VC6
00116         RET = Loki::IsEqualType<T1, T2>::value
00117 #else
00118         RET = Loki::IsSameType<T1, T2>::value
00119 #endif
00120     };
00121 };
00122 
00123 
00125 
00126 template<int Val1, int Val2>
00127 struct EQUAL {
00128     enum { RET = (Val1 == Val2) };
00129 };
00131 template<int Val1, int Val2>
00132 struct NOT_EQUAL {
00133     enum { RET = (Val1 != Val2) };
00134 };
00136 template<int Val1, int Val2>
00137 struct GREATER {
00138     enum { RET = (Val1 > Val2) };
00139 };
00141 template<int Val1, int Val2>
00142 struct GREATER_EQUAL {
00143     enum { RET = (Val1 >= Val2) };
00144 };
00146 template<int Val1, int Val2>
00147 struct LESS {
00148     enum { RET = (Val1 < Val2) };
00149 };
00151 template<int Val1, int Val2>
00152 struct LESS_EQUAL {
00153     enum { RET = (Val1 <= Val2) };
00154 };
00156 
00157 /************************************************/
00158 // And, Or, Xor operation for bool
00160 
00161 template<bool Val1, bool Val2>
00162 struct AND_bool {
00163     enum { RET = (Val1 && Val2) };
00164 };
00166 template<bool Val1, bool Val2>
00167 struct OR_bool {
00168     enum { RET = (Val1 || Val2) };
00169 };
00171 template<bool Val1, bool Val2>
00172 struct XOR_bool {
00173     enum { RET = (Val1 ^ Val2) };
00174 };
00176 
00177 /************************************************/
00178 // If then else
00179 // Adopted from "Generative Programming, Methods, Tools, and Application" P.435
00180 #if EXMAT_VC6
00181 
00182 
00185 template<bool Condition, class ThenType, class ElseType>
00186 struct IF
00187 {
00188     template<bool Condition>
00189     struct selector {
00190         typedef ThenType SELECT_CLASS;
00191     };
00192 
00193     template<>
00194     struct selector<false> {
00195         typedef ElseType SELECT_CLASS;
00196     };
00197 
00198     typedef selector<Condition>::SELECT_CLASS RET;
00199 };
00200 #else
00201 namespace PNS { // A private namespace
00202     struct SelectThen {
00203         template<class ThenType, class ElseType>
00204         struct Result {
00205             typedef ThenType RET;
00206         };
00207     };
00208     struct SelectElse {
00209         template<class ThenType, class ElseType>
00210         struct Result {
00211             typedef ElseType RET;
00212         };
00213     };
00214     template<bool Condition>
00215     struct ChooseSelector {
00216         typedef SelectThen RET;
00217     };
00218     template<>
00219     struct ChooseSelector<false> {
00220         typedef SelectElse RET;
00221     };
00222 };
00223 
00225 
00228 template<bool Condition, class ThenType, class ElseType>
00229 class IF {
00230     typedef typename ::exmat::PNS::ChooseSelector<Condition>::RET Selector;
00231 public:
00232     // The keyword "template" after the scope operator tells the compiler
00233     // that Code is a member template
00234     typedef typename Selector::template Result<ThenType, ElseType>::RET RET;
00235 };
00236 #endif
00237 
00238 /************************************************/
00239 // Switch - case
00240 // Adopted from "Generative Programming, Methods, Tools, and Application" P.445
00241 // Example usage:
00242 /*
00243 SWITCH<2,
00244     CASE<1,A,
00245     CASE<2,B,
00246     CASE<DEFAULT,D> > >
00247 >::RET
00248 */
00249 // Initialize DEFAULT with an smallest int
00250 const int DEFAULT = ~(~0u >> 1);
00251 const int nilValue = DEFAULT+1;
00252 struct NilCase {
00253     enum { tag = nilValue };
00254     typedef NilCase RET;
00255 };
00256 
00257 template<int tag_, class Type_, class Next_=NilCase>
00258 struct CASE {
00259     enum { tag = tag_ };
00260     typedef Type_ Type;
00261     typedef Next_ Next;
00262 };
00263 
00264 template<int tag, class Case>
00265 class SWITCH {
00266     typedef typename Case::Next NextCase;
00267     enum {
00268         caseTag = Case::tag,
00269         nextTag = NextCase::tag,
00270         found = (caseTag == tag || caseTag == DEFAULT )
00271     };
00272     typedef typename
00273     IF<(nextTag == nilValue),
00274         NilCase,
00275         SWITCH<tag, NextCase>
00276     >::RET NextSwitch;
00277 public:
00278     typedef typename
00279     IF<(found != 0),
00280         typename Case::Type,
00281         typename NextSwitch::RET
00282     >::RET RET;
00283 };
00284 
00285 /************************************************/
00286 // While loop
00287 // Adopted from "Generative Programming, Methods, Tools, and Application" P.457
00288 // User have to supply two class,
00289 // 1) Statement - which contains code to run in each iteration
00290 // 2) Condition - condition to terminate the while loop
00291 // Example usage:
00292 /*
00293 For example we want to do a loop as:
00294 */
00295 namespace PNS {
00296     template<class Statement>
00297     struct STOP {
00298         typedef Statement RET;
00299         EXMAT_INLINE2 static void exec() {};
00300         template<class Env> EXMAT_INLINE2 static void exec(Env&) {};
00301     };
00302 };
00303 
00305 template<class Statement>
00306 struct WHILE {
00307     typedef typename
00308     IF<
00309         Statement::Condition,
00310         WHILE<typename Statement::Next>,
00311         PNS::STOP<Statement>
00312     >::RET TMP;
00313     typedef typename TMP::RET RET;
00314 };
00315 
00316 /************************************************/
00318 template<class Statement>
00319 class DO {
00320     typedef typename Statement::Next NewStatement;
00321     typedef typename IF<
00322         NewStatement::Condition,
00323         DO<NewStatement>,
00324         ::exmat::PNS::STOP<NewStatement>
00325     >::RET TMP;
00326 public:
00327     typedef typename TMP::RET RET;
00328 };
00329 
00330 /************************************************/
00332 template<class Statement>
00333 struct EWHILE {
00334     EXMAT_INLINE2 static void exec() {
00335         IF<
00336             Statement::Condition,
00337             Statement,
00338             PNS::STOP<Statement>
00339         >::RET::exec();     // Call Statement if condition OK
00340         typedef typename Statement::Next next;
00341         IF<
00342             Statement::Condition,
00343             EWHILE<next>,
00344             PNS::STOP<Statement>
00345         >::RET::exec();     // Call EWHILE recursively if Condition OK
00346     }
00347 };
00348 
00349 /************************************************/
00351 template<class Statement>
00352 struct EWHILE1 {
00353     template<class Env>
00354     EXMAT_INLINE2 static void exec(Env& env) {
00355         IF<
00356             Statement::Condition,
00357             Statement,
00358             ::exmat::PNS::STOP<Statement>
00359         >::RET::exec(env);      // Call Statement if condition OK
00360         typedef typename Statement::Next next;
00361         IF<
00362             Statement::Condition,
00363             EWHILE1<next>,
00364             ::exmat::PNS::STOP<Statement>
00365         >::RET::exec(env);      // Call EWHILE recursively if Condition OK
00366     }
00367 };
00368 
00369 
00370 /************************************************/
00372 template<int N1, int N2>
00373 class MIN {
00374 private:
00375     typedef typename
00376         IF<	LESS<N1,N2>::RET,
00377             Int2Type<N1>, Int2Type<N2>
00378         >::RET SmallerType;
00379 public:
00380     enum { RET = SmallerType::RET };
00381 };
00383 template<int N1, int N2>
00384 class MAX {
00385 private:
00386     typedef typename
00387         IF<	GREATER<N1,N2>::RET,
00388             Int2Type<N1>, Int2Type<N2>
00389         >::RET BiggerType;
00390 public:
00391     enum { RET = BiggerType::RET };
00392 };
00393 
00394 /************************************************/
00395 // Square root of an int
00396 namespace PNS {
00397     template<int n_, int p_>
00398     struct SQRT_STAT {
00399         enum {
00400             p = p_,
00401             n = n_
00402         };
00403         typedef SQRT_STAT<n-p-2, p+2> Next;
00404         enum { Condition = n >= 0 };
00405     };
00406 }   // namespace exmat
00408 template<int n>
00409 struct SQRT {
00410     enum {
00411         p = DO<
00412             PNS::SQRT_STAT<n,-1>
00413         >::RET::p,
00414         RET = p/2
00415     };
00416 };
00417 
00418 /************************************************/
00419 // Raising a static variable m, to the power of a static number n
00420 namespace PNS {
00421     template<int m_, unsigned int n_, int num_=1>
00422     struct POW_STAT {
00423         typedef POW_STAT<m_, n_-1, num_*m_> Next;
00424         enum { Condition = n_ > 0 };
00425         enum { RET = num_ };
00426     };
00427 }   // namespace exmat
00429 template<int m, unsigned int n>
00430 class POW {
00431     typedef typename
00432     IF< n == 0,     // Handle the special case, n=0
00433         Int2Type<1>,
00434         typename DO<    // Use MAX<n,1> to prevent n_=0 pass to POW_STAT
00435             ::exmat::PNS::POW_STAT<m,MAX<n,1>::RET >
00436         >::RET
00437     >::RET RetType;
00438 public:
00439     enum {
00440         RET = RetType::RET
00441     };
00442 };
00443 #if HAVE_PARTIAL_SPECIALIZATION
00444 template<int m> class POW<m, 0> { public: enum { RET = 1 }; };
00445 template<int m> class POW<m, 1> { public: enum { RET = m }; };
00446 template<int m> class POW<m, 2> { public: enum { RET = m*m }; };
00447 template<int m> class POW<m, 3> { public: enum { RET = m*m*m }; };
00448 #endif  // HAVE_PARTIAL_SPECIALIZATION
00449 
00450 
00451 /************************************************/
00452 // Raising a runtime variable m, to the power of a static number n
00453 /*namespace PNS {
00454 struct POWER_ENV {
00455     EXMAT_INLINE2
00456     POWER_ENV(const int& m_, unsigned int r_) 
00457         : m(m_), r(r_) {}
00458     const int m;
00459     unsigned int r;
00460 };
00462 template<unsigned int n_, unsigned int i_>
00463 struct POWER_STAT {
00464     enum {
00465         n = n_,
00466         i = i_
00467     };
00468     EXMAT_INLINE2
00469     static void exec(POWER_ENV& env) {
00470         env.r *= env.m;
00471     }
00472     typedef POWER_STAT<n, i+1> Next;
00473     enum { Condition = i < n };
00474 };
00475 }   // namespace exmat
00477 template<unsigned int n>
00478 struct pow {
00479     EXMAT_INLINE2
00480     static int exec(const int &m) {
00481         PNS::POWER_ENV env(m, 1);
00482         EWHILE1<PNS::POWER_STAT<n,0> >::exec(env);
00483         return env.r;
00484     }
00485 };*/
00486 
00487 /************************************************/
00491 template<unsigned int num, unsigned int n=sizeof(int)*4/2>
00492 class IsPowOf2 {
00493     typedef typename
00494     IF< n==1,                   // End, not power of 2
00495         Int2Type<false>,
00496     typename
00497     IF< num == POW<2,n>::RET,   // Match one of the POW<2,n>, return true
00498         Int2Type<true>,
00499         IsPowOf2<num, n-1>
00500     >::RET>::RET RetType;
00501 public:
00502     enum {
00503         RET = RetType::RET
00504     };
00505 };
00506 template<> class IsPowOf2<8, sizeof(int)*4/2> {
00507 public: enum { RET = true };
00508 };
00509 template<> class IsPowOf2<16, sizeof(int)*4/2> {
00510 public: enum { RET = true };
00511 };
00512 template<> class IsPowOf2<32, sizeof(int)*4/2> {
00513 public: enum { RET = true };
00514 };
00515 template<> class IsPowOf2<64, sizeof(int)*4/2> {
00516 public: enum { RET = true };
00517 };
00518 
00519 /************************************************/
00520 // Modulus of a runtime variable n, against a static number m
00521 
00522 
00523 /************************************************/
00524 // Compile-time bitset
00525 namespace BITSET {
00526 
00527 enum { BitsUnitLength = sizeof(int) };
00528 
00529 struct NullBITS {
00530     typedef NullBITS Next;
00531     enum { BitsUnit = 0, Level = -1 };
00532 };
00533 
00534 template<int B=0, class N=NullBITS>
00535 struct BITS {
00536     typedef N Next;
00537     enum {
00538         BitsUnit = B,
00539         Level = Next::Level+1
00540     };
00541 
00542 };
00543 
00544 /*template<int B, class Next> static
00545 std::ostream& operator<<(std::ostream& os, const BITS<B,Next>&) {
00546     os << Next();
00547     enum { BitsUnit = BITS<B,Next>::BitsUnit };
00548     for(int i=0; i<BitsUnitLength; ++i) {
00549         os << int(((1 << i) & BitsUnit) != 0);
00550     }
00551     return (os << std::endl);
00552 }
00553 static std::ostream& operator<<(std::ostream& os, const NullBITS&)
00554 {   return os;  }
00555 */
00556 
00557 template<bool b1> struct BIT1 {
00558     typedef BITS<b1> RET;   };
00559 template<bool b1,bool b2> struct BIT2 {
00560     typedef BITS<b1+(b2<<1)> RET;   };
00561 template<bool b1,bool b2,bool b3> struct BIT3 {
00562     typedef BITS<b1+(b2<<1)+(b3<<2)> RET;   };
00563 template<bool b1,bool b2,bool b3,bool b4> struct BIT4 {
00564     typedef BITS<b1+(b2<<1)+(b3<<2)+(b4<<3)> RET;   };
00565 template<bool b1,bool b2,bool b3,bool b4,bool b5> struct BIT5 {
00566     typedef BITS<b1+(b2<<1)+(b3<<2)+(b4<<3)+(b5<<4)> RET;   };
00567 template<bool b1,bool b2,bool b3,bool b4,bool b5,bool b6> struct BIT6 {
00568     typedef BITS<b1+(b2<<1)+(b3<<2)+(b4<<3)+(b5<<4)+(b6<<5)> RET;   };
00569 template<bool b1,bool b2,bool b3,bool b4,bool b5,bool b6,bool b7> struct BIT7 {
00570     typedef BITS<b1+(b2<<1)+(b3<<2)+(b4<<3)+(b5<<4)+(b6<<5)+(b7<<6)> RET;   };
00571 template<bool b1,bool b2,bool b3,bool b4,bool b5,bool b6,bool b7,bool b8> struct BIT8 {
00572     typedef BITS<b1+(b2<<1)+(b3<<2)+(b4<<3)+(b5<<4)+(b6<<5)+(b7<<6)+(b8<<7)> RET;   };
00573 
00574 template<class Bits, int I>
00575 class GetBitAt {
00576     template<int b, int i> struct BitAtInt
00577     { enum { RET = (1 << i) & b }; };
00578 
00579     typedef typename IF<EQUAL<I/32, Bits::Level>::RET,
00580         BitAtInt<Bits::BitsUnit, I%BitsUnitLength>,
00581         GetBitAt<TTYPENAME Bits::Next, I%BitsUnitLength>
00582     >::RET RetT;
00583 public:
00584     enum {
00585         RET = (RetT::RET > 0 ? 1 : 0)
00586     };
00587 };
00588 
00590 template<class Bits, int I, bool Bit>
00591 class SetBitAt {
00592     enum {
00593         I2 = I%BitsUnitLength,
00594         NewBitsUnit = (!Bit << I2) ^ (Bits::BitsUnit | (1 << I2))
00595     };
00596 #if EXMAT_VC6
00597 public:
00598 #endif  // EXMAT_VC6
00599     template<class Bits_, int I_, bool Bit_>
00600     struct Append {
00601         enum {
00602             Lp1 = Bits_::Level+1,
00603             BitsUnit = Bit_ << I_%BitsUnitLength
00604         };
00605         typedef typename IF<GREATER<I_/BitsUnitLength, Lp1>::RET,
00606             Append<BITS<0, Bits_>, I_, Bit_>,
00607             Type2Type<BITS<BitsUnit, Bits_> >
00608         >::RET RetT_;
00609         typedef typename RetT_::RET RET;
00610     };
00611 #if EXMAT_VC6
00612 private:
00613 #endif  // EXMAT_VC6
00614     typedef typename IF<GREATER<I/BitsUnitLength, Bits::Level>::RET,
00615         Type2Type<TTYPENAME Bits::Next>,
00616     TTYPENAME IF<EQUAL<I/BitsUnitLength, Bits::Level>::RET,
00617         Type2Type<TTYPENAME Bits::Next>,
00618         SetBitAt<TTYPENAME Bits::Next,I,Bit>
00619     >::RET>::RET Helper;
00620 
00621     typedef typename IF<GREATER<I/BitsUnitLength, Bits::Level>::RET,
00622         Append<Bits, I, Bit>,
00623     TTYPENAME IF<EQUAL<I/BitsUnitLength, Bits::Level>::RET,
00624         Type2Type<BITS<NewBitsUnit, TTYPENAME Helper::RET> >,
00625         Type2Type<BITS<Bits::BitsUnit, TTYPENAME Helper::RET> >
00626     >::RET>::RET RetT;
00627 
00628 public:
00629     typedef typename RetT::RET RET;
00630 };
00631 
00632 template<class Bits1, class Bits2>
00633 class OR {
00634     enum {
00635         LargerLevel = MAX<Bits1::Level, Bits2::Level>::RET,
00636         ResultUnit = 
00637             (Bits1::Level == LargerLevel ? Bits1::BitsUnit : 0) |
00638             (Bits2::Level == LargerLevel ? Bits2::BitsUnit : 0)
00639     };
00640     typedef typename IF<EQUAL<Bits1::Level,LargerLevel>::RET,
00641         TTYPENAME Bits1::Next, Bits1
00642     >::RET B1N;     // Bits1's next
00643     typedef typename IF<EQUAL<Bits2::Level,LargerLevel>::RET,
00644         TTYPENAME Bits2::Next, Bits2
00645     >::RET B2N;     // Bits2's next
00646     typedef typename IF<EQUAL<LargerLevel, 0>::RET,
00647         Type2Type<BITS<ResultUnit> >,
00648         OR<B1N, B2N>
00649     >::RET Helper;
00650 public:
00651     typedef typename IF<EQUAL<LargerLevel, 0>::RET,
00652         TTYPENAME Helper::RET,
00653         BITS<ResultUnit, TTYPENAME Helper::RET>
00654     >::RET RET;
00655 };
00656 
00657 template<class Bits1, class Bits2>
00658 class XOR {
00659     enum {
00660         LargerLevel = MAX<Bits1::Level, Bits2::Level>::RET,
00661         ResultUnit = 
00662         (Bits1::Level == LargerLevel ? Bits1::BitsUnit : 0) ^
00663         (Bits2::Level == LargerLevel ? Bits2::BitsUnit : 0)
00664     };
00665     typedef typename IF<EQUAL<Bits1::Level,LargerLevel>::RET,
00666         TTYPENAME Bits1::Next, Bits1
00667     >::RET B1N;     // Bits1's next
00668     typedef typename IF<EQUAL<Bits2::Level,LargerLevel>::RET,
00669         TTYPENAME Bits2::Next, Bits2
00670     >::RET B2N;     // Bits2's next
00671     typedef typename IF<EQUAL<LargerLevel, 0>::RET,
00672         Type2Type<BITS<ResultUnit> >,
00673         XOR<B1N, B2N>
00674     >::RET Helper;
00675 public:
00676     typedef typename IF<EQUAL<LargerLevel, 0>::RET,
00677         TTYPENAME Helper::RET,
00678         BITS<ResultUnit, TTYPENAME Helper::RET>
00679     >::RET RET;
00680 };
00681 
00682 template<class Bits1, class Bits2>
00683 class AND {
00684     enum {
00685         LargerLevel = MAX<Bits1::Level, Bits2::Level>::RET,
00686         ResultUnit = 
00687         (Bits1::Level == LargerLevel ? Bits1::BitsUnit : 0) &
00688         (Bits2::Level == LargerLevel ? Bits2::BitsUnit : 0)
00689     };
00690     typedef typename IF<EQUAL<Bits1::Level,LargerLevel>::RET,
00691         TTYPENAME Bits1::Next, Bits1
00692     >::RET B1N;     // Bits1's next
00693     typedef typename IF<EQUAL<Bits2::Level,LargerLevel>::RET,
00694         TTYPENAME Bits2::Next, Bits2
00695     >::RET B2N;     // Bits2's next
00696     typedef typename IF<EQUAL<LargerLevel, 0>::RET,
00697         Type2Type<BITS<ResultUnit> >,
00698         AND<B1N, B2N>
00699     >::RET Helper;
00700 public:
00701     typedef typename IF<EQUAL<LargerLevel, 0>::RET,
00702         TTYPENAME Helper::RET,
00703         BITS<ResultUnit, TTYPENAME Helper::RET>
00704     >::RET RET;
00705 };
00706 
00707 template<class Bits>
00708 class NOT {
00709     enum { ResultUnit = ~Bits::BitsUnit };
00710     typedef typename IF<EQUAL<Bits::Level, 0>::RET,
00711         Type2Type<BITS<ResultUnit> >,
00712         NOT<TTYPENAME Bits::Next>
00713     >::RET Helper;
00714 public:
00715     typedef typename IF<EQUAL<Bits::Level, 0>::RET,
00716         TTYPENAME Helper::RET,
00717         BITS<ResultUnit, TTYPENAME Helper::RET>
00718     >::RET RET;
00719 };
00720 
00721 };  // namespace BITSET
00722 
00723 }   // namespace exmat
00724 
00725 #ifdef _MSC_VER
00726 #   pragma warning( pop )
00727 #endif  // _MSC_VER
00728 
00729 #endif  // _EXMAT_METAPROGRAMMING_H

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