TemplateTools.h

Go to the documentation of this file.
00001 
00005 /* Copyright (C) 2002, 2003, 2004 Bernd Speiser */
00006 /* This file is part of BSUtilities.
00007 
00008 BSUtilities is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU General Public License
00010 as published by the Free Software Foundation; either version 2
00011 of the License, or (at your option) any later version.
00012 
00013 BSUtilities is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 GNU General Public License for more details.
00017   
00018 You should have received a copy of the GNU General Public License
00019 along with this program; if not, write to the Free Software
00020 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00021 02111-1307, USA.
00022 */
00023 
00024 /*
00025 These classes are derived based on ideas and code in the following
00026 books and articles:
00027 
00028 A. Alexandrescu, Modern C++ Design, Addison Wesley, Boston, 2001
00029 
00030 K. Czarnecki and U.W. Eisenecker, Generative Programming, 
00031 Addison Wesley, Boston, 2000
00032 
00033 W.E. Brown, Proceedings of the Second Workshop on C++ Template 
00034 Programming, Oct. 14, 2001, Tampa Bay, Fla., USA;
00035 http://www.oonumerics.org/tmpw01/brown.pdf
00036 
00037 J.M. Bucknall, http://www.boyet.com/Articles/GcdfractionClass.html 
00038 
00039 B.K.P. Horn, Rational Arithmetic for Minicomputers, 
00040 Software - Practice and Experience 8, 171 - 176 (1978) 
00041 */
00042 
00043 #ifndef _TemplateTools_h
00044 #define _TemplateTools_h
00045 
00046 #include "NullType.h"
00047 #include "TypeManip.h"
00048 #include "Typelist.h"
00049 
00050 #include <limits>
00051 #include <utility>
00052 #include <cstdlib>
00053 #include <cmath>
00054 
00055 namespace BSUtilities {
00056 
00058 //
00059 // compile time logical decisions
00060 //
00062 
00064 
00068 template<bool condition, class Then, class Else>
00069   struct IF
00070   {
00071     typedef Then RET;
00072   };
00073 
00074 template<class Then, class Else>
00075   struct IF<false, Then, Else>
00076   {
00077     typedef Else RET;
00078   };
00079 
00081 
00084 template<bool Arg1, bool Arg2> 
00085   struct OR
00086   {
00087     enum {RET = false};
00088   };
00089 
00091 
00094 template<bool Arg2> 
00095   struct OR<true, Arg2>
00096   {
00097     enum {RET = true};
00098   };
00099 
00101 
00104 template<bool Arg1> 
00105   struct OR<Arg1, true>
00106   {
00107     enum {RET = true};
00108   };
00109 
00111 
00114 template<> 
00115   struct OR<true, true>
00116   {
00117     enum {RET = true};
00118   };
00119 
00121 //
00122 // equivalence of types and templates
00123 //
00125 
00127 
00130 template<class X> class EmptyTemplate_1 {};
00131 
00133 
00136 template<class X, class Y> class EmptyTemplate_2 {};
00137 
00139 
00141 template<class X, class Y>
00142   struct SameType 
00143   {
00144     enum {sameType = false};
00145   };
00146 
00148 template<class X>
00149   struct SameType<X, X> 
00150   {
00151     enum {sameType = true};
00152   };
00153 
00155 
00157 template<template<class> class X, template<class> class Y>
00158   struct SameTemplate_1 
00159   {
00160     enum {sameTemplate_1 = false};
00161   };
00162 
00164 
00166 template<template<class> class X>
00167   struct SameTemplate_1<X, X> 
00168   {
00169     enum {sameTemplate_1 = true};
00170   };
00171 
00173 
00175 template<template<class, class> class X, template<class, class> class Y>
00176   struct SameTemplate_2 
00177   {
00178     enum {sameTemplate_2 = false};
00179   };
00180 
00182 
00184 template<template<class, class> class X>
00185   struct SameTemplate_2<X, X> 
00186   {
00187     enum {sameTemplate_2 = true};
00188   };
00189 
00191 //
00192 // Loki::TYPELIST helpers
00193 //
00195 
00197 
00200 template<class A, class B> struct Concatenate;
00201 
00202 template<class Head1, class Head2, class Tail1, class Tail2>  
00203 struct Concatenate<Loki::Typelist<Head1, Tail1>, 
00204                                           Loki::Typelist<Head2, Tail2> >
00205   {typedef Loki::Typelist<Head1, 
00206     typename Concatenate<Tail1, Loki::Typelist<Head2, Tail2> >
00207                                                     ::Result > Result;};
00208 
00209 template<class A> struct Concatenate<A, Loki::NullType> 
00210                                                     {typedef A Result;};
00211 
00212 template<class B> struct Concatenate<Loki::NullType, B> 
00213                                                     {typedef B Result;};
00214 
00216 //
00217 // compile time Rational number calculations
00218 //
00220 
00223 template<long N>
00224   struct Signum {static long const RET = (N < 0L) ? -1L : +1L;};
00225 
00228 template<> struct Signum<0L> {static long const RET = 0L;};
00229 
00232 template<long N>
00233   struct Abs {static long const RET = (N < 0L) ? -N : N;};
00234 
00238 template<long M, long N>
00239   struct Gcd
00240   {
00241     private:
00242       static long const m = Abs<M>::RET;
00243       static long const n = Abs<N>::RET;
00244 
00245     public:
00246       static long const RET = Gcd<n, m%n>::RET;
00247   };
00248 
00251 template<long M> struct Gcd<M, 0L> 
00252                                 {static long const RET = Abs<M>::RET;};
00253 
00256 template<> struct Gcd<0L, 0L> {static long const RET = 1L;};
00257 
00259 
00262 inline long gcd (const long &i1, const long &i2)
00263   {
00264     if (i2 == 0L && i1 == 0L)
00265       return 1L;
00266     else if (i2 == 0L)
00267       return std::abs(i1);
00268     else
00269       return gcd (std::abs(i2), std::abs (i1%i2));
00270   }
00271 
00273 
00288 template<class T>
00289   std::pair<long, long> contFrac (const T &value)
00290     {
00291       bool isNegative = (value < T(0.0));
00292 
00293       long p1 = 0;
00294       long p2 = 1;
00295       long q1 = 1;
00296       long q2 = 0;
00297 
00298       long p0;
00299       long q0;
00300 
00301       long i = 0;
00302       T s = std::abs(value);
00303 
00304       long limit = std::numeric_limits<long>::max ();
00305 
00306       while (p2 < limit && q2 < limit)
00307       {
00308         p0 = p1;
00309         q0 = q1;
00310         p1 = p2;
00311         q1 = q2;
00312 
00313         i = long (floor (s));
00314 
00315         p2 = p0 + i * p1;
00316         q2 = q0 + i * q1;
00317 
00318 
00319         if (std::abs(std::abs(value) - T(p2)/T(q2)) 
00320                                    > std::numeric_limits<T>::epsilon ())
00321           s = 1/(s - floor(s));
00322 
00323         else
00324         {
00325           p1 = p2;
00326           q1 = q2;
00327           break;
00328         }
00329       } 
00330 
00331       if (isNegative)
00332         p1 = -p1;
00333 
00334       return std::make_pair (p1, q1);
00335     }
00336 
00341 template<long N, long D=1L>
00342   struct Rational
00343   {
00344     private:
00345       static long const gcd = Signum<D>::RET * Gcd<N,D>::RET;
00346 
00347     public:
00348       static long const numerator = N;
00349       static long const denominator = D;
00350 
00351       typedef Rational<N/gcd, D/gcd> Canonical;
00352 
00354       template<class To>
00355         static To convert() 
00356                          {return static_cast<To>(N)/static_cast<To>(D);}
00357 
00358   };
00359 
00361 template<long D>
00362   struct Rational<0L, D>
00363   {
00364     public:
00365       static long const numerator = 0L;
00366       static long const denominator = 1L;
00367 
00368       typedef Rational<0L, 1L> Canonical;
00369 
00372       template<class To>
00373                        static To convert() {return static_cast<To>(0);}
00374   };
00375 
00377 
00380 template<class R1, class R2> class RationalEquality;
00382 template<long N1, long D1, long N2, long D2> 
00383   class RationalEquality<Rational<N1, D1>, Rational<N2, D2> >
00384   {
00385     private:
00386       typedef Rational<N1, D1> R1;
00387       typedef Rational<N2, D2> R2;
00388 
00389     public:
00390       enum {RET = ((R1::Canonical::numerator 
00391                                          == R2::Canonical::numerator) 
00392           && (R1::Canonical::denominator == R2::Canonical::denominator))
00393                                                               ? 1 : 0 };
00394   };
00395 
00397 template<class R1, class R2> class RationalAdd;
00399 
00406 template<long N1, long D1, long N2, long D2>
00407   class RationalAdd<Rational<N1, D1>, Rational<N2, D2> >
00408   {
00409     private:
00410       typedef Rational<N1, D1> R1;
00411       typedef Rational<N2, D2> R2;
00412 
00413     public:
00414       typedef typename 
00415         Rational<R1::Canonical::numerator * R2::Canonical::denominator 
00416           + R2::Canonical::numerator * R1::Canonical::denominator, 
00417             R1::Canonical::denominator * R2::Canonical::denominator>
00418                                                         ::Canonical RET;
00419   };
00420 
00422 template<class R1, class R2> class RationalSub;
00424 
00431 template<long N1, long D1, long N2, long D2>
00432   class RationalSub<Rational<N1, D1>, Rational<N2, D2> >
00433   {
00434     private:
00435       typedef Rational<N1, D1> R1;
00436       typedef Rational<N2, D2> R2;
00437 
00438     public:
00439       typedef typename 
00440         Rational<R1::Canonical::numerator * R2::Canonical::denominator 
00441           - R2::Canonical::numerator * R1::Canonical::denominator, 
00442             R1::Canonical::denominator * R2::Canonical::denominator>
00443                                                         ::Canonical RET;
00444   };
00445 
00447 template<class R1, class R2> class RationalMult;
00449 
00455 template<long N1, long D1, long N2, long D2>
00456   class RationalMult<Rational<N1, D1>, Rational<N2, D2> >
00457   {
00458     private:
00459       typedef Rational<N1, D1> R1;
00460       typedef Rational<N2, D2> R2;
00461 
00462     public:
00463       typedef typename Rational<R1::Canonical::numerator 
00464         * R2::Canonical::numerator, R1::Canonical::denominator 
00465                            * R2::Canonical::denominator>::Canonical RET;
00466   };
00467 
00469 template<class R1, class R2> class RationalDiv;
00471 
00477 template<long N1, long D1, long N2, long D2>
00478   class RationalDiv<Rational<N1, D1>, Rational<N2, D2> >
00479   {
00480     private:
00481       typedef Rational<N1, D1> R1;
00482       typedef Rational<N2, D2> R2;
00483 
00484     public:
00485       typedef typename Rational<R1::Canonical::numerator 
00486         * R2::Canonical::denominator, R1::Canonical::denominator 
00487                            * R2::Canonical::numerator>::Canonical RET;
00488   };
00489 
00491 template<class R1> class RationalNeg;
00493 
00498 template<long N1, long D1>
00499   class RationalNeg<Rational<N1, D1> >
00500   {
00501     private:
00502       typedef Rational<N1, D1> R1;
00503 
00504     public:
00505       typedef typename Rational<-R1::Canonical::numerator, 
00506                              R1::Canonical::denominator>::Canonical RET;
00507   };
00508 
00509 }
00510 
00511 #endif /* _TemplateTools_h */

Generated on Sun Jul 26 16:51:58 2009 for BSUtilities by  doxygen 1.5.3