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 - 2009, 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 // Quantity includes
00030 #include "Quantity/Prefix.h"
00031 
00032 // BSUtilities includes
00033 #include "BSUtilities/BSUtilities.h"
00034 #include "BSUtilities/TemplateTools.h"
00035 #include "BSUtilities/Conversion.h"
00036 
00037 // Loki includes
00038 #include "loki/NullType.h"
00039 #include "loki/EmptyType.h"
00040 #include "loki/TypeManip.h"
00041 #include "loki/Typelist.h"
00042 
00043 // STL includes
00044 #include <vector>
00045 #include <string>
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 
00147   };
00148 
00150 
00154 template<class BT> class Unit : public Units
00155   {
00156     public:
00158 
00160       virtual std::string name (void) const = 0;
00161 
00163 
00165       virtual std::string symbol (void) const = 0;
00166 
00168 
00170       virtual bool isSI (void) const = 0;
00171 
00172       virtual ~Unit () {}
00173 
00174   };
00175 
00177 //
00178 //  the NonPrefixable units
00179 //
00181 
00183 
00187 template<class BT, class U> 
00188   class NonPrefixable : public Unit<BT>
00189   {
00190     private:
00192       static const bool SI;
00193 
00195 
00197       static const std::string Namestring;
00198 
00200 
00202       static const std::string Symbolstring;
00203 
00204   public:
00206 
00210       static bool IsSI (void) {return SI;}
00211 
00213 
00215       bool isSI (void) const {return IsSI ();}
00216 
00218 /*  direct static access to be used if type of unit is known at 
00219     compile time; returns the namestring;
00220     must not be a static const data member, since similar functions
00221     in other cases of units require access to possibly not yet defined
00222     static data.
00223 */
00224       static std::string Name (void) {return Namestring;}
00225 
00227 
00230       std::string name (void) const {return Name ();}
00231 
00233 /*  direct static access to be used if type of unit is known at 
00234     compile time; 
00235     must not be a static const data member, since similar functions
00236     in other cases of units require access to possibly not yet defined
00237     static data.
00238 */
00239       static std::string Symbol (void) {return Symbolstring;}
00240 
00242 
00245       std::string symbol (void) const {return Symbol ();}
00246 
00247   };
00248 
00250 //
00251 //  the Prefixable and Prefixed units
00252 //
00254 
00255 // forward declaration
00256 template<class BT, class U> class Prefixable;
00257 
00259 
00262 template<class BP, class UP = No> class Prefixed;
00263 
00265 
00270 template<class BT, class U, class UP> 
00271   class Prefixed<Prefixable<BT, U>, UP> : public Prefixable<BT, U>
00272   {
00273     public:
00275 /*  direct static access to be used if type of unit is known at 
00276     compile time; 
00277     get name from prefix and prepend to basename which is inherited
00278     from Prefixable<BT, U>;
00279     must not be a static const data member, since similar functions
00280     in other cases of units require access to possibly not yet defined
00281     static data.
00282 */
00283       static std::string Name (void) 
00284                       {return UP::Name + Prefixable<BT, U>::Basename;}
00285 
00287 
00290       std::string name (void) const {return Name ();}
00291 
00293 /*  direct static access to be used if type of unit is known at 
00294     compile time; 
00295     get symbol from prefix and prepend to basesymbol which is inherited
00296     from Prefixable<BT, U>
00297     must not be a static const data member, since similar functions
00298     in other cases of units require access to possibly not yet defined
00299     static data.
00300 */
00301       static std::string Symbol (void) 
00302                   {return UP::Symbol + Prefixable<BT, U>::Basesymbol;}
00303 
00305 
00308       std::string symbol (void) const {return Symbol ();}
00309 
00310   };
00311 
00313 
00320 template<class BT, class U> class Prefixable : public Unit<BT>
00321   {
00322     private:
00324 
00326       static const bool SI;
00327 
00328     public:
00330       typedef Loki::Typelist<Prefixed<Prefixable<BT, U>, Yotta>, 
00331               Loki::Typelist<Prefixed<Prefixable<BT, U>, Zetta>, 
00332               Loki::Typelist<Prefixed<Prefixable<BT, U>, Exa>, 
00333               Loki::Typelist<Prefixed<Prefixable<BT, U>, Peta>, 
00334               Loki::Typelist<Prefixed<Prefixable<BT, U>, Tera>, 
00335               Loki::Typelist<Prefixed<Prefixable<BT, U>, Giga>, 
00336               Loki::Typelist<Prefixed<Prefixable<BT, U>, Mega>, 
00337               Loki::Typelist<Prefixed<Prefixable<BT, U>, Kilo>, 
00338               Loki::Typelist<Prefixed<Prefixable<BT, U>, Hecto>, 
00339               Loki::Typelist<Prefixed<Prefixable<BT, U>, Deca>, 
00340               Loki::Typelist<Prefixed<Prefixable<BT, U>, No>, 
00341               Loki::Typelist<Prefixed<Prefixable<BT, U>, Deci>, 
00342               Loki::Typelist<Prefixed<Prefixable<BT, U>, Centi>, 
00343               Loki::Typelist<Prefixed<Prefixable<BT, U>, Milli>, 
00344               Loki::Typelist<Prefixed<Prefixable<BT, U>, Micro>, 
00345               Loki::Typelist<Prefixed<Prefixable<BT, U>, Nano>, 
00346               Loki::Typelist<Prefixed<Prefixable<BT, U>, Pico>, 
00347               Loki::Typelist<Prefixed<Prefixable<BT, U>, Femto>, 
00348               Loki::Typelist<Prefixed<Prefixable<BT, U>, Atto>, 
00349               Loki::Typelist<Prefixed<Prefixable<BT, U>, Zepto>, 
00350               Loki::Typelist<Prefixed<Prefixable<BT, U>, Yocto>, 
00351               Loki::NullType> > > > > > > > > > > > > > > > > > > > > 
00352                                                                   Units;
00353 
00355 
00359       static bool IsSI (void) {return SI;}
00360 
00362 
00364       bool isSI (void) const {return IsSI ();}
00365 
00366     protected:
00368 /*  direct static access to be used if type of unit is known at 
00369     compile time 
00370 */
00371       static const std::string Basename;
00372 
00374 /*  direct static access to be used if type of unit is known at 
00375     compile time 
00376 */
00377       static const std::string Basesymbol;
00378 
00379   };
00380 
00382 //
00383 //  the ComposeBase and Composed units with helper classes and structs
00384 //  ComposeElement, ComposedSI, ComposedStrings
00385 //
00387 
00389 template<class BT, class CEL> class ComposeBase;
00390 
00392 
00395 template<class BC, class CUL> class Composed;
00396 
00398 
00403 template<class BT, class UL, class R> struct ComposeElement;
00404 
00406 
00412 template<class BT, class BT1, class U, class UTail, long N, long D>
00413   struct 
00414     ComposeElement<BT, Loki::Typelist<NonPrefixable<BT1, U>, UTail>,
00415                                            BSUtilities::Rational<N, D> >
00416   {
00417     private:
00418       typedef typename CheckUnits<Unit<BT1>, 
00419             Loki::Typelist<NonPrefixable<BT1, U>, UTail> >::Check Check;
00420 
00421     public:
00422       typedef Loki::Typelist<NonPrefixable<BT1, U>, UTail> Units;
00423       typedef BSUtilities::Rational<N, D> Power;
00424   };
00425 
00427 
00433 template<class BT, class BT1, class U, class UP, class UTail, 
00434                                                          long N, long D>
00435   struct ComposeElement<BT,
00436     Loki::Typelist<Prefixed<Prefixable<BT1, U>, UP>, UTail>, 
00437                                            BSUtilities::Rational<N, D> >
00438   {
00439     private:
00440       typedef typename CheckUnits<Unit<BT1>, 
00441             Loki::Typelist<Prefixed<Prefixable<BT1, U>, UP>, UTail> >
00442                                                           ::Check Check;
00443 
00444     public:
00445       typedef Loki::Typelist<Prefixed<Prefixable<BT1, U>, UP>, UTail>
00446                                                                   Units;
00447       typedef BSUtilities::Rational<N, D> Power;
00448   };
00449 
00451 
00457 template<class BT, class BT1, class CEL, class CUL, 
00458                                             class UTail, long N, long D>
00459   struct ComposeElement<BT,
00460     Loki::Typelist<Composed<ComposeBase<BT1, CEL>, CUL>, UTail>, 
00461                                            BSUtilities::Rational<N, D> >
00462   {
00463     private:
00464       typedef typename CheckUnits<Unit<BT1>, 
00465         Loki::Typelist<Composed<ComposeBase<BT1, CEL>, CUL>, UTail> >
00466                                                           ::Check Check;
00467 
00468     public:
00469       typedef Loki::Typelist<Composed<ComposeBase<BT1, CEL>, CUL>, 
00470                                                            UTail> Units;
00471       typedef BSUtilities::Rational<N, D> Power;
00472   };
00473 
00475 
00477 template<class UL> struct ComposedSI;
00478 
00480 
00484 template<class U, class UTail>
00485   struct ComposedSI<Loki::Typelist<U, UTail> >
00486   {
00491     static bool isSI (void) 
00492         {return ((U::IsSI () && ComposedSI<UTail>::isSI ()) ? 1 : 0);}
00493 
00494   };
00495   
00499 template<>
00500   struct ComposedSI<Loki::NullType>
00501   {
00502     static bool isSI (void) {return true;}
00503   };
00504 
00506 
00509 template<class UL, class RL> struct ComposedStrings;
00510 
00512 
00516 template<class U, class UTail, long N, long D, class RTail>
00517   struct ComposedStrings<Loki::Typelist<U, UTail>, 
00518                     Loki::Typelist<BSUtilities::Rational<N, D>, RTail> >
00519   {
00520       static const std::string Name (void)
00521         {return U::Name ()
00522           + "^(" + BSUtilities::Conversion<long>::to_string(N) 
00523               + "/" + BSUtilities::Conversion<long>::to_string(D) + ")"
00524                               + ComposedStrings<UTail, RTail>::Name ();}
00525 
00526       static const std::string Symbol (void)
00527         {return U::Symbol ()
00528           + "^(" + BSUtilities::Conversion<long>::to_string(N) 
00529               + "/" + BSUtilities::Conversion<long>::to_string(D) + ")"
00530                             + ComposedStrings<UTail, RTail>::Symbol ();}
00531 
00532   };
00533 
00535 
00537 template<class U, class UTail, long N, class RTail>
00538   struct ComposedStrings<Loki::Typelist<U, UTail>, 
00539                    Loki::Typelist<BSUtilities::Rational<N, 1L>, RTail> >
00540   {
00541       static const std::string Name (void)
00542         {return U::Name ()
00543           + "^" + BSUtilities::Conversion<long>::to_string(N) 
00544                               + ComposedStrings<UTail, RTail>::Name ();}
00545 
00546       static const std::string Symbol (void)
00547         {return U::Symbol ()
00548           + "^" + BSUtilities::Conversion<long>::to_string(N) + " "
00549                             + ComposedStrings<UTail, RTail>::Symbol ();}
00550 
00551   };
00552 
00554 
00556 template<class U, class UTail, class RTail>
00557   struct ComposedStrings<Loki::Typelist<U, UTail>, 
00558                   Loki::Typelist<BSUtilities::Rational<1L, 1L>, RTail> >
00559   {
00560       static const std::string Name (void)
00561         {return U::Name () + ComposedStrings<UTail, RTail>::Name ();}
00562 
00563       static const std::string Symbol (void)
00564         {return U::Symbol () + " "
00565                             + ComposedStrings<UTail, RTail>::Symbol ();}
00566 
00567   };
00568 
00570 
00572 template<class U, long N, long D>
00573   struct ComposedStrings<Loki::Typelist<U, Loki::NullType>, 
00574            Loki::Typelist<BSUtilities::Rational<N, D>, Loki::NullType> >
00575   {
00576       static const std::string Name (void)
00577        {return U::Name ()
00578          + "^(" + BSUtilities::Conversion<long>::to_string(N) 
00579              + "/" + BSUtilities::Conversion<long>::to_string(D) + ")";}
00580 
00581       static const std::string Symbol (void)
00582        {return U::Symbol ()
00583          + "^(" + BSUtilities::Conversion<long>::to_string(N) 
00584              + "/" + BSUtilities::Conversion<long>::to_string(D) + ")";}
00585 
00586   };
00587 
00589 
00592 template<class U, long N>
00593   struct ComposedStrings<Loki::Typelist<U, Loki::NullType>, 
00594               Loki::Typelist<BSUtilities::Rational<N>, Loki::NullType> >
00595   {
00596       static const std::string Name (void)
00597        {return U::Name ()
00598          + "^" + BSUtilities::Conversion<long>::to_string(N);}
00599 
00600       static const std::string Symbol (void)
00601        {return U::Symbol ()
00602          + "^" + BSUtilities::Conversion<long>::to_string(N);}
00603 
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 bool IsSI (void) {return ComposedSI<UL>::isSI ();}
00628 
00630 
00632       bool 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       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       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 Mon Jul 27 15:55:45 2009 for Quantities by  doxygen 1.5.3