Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

Unit.h

Go to the documentation of this file.
00001 
00004 /* Unit is an abstract base class for units according to the SI, see
00005    Mills et al., 1993 */
00006 
00007 /* Copyright (C) 2002 - 2005, Bernd Speiser */
00008 /* This file is part of Quantity.
00009 
00010 Quantity is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 Quantity is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019   
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00023 02111-1307, USA.
00024 */
00025 
00026 #ifndef _Unit_h
00027 #define _Unit_h
00028 
00029 #include <vector>
00030 #include <string>
00031 
00032 #include "Quantity/Prefix.h"
00033 
00034 #include "NullType.h"
00035 #include "EmptyType.h"
00036 #include "TypeManip.h"
00037 #include "Typelist.h"
00038 
00039 #include "BSUtilities.h"
00040 #include "TemplateTools.h"
00041 #include "Conversion.h"
00042 
00043 #include "xmlwriter.h"
00044 
00045 #include <tinyxml/tinyxml.h>
00046 
00048 
00056 namespace unit {
00057 
00059 //
00060 //  Helper classes and structs which check that units are derived
00061 //  from certain base classes 
00062 //
00064 
00066 
00069 template<bool> 
00070   struct UnitError;
00071 
00073 
00075 template<class BU, class TU>
00076   struct CheckUnit
00077   {
00079 
00089     typedef typename
00090       BSUtilities::IF<Loki::SuperSubclass<BU, TU>::value, 
00091                                        TU, UnitError<true> >::RET Check;
00092   };
00093 
00095 
00101 template<class BU, class TUL>
00102   struct CheckUnits
00103   {
00104     private: 
00105       typedef 
00106             typename CheckUnit<BU, typename TUL::Head>::Check UnitCheck;
00107 
00108     public: 
00109        typedef typename CheckUnits<BU, typename TUL::Tail>::Check Check;
00110   };
00111 
00113 
00116 template<class BU>
00117   struct CheckUnits<BU, Loki::NullType>
00118   {
00120     typedef Loki::EmptyType Check;
00121   };
00122 
00124 //
00125 //  the Units and Unit base class templates
00126 //
00128 
00130 class Units
00131   {
00132     public:
00134 
00137       static const std::string Version (void)
00138         {static const std::string v_string ("Units version 1.2");
00139                                                        return v_string;}
00140 
00142 
00145       static const std::string version (void) {return Version ();}
00146 
00148 
00150   static const std::string TAG;
00151 
00153 
00155   static const std::string TYPETAG;
00156 
00157   };
00158 
00160 
00164 template<class BT> class Unit : public Units
00165   {
00166     public:
00168 
00170       virtual const std::string name (void) const = 0;
00171 
00173 
00175       virtual const std::string symbol (void) const = 0;
00176 
00178 
00180       virtual const bool isSI (void) const = 0;
00181 
00182   };
00183 
00185 //
00186 //  the NonPrefixable units
00187 //
00189 
00191 
00195 template<class BT, class U> 
00196   class NonPrefixable : public Unit<BT>
00197   {
00198     private:
00200       static const bool SI;
00201 
00203 
00205       static const std::string Namestring;
00206 
00208 
00210       static const std::string Symbolstring;
00211 
00212     public:
00214 
00218       static const bool IsSI (void) {return SI;}
00219 
00221 
00223       const bool isSI (void) const {return IsSI ();}
00224 
00226 /*  direct static access to be used if type of unit is known at 
00227     compile time; returns the namestring;
00228     must not be a static const data member, since similar functions
00229     in other cases of units require access to possibly not yet defined
00230     static data.
00231 */
00232       static const std::string Name (void) {return Namestring;}
00233 
00235 
00238       const std::string name (void) const {return Name ();}
00239 
00241 /*  direct static access to be used if type of unit is known at 
00242     compile time; 
00243     must not be a static const data member, since similar functions
00244     in other cases of units require access to possibly not yet defined
00245     static data.
00246 */
00247       static const std::string Symbol (void) {return Symbolstring;}
00248 
00250 
00253       const std::string symbol (void) const {return Symbol ();}
00254 
00255   };
00256 
00258 //
00259 //  the Prefixable and Prefixed units
00260 //
00262 
00263 // forward declaration
00264 template<class BT, class U> class Prefixable;
00265 
00267 
00270 template<class BP, class UP = No> class Prefixed;
00271 
00273 
00278 template<class BT, class U, class UP> 
00279   class Prefixed<Prefixable<BT, U>, UP> : public Prefixable<BT, U>
00280   {
00281     public:
00283 /*  direct static access to be used if type of unit is known at 
00284     compile time; 
00285     get name from prefix and prepend to basename which is inherited
00286     from Prefixable<BT, U>;
00287     must not be a static const data member, since similar functions
00288     in other cases of units require access to possibly not yet defined
00289     static data.
00290 */
00291       static const std::string Name (void) {return UP::Name + Basename;}
00292 
00294 
00297       const std::string name (void) const {return Name ();}
00298 
00300 /*  direct static access to be used if type of unit is known at 
00301     compile time; 
00302     get symbol from prefix and prepend to basesymbol which is inherited
00303     from Prefixable<BT, U>
00304     must not be a static const data member, since similar functions
00305     in other cases of units require access to possibly not yet defined
00306     static data.
00307 */
00308       static const std::string Symbol (void) 
00309                                        {return UP::Symbol + Basesymbol;}
00310 
00312 
00315       const std::string symbol (void) const {return Symbol ();}
00316 
00317   };
00318 
00320 
00327 template<class BT, class U> class Prefixable : public Unit<BT>
00328   {
00329     private:
00331 
00333       static const bool SI;
00334 
00335     public:
00337       typedef Loki::Typelist<Prefixed<Prefixable<BT, U>, Yotta>, 
00338               Loki::Typelist<Prefixed<Prefixable<BT, U>, Zetta>, 
00339               Loki::Typelist<Prefixed<Prefixable<BT, U>, Exa>, 
00340               Loki::Typelist<Prefixed<Prefixable<BT, U>, Peta>, 
00341               Loki::Typelist<Prefixed<Prefixable<BT, U>, Tera>, 
00342               Loki::Typelist<Prefixed<Prefixable<BT, U>, Giga>, 
00343               Loki::Typelist<Prefixed<Prefixable<BT, U>, Mega>, 
00344               Loki::Typelist<Prefixed<Prefixable<BT, U>, Kilo>, 
00345               Loki::Typelist<Prefixed<Prefixable<BT, U>, Hecto>, 
00346               Loki::Typelist<Prefixed<Prefixable<BT, U>, Deca>, 
00347               Loki::Typelist<Prefixed<Prefixable<BT, U>, No>, 
00348               Loki::Typelist<Prefixed<Prefixable<BT, U>, Deci>, 
00349               Loki::Typelist<Prefixed<Prefixable<BT, U>, Centi>, 
00350               Loki::Typelist<Prefixed<Prefixable<BT, U>, Milli>, 
00351               Loki::Typelist<Prefixed<Prefixable<BT, U>, Micro>, 
00352               Loki::Typelist<Prefixed<Prefixable<BT, U>, Nano>, 
00353               Loki::Typelist<Prefixed<Prefixable<BT, U>, Pico>, 
00354               Loki::Typelist<Prefixed<Prefixable<BT, U>, Femto>, 
00355               Loki::Typelist<Prefixed<Prefixable<BT, U>, Atto>, 
00356               Loki::Typelist<Prefixed<Prefixable<BT, U>, Zepto>, 
00357               Loki::Typelist<Prefixed<Prefixable<BT, U>, Yocto>, 
00358               Loki::NullType> > > > > > > > > > > > > > > > > > > > > 
00359                                                                   Units;
00360 
00362 
00366       static const bool IsSI (void) {return SI;}
00367 
00369 
00371       const bool isSI (void) const {return IsSI ();}
00372 
00373     protected:
00375 /*  direct static access to be used if type of unit is known at 
00376     compile time 
00377 */
00378       static const std::string Basename;
00379 
00381 /*  direct static access to be used if type of unit is known at 
00382     compile time 
00383 */
00384       static const std::string Basesymbol;
00385 
00386   };
00387 
00389 //
00390 //  the ComposeBase and Composed units with helper classes and structs
00391 //  ComposeElement, ComposedSI, ComposedStrings
00392 //
00394 
00396 template<class BT, class CEL> class ComposeBase;
00397 
00399 
00402 template<class BC, class CUL> class Composed;
00403 
00405 
00410 template<class BT, class UL, class R> struct ComposeElement;
00411 
00413 
00419 template<class BT, class BT1, class U, class UTail, long N, long D>
00420   struct 
00421     ComposeElement<BT, Loki::Typelist<NonPrefixable<BT1, U>, UTail>,
00422                                            BSUtilities::Rational<N, D> >
00423   {
00424     private:
00425       typedef typename CheckUnits<Unit<BT1>, 
00426             Loki::Typelist<NonPrefixable<BT1, U>, UTail> >::Check Check;
00427 
00428     public:
00429       typedef Loki::Typelist<NonPrefixable<BT1, U>, UTail> Units;
00430       typedef BSUtilities::Rational<N, D> Power;
00431   };
00432 
00434 
00440 template<class BT, class BT1, class U, class UP, class UTail, 
00441                                                          long N, long D>
00442   struct ComposeElement<BT,
00443     Loki::Typelist<Prefixed<Prefixable<BT1, U>, UP>, UTail>, 
00444                                            BSUtilities::Rational<N, D> >
00445   {
00446     private:
00447       typedef typename CheckUnits<Unit<BT1>, 
00448             Loki::Typelist<Prefixed<Prefixable<BT1, U>, UP>, UTail> >
00449                                                           ::Check Check;
00450 
00451     public:
00452       typedef Loki::Typelist<Prefixed<Prefixable<BT1, U>, UP>, UTail>
00453                                                                   Units;
00454       typedef BSUtilities::Rational<N, D> Power;
00455   };
00456 
00458 
00464 template<class BT, class BT1, class CEL, class CUL, 
00465                                             class UTail, long N, long D>
00466   struct ComposeElement<BT,
00467     Loki::Typelist<Composed<ComposeBase<BT1, CEL>, CUL>, UTail>, 
00468                                            BSUtilities::Rational<N, D> >
00469   {
00470     private:
00471       typedef typename CheckUnits<Unit<BT1>, 
00472         Loki::Typelist<Composed<ComposeBase<BT1, CEL>, CUL>, UTail> >
00473                                                           ::Check Check;
00474 
00475     public:
00476       typedef Loki::Typelist<Composed<ComposeBase<BT1, CEL>, CUL>, 
00477                                                            UTail> Units;
00478       typedef BSUtilities::Rational<N, D> Power;
00479   };
00480 
00482 
00484 template<class UL> struct ComposedSI;
00485 
00487 
00491 template<class U, class UTail>
00492   struct ComposedSI<Loki::Typelist<U, UTail> >
00493   {
00498     static const bool isSI (void) 
00499         {return ((U::IsSI () && ComposedSI<UTail>::isSI ()) ? 1 : 0);}
00500 
00501   };
00502   
00506 template<>
00507   struct ComposedSI<Loki::NullType>
00508   {
00509     static const bool isSI (void) {return true;}
00510   };
00511 
00513 
00516 template<class UL, class RL> struct ComposedStrings;
00517 
00519 
00521 template<class U, class UTail, long N, long D, class RTail>
00522   struct ComposedStrings<Loki::Typelist<U, UTail>, 
00523                     Loki::Typelist<BSUtilities::Rational<N, D>, RTail> >
00524   {
00525       static const std::string Name (void)
00526         {return U::Name ()
00527           + "^(" + BSUtilities::Conversion<long>::to_string(N) 
00528               + "/" + BSUtilities::Conversion<long>::to_string(D) + ")"
00529                               + ComposedStrings<UTail, RTail>::Name ();}
00530 
00531       static const std::string Symbol (void)
00532         {return U::Symbol ()
00533           + "^(" + BSUtilities::Conversion<long>::to_string(N) 
00534               + "/" + BSUtilities::Conversion<long>::to_string(D) + ")"
00535                             + ComposedStrings<UTail, RTail>::Symbol ();}
00536   };
00537 
00539 
00541 template<class U, class UTail, long N, class RTail>
00542   struct ComposedStrings<Loki::Typelist<U, UTail>, 
00543                    Loki::Typelist<BSUtilities::Rational<N, 1L>, RTail> >
00544   {
00545       static const std::string Name (void)
00546         {return U::Name ()
00547           + "^" + BSUtilities::Conversion<long>::to_string(N) 
00548                               + ComposedStrings<UTail, RTail>::Name ();}
00549 
00550       static const std::string Symbol (void)
00551         {return U::Symbol ()
00552           + "^" + BSUtilities::Conversion<long>::to_string(N) + " "
00553                             + ComposedStrings<UTail, RTail>::Symbol ();}
00554   };
00555 
00557 
00559 template<class U, class UTail, class RTail>
00560   struct ComposedStrings<Loki::Typelist<U, UTail>, 
00561                   Loki::Typelist<BSUtilities::Rational<1L, 1L>, RTail> >
00562   {
00563       static const std::string Name (void)
00564         {return U::Name () + ComposedStrings<UTail, RTail>::Name ();}
00565 
00566       static const std::string Symbol (void)
00567         {return U::Symbol () + " "
00568                             + ComposedStrings<UTail, RTail>::Symbol ();}
00569   };
00570 
00572 
00574 template<class U, long N, long D>
00575   struct ComposedStrings<Loki::Typelist<U, Loki::NullType>, 
00576            Loki::Typelist<BSUtilities::Rational<N, D>, Loki::NullType> >
00577   {
00578       static const std::string Name (void)
00579        {return U::Name ()
00580          + "^(" + BSUtilities::Conversion<long>::to_string(N) 
00581              + "/" + BSUtilities::Conversion<long>::to_string(D) + ")";}
00582 
00583       static const std::string Symbol (void)
00584        {return U::Symbol ()
00585          + "^(" + BSUtilities::Conversion<long>::to_string(N) 
00586              + "/" + BSUtilities::Conversion<long>::to_string(D) + ")";}
00587   };
00588 
00590 
00593 template<class U, long N>
00594   struct ComposedStrings<Loki::Typelist<U, Loki::NullType>, 
00595               Loki::Typelist<BSUtilities::Rational<N>, Loki::NullType> >
00596   {
00597       static const std::string Name (void)
00598        {return U::Name ()
00599          + "^" + BSUtilities::Conversion<long>::to_string(N);}
00600 
00601       static const std::string Symbol (void)
00602        {return U::Symbol ()
00603          + "^" + BSUtilities::Conversion<long>::to_string(N);}
00604   };
00605 
00607 
00616 template<class BT, class CEL, class UL>
00617   class Composed<ComposeBase<BT, CEL>, UL> : public ComposeBase<BT, CEL>
00618   {
00619     private:
00620       typedef Composed<ComposeBase<BT, CEL>, UL> Unit;
00621       typedef typename ComposeBase<BT, CEL>::Powers::Powers Powers;
00622 
00623     public:
00625 /*  static access
00626 */
00627       static const bool IsSI (void) {return ComposedSI<UL>::isSI ();}
00628 
00630 
00632       bool const isSI (void) const {return IsSI ();}
00633 
00635 /*  direct static access to be used if type of unit is known at 
00636     compile time;
00637     must not be a static const data member, since it requires access
00638     to the name values of the individual elementary units; they may 
00639     not be available yet when they are needed here.
00640 */
00641         static const std::string Name (void)
00642                           {return ComposedStrings<UL, Powers>::Name ();}
00643 
00645 
00648       const std::string name (void) const {return Name ();}
00649 
00651 /*  direct static access to be used if type of unit is known at 
00652     compile time;
00653     must not be a static const data member, since it requires access
00654     to the symbol values of the individual elementary units; they may 
00655     not be available yet when they are needed here.
00656 */
00657         static const std::string Symbol (void)
00658                         {return ComposedStrings<UL, Powers>::Symbol ();}
00659 
00661 
00664       const std::string symbol (void) const {return Symbol ();}
00665 
00666   };
00667 
00669 
00678 template<class UL, class CUL> struct GenComposedList;
00679 
00681 
00687 template<class U, class UTail>
00688   struct GenComposedList<Loki::Typelist<U, UTail>, Loki::NullType>
00689   {
00690       typedef 
00691         Loki::Typelist<Loki::Typelist<U, Loki::NullType>,
00692             typename GenComposedList<UTail, Loki::NullType>::List> List;
00693   };
00694 
00696 
00700 template<>
00701   struct GenComposedList<Loki::NullType, Loki::NullType>
00702   {
00703     typedef Loki::NullType List;
00704   };
00705 
00707 
00715 template<class U1, class U, class UTail, class CULTail>
00716   struct GenComposedList<U1, 
00717                      Loki::Typelist<Loki::Typelist<U, UTail>, CULTail> >
00718   {
00719      typedef Loki::Typelist<Loki::Typelist<U1, 
00720         Loki::Typelist<U, UTail> >, 
00721                       typename GenComposedList<U1, CULTail>::List> List;
00722   };
00723 
00725 
00727 template<class U>
00728   struct GenComposedList<U, Loki::NullType>
00729   {
00730       typedef Loki::NullType List;
00731   };
00732 
00734 
00740 template<class U1, class U, class UTail, class U1Tail, class CULTail>
00741   struct GenComposedList<Loki::Typelist<U1, U1Tail>,
00742                      Loki::Typelist<Loki::Typelist<U, UTail>, CULTail> >
00743   {
00744       typedef typename BSUtilities::Concatenate<typename 
00745         GenComposedList<U1, 
00746           Loki::Typelist<Loki::Typelist<U, UTail>, CULTail> >::List,
00747             typename GenComposedList<U1Tail, 
00748               Loki::Typelist<Loki::Typelist<U, UTail>, CULTail> 
00749                                                   >::List>::Result List;
00750   };
00751 
00753 
00756 template<class U, class UTail, class CULTail>
00757   struct GenComposedList<Loki::NullType, 
00758                      Loki::Typelist<Loki::Typelist<U, UTail>, CULTail> >
00759   {
00760       typedef Loki::NullType List;
00761   };
00762 
00764 
00767 template<class CEL> struct ExpandComposeElementList;
00768 
00770 
00775 template<class CELHead, class CELTail>
00776   struct ExpandComposeElementList<Loki::Typelist<CELHead, CELTail> >
00777   {
00778       typedef typename GenComposedList<typename CELHead::Units,
00779            typename ExpandComposeElementList<CELTail>::List>::List List;
00780   };
00781 
00783 
00785 template<>
00786   struct ExpandComposeElementList<Loki::NullType>
00787   {
00788       typedef Loki::NullType List;
00789   };
00790 
00792 
00795 template<class BC, class CUL> struct GenComposedUnits;
00796 
00798 
00801 template<class BT, class CEL, class CULHead, class CULTail>
00802   struct GenComposedUnits<ComposeBase<BT, CEL>, 
00803                                     Loki::Typelist<CULHead, CULTail> >
00804   {
00805       typedef Loki::Typelist<Composed<ComposeBase<BT, CEL>, CULHead>,
00806         typename GenComposedUnits<ComposeBase<BT, CEL>, 
00807                                                    CULTail>::List> List;
00808   };
00809           
00811 
00814 template<class BT, class CEL>
00815   struct GenComposedUnits<ComposeBase<BT, CEL>, Loki::NullType>
00816   {
00817       typedef Loki::NullType List;
00818   };
00819 
00821 
00823 template<class CEL> struct GenPowers;
00824 
00826 
00829 template<class CELHead, class CELTail>
00830   struct GenPowers<Loki::Typelist<CELHead, CELTail> >
00831   {
00832     typedef Loki::Typelist<typename CELHead::Power, 
00833                             typename GenPowers<CELTail>::Powers> Powers;
00834   };
00835 
00837 
00841 template<class CE>
00842   struct GenPowers<Loki::Typelist<CE, Loki::NullType> >
00843   {
00844     typedef Loki::Typelist<typename CE::Power, Loki::NullType> Powers;
00845   };
00846 
00847           
00849 //
00850 //  template ComposeBase
00851 //  a unit compounded from one or more base units
00852 //
00854 
00856 
00860 template<class BT, class UHead, class UTail, 
00861                                  long N, long D, class ELTail>
00862   class ComposeBase<BT, Loki::Typelist<ComposeElement<BT, 
00863         Loki::Typelist<UHead, UTail>, BSUtilities::Rational<N, D> >, 
00864                                              ELTail> > : public Unit<BT>
00865   {
00866     private:
00867       typedef 
00868         Loki::Typelist<ComposeElement<BT, Loki::Typelist<UHead, UTail>,
00869                      BSUtilities::Rational<N, D> >, ELTail> ElementList;
00870 
00871     public:
00872       typedef GenPowers<ElementList> Powers;
00873 
00874       typedef typename 
00875         GenComposedUnits<ComposeBase<BT, ElementList>, typename
00876                ExpandComposeElementList<ElementList>::List>::List Units;
00877   };
00878 
00879 }
00880 
00881 #endif /* _Unit_h */

Generated on Fri Dec 8 19:08:32 2006 for Quantity by doxygen 1.3.6