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

Quantity.h

Go to the documentation of this file.
00001 
00005 /* Copyright (C) 2002 - 2004, Bernd Speiser */
00006 /* This file is part of Quantity.
00007 
00008 Quantity 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 Quantity 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 #ifndef _Quantity_h
00025 #define _Quantity_h
00026 
00027 #include "Quantity/Unit.h"
00028 #include "Quantity/Dimension.h"
00029 
00030 #include "BSUtilities.h"
00031 #include "Conversion.h"
00032 
00033 #include "Singleton.h"
00034 #include "NullType.h"
00035 
00036 #include <iostream>
00037 #include <string>
00038 
00040 namespace Quantities {
00041 
00043 //
00044 //  Helper classes and structs which store and/or check 
00045 //  specific units or lists of units.
00046 //
00048 
00050 
00053 class UnitMismatch {};
00054 
00056 
00058 class InputError {};
00059 
00061 
00070 template<class GT, class UL, class DU, class ST = double>
00071   class FindBySymbol
00072   {
00073     public:
00075       static Units::Unit<GT, ST> *result (const std::string &unitstring)
00076         {if (UL::Head::Symbol () == unitstring)
00077            return new typename UL::Head;
00078          else
00079            return FindBySymbol<GT, 
00080                        typename UL::Tail, DU, ST>::result (unitstring);
00081         }
00082   };
00083 
00085 
00089 template<class GT, class DU, class ST>
00090   class FindBySymbol<GT, Loki::NullType, DU, ST>
00091   {
00092     public:
00094 
00097       static Units::Unit<GT, ST> *result (const std::string &)
00098         {throw UnitMismatch (); return 0;}
00099   };
00100 
00101 
00103 
00105 template<class GT, class UL, class ST = double>
00106   class ListUnitSymbols
00107   {
00108     public:
00110 
00114     static std::vector<std::string> & result 
00115                                 (std::vector<std::string> &stringvector)
00116       {
00117        stringvector.push_back (UL::Head::Symbol ());
00118        return ListUnitSymbols<GT, typename UL::Tail, ST>::result 
00119                                                          (stringvector);
00120       }
00121   };
00122 
00124 
00126 template<class GT, class ST>
00127   class ListUnitSymbols<GT, Loki::NullType, ST>
00128   {
00129     public:
00131     static std::vector<std::string> & result 
00132                                 (std::vector<std::string> &stringvector)
00133       {
00134         return stringvector;
00135       }
00136   };
00137 
00144 template<class GT, class UL, class DU, class ST = double>
00145   class AllUnits
00146   {
00147     private:
00149 
00151       typedef 
00152         typename Units::CheckUnits<Units::Unit<GT, ST>, UL>::Checked 
00153                                                                 Checked;
00154 
00155     public:
00157       typedef UL Units;
00158 
00160 
00166       static ::Units::Unit<GT, ST> *unit (const std::string &unitstring)
00167         {return FindBySymbol<GT, UL, DU, ST>::result (unitstring);}
00168 
00170 
00173       static std::vector<std::string> allsymbols (void)
00174         {std::vector<std::string> stringvector;
00175          return ListUnitSymbols<GT, UL, ST>::result (stringvector);
00176         }
00177   };
00178 
00180 
00183 template<class GT, class U, class ST = double>
00184   class DefaultUnit
00185   {
00186     private:
00188 
00190       typedef 
00191         typename Units::CheckUnit<Units::Unit<GT, ST>, U>::Check 
00192                                                                 Checked;
00193 
00194     public:
00196       typedef U Unit;
00197   };
00198 
00200 
00202 template<bool>
00203   struct DimensionError;
00204 
00206 
00211 template<>
00212   struct DimensionError<false>
00213     {
00215 
00217        static const bool RET = true;
00218     };
00219 
00221 
00225 template<class Q>
00226   struct CheckDimensionality
00227   {
00228     public: 
00230 
00232       static const bool RET =
00233         BSUtilities::IF<Q::D::IsDimensionless, DimensionError<false>, 
00234                                        DimensionError<true> >::RET::RET;
00235   };
00236 
00238 template<class U, class TL> struct CheckAgainstAllUnits;
00239 
00241 
00249 template<class U, class Head, class Tail> 
00250   struct CheckAgainstAllUnits<U, Loki::Typelist<Head, Tail> >
00251   {
00252     typedef 
00253       typename BSUtilities::IF<BSUtilities::SameType<U, Head>::sameType,
00254               U, typename CheckAgainstAllUnits<U, Tail>::RET >::RET RET;
00255   };
00256 
00258 
00265 template<class U>
00266   struct CheckAgainstAllUnits<U, Loki::NullType>
00267   {
00268     typedef Units::UnitError<true> RET;
00269   };
00270   
00272 //
00273 //  helper classes for input and output
00274 //
00276 
00278 
00280 template<bool P> class PrintName;
00282 
00284 template<bool P> class PrintSymbol;
00285 
00287 class PrintStatus
00288   {
00289     private:
00291       static bool _name;
00293       static bool _symbol;
00294 
00295     public:
00297 
00299       bool name (void) const {return _name;}
00301 
00303       bool symbol (void) const {return _symbol;}
00304 
00306       template<bool P> friend class PrintName;
00307 
00309       template<bool P> friend class PrintSymbol;
00310   };
00311 
00313 typedef Loki::SingletonHolder<PrintStatus> PrintStatusHolder;
00314 
00315 #define PS PrintStatusHolder::Instance()
00316 
00318 
00321 template<bool P>
00322   class PrintName
00323   {
00325 
00328     void set (bool name) const {PrintStatus::_name = name;}
00329 
00331 
00337     friend std::ostream & operator<< 
00338                               (std::ostream &os, const PrintName &print)
00339            {print.set (P); return os;}
00340   };
00341 
00343 
00346 template<bool P>
00347   class PrintSymbol
00348   {
00350 
00353     void set (bool symbol) const {PrintStatus::_symbol = symbol;}
00354 
00356 
00362     friend std::ostream & operator<< 
00363                            (std::ostream &os, const PrintSymbol &print)
00364            {print.set (P); return os;}
00365 
00366   };
00367 
00369 
00371 template<bool P> class ReadName;
00372 
00374 
00376 template<bool P> class ReadSymbol;
00377 
00379 
00381 template<bool P> class ReadEqual;
00382 
00384 class ReadStatus
00385   {
00386     private:
00388       static bool _name;
00389 
00391       static bool _symbol;
00392 
00394       static bool _equal;
00395 
00397 
00400       static std::string _unit;
00401 
00402     public:
00404 
00406       bool name (void) const {return _name;}
00407 
00409 
00411       bool symbol (void) const {return _symbol;}
00412 
00414 
00416       bool equal (void) const {return _equal;}
00417 
00419 
00421       std::string unit (void) const {return _unit;}
00422 
00424       template<bool P> friend class ReadName;
00425 
00427       template<bool P> friend class ReadSymbol;
00428 
00430       template<bool P> friend class ReadEqual;
00431 
00433       template<class U> friend class ReadUnit;
00434   };
00435 
00437 typedef Loki::SingletonHolder<ReadStatus> ReadStatusHolder;
00438 
00439 #define RS ReadStatusHolder::Instance()
00440 
00442 
00445 template<bool P>
00446   class ReadName
00447   {
00449 
00452     void set (bool name) const {ReadStatus::_name = name;}
00453 
00455 
00461     friend std::istream & operator>> 
00462                               (std::istream &is, const ReadName &read)
00463            {read.set (P); return is;}
00464   };
00465 
00467 
00470 template<bool P>
00471   class ReadSymbol
00472   {
00474 
00477     void set (bool symbol) const {ReadStatus::_symbol = symbol;}
00478 
00480 
00486     friend std::istream & operator>> 
00487                            (std::istream &is, const ReadSymbol &read)
00488            {read.set (P); return is;}
00489 
00490   };
00491 
00493 
00496 template<bool P>
00497   class ReadEqual
00498   {
00500 
00503     void set (bool equal) const {ReadStatus::_equal = equal;}
00504 
00506 
00512     friend std::istream & operator>> 
00513                               (std::istream &is, const ReadEqual &read)
00514            {read.set (P); return is;}
00515 
00516   };
00517 
00519 
00521 template<class U>
00522   class ReadUnit
00523   {
00525 
00528     void set (std::string unit) const {ReadStatus::_unit = unit;}
00529 
00531 
00538     friend std::istream & operator>> 
00539                            (std::istream &is, const ReadUnit<U> &unit)
00540            {unit.set (U::Symbol ()); return is;}
00541 
00542   };
00543 
00544 typedef Loki::NullType NoUnit;
00545 
00547 
00549 template<>
00550   class ReadUnit<NoUnit>
00551   {
00553 
00556     void set (std::string unit) const {ReadStatus::_unit = unit;}
00557 
00559 
00565     friend std::istream & operator>> 
00566                       (std::istream &is, const ReadUnit<NoUnit> &unit)
00567            {unit.set (""); return is;}
00568 
00569   };
00570 
00571 
00573 //
00574 //  the Quantities base class
00575 //
00577 
00579 
00581 class Quantities
00582   {
00583     public:
00585 
00587       static std::string version (void)
00588         {static const 
00589           std::string v_string ("Quantities version 1.0 with ");
00590              return v_string + ::Units::Units::version () + ", " 
00591                    + ::Dimensions::Dimensions::version () + 
00592                        " and " + ::BSUtilities::version ();}
00593 
00595 
00597       virtual const std::string unitsymbol (void) const = 0;
00598 
00600 
00602       virtual const std::string unitname (void) const = 0;
00603 
00605 
00607       virtual const bool isDimensionless (void) const = 0;
00608 
00610 
00613       virtual ~Quantities (void) {}
00614 
00615   };
00616 
00618 //
00619 //  the Quantity base class
00620 //
00622 
00624 
00628 template<class GT, class UL, class DU, class ST = double> 
00629                                                          class Quantity;
00630 
00632 template <class Q> struct Name;
00633 
00635 template<class GT, class Head, class Tail, class DU, class ST>
00636   struct Name<Quantity<GT, Loki::Typelist<Head, Tail>, DU, ST> >
00637   {
00639 
00641     static const std::string String;
00642   };
00643 
00645 template <class Q> struct Symbol;
00646 
00648 template<class GT, class Head, class Tail, class DU, class ST>
00649   struct Symbol<Quantity<GT, Loki::Typelist<Head, Tail>, DU, ST> >
00650   {
00652 
00654     static const std::string String;
00655   };
00656 
00658 
00666 template<class GT, class Head, class Tail, class DU, class ST>
00667   class Quantity<GT, Loki::Typelist<Head, Tail>, DU, ST> 
00668                                                      : public Quantities
00669   {
00670     private:
00672       typedef 
00673            Name<Quantity<GT, Loki::Typelist<Head, Tail>, DU, ST> > Name;
00675       typedef Symbol<Quantity<GT, Loki::Typelist<Head, Tail>, DU, ST> > 
00676                                                                  Symbol;
00677 
00678     public:
00680 
00682       typedef Dimensions::Dimension<GT> D;
00683 
00685       typedef GT Type;
00686 
00688       typedef ST SType;
00689 
00690     protected:
00692 
00694       std::string namestring;
00696 
00698       std::string symbolstring;
00699 
00701 
00703       Units::Unit<GT, ST> * findBySymbol (const std::string &unitsymbol)
00704          {return FindBySymbol<GT, Loki::Typelist<Head, Tail>, DU, ST>
00705                                                  ::result (unitsymbol);}
00706 
00707     public:
00709 
00712       Quantity (void) 
00713          : namestring (Name::String), symbolstring (Symbol::String) {}
00714 
00716 
00719       virtual ~Quantity (void) {}
00720 
00722 
00725       typedef AllUnits<GT, Loki::Typelist<Head, Tail>, ST> AllUnits;
00726 
00728 
00731       typedef DefaultUnit<GT, DU, ST> DefaultUnit;
00732 
00734       std::string name (void) const {return namestring;}
00736       std::string symbol (void) const {return symbolstring;}
00737 
00739       void name (const std::string &name) {namestring = name;}
00741       void symbol (const std::string &symbol) {symbolstring = symbol;}
00742 
00744 
00746       virtual ST standard_value (void) const = 0;
00747 
00749 
00751       virtual ST value (void) const = 0;
00752 
00754 
00756       static const bool IsDimensionless = D::IsDimensionless;
00757 
00759 
00761       const bool isDimensionless (void) const {return IsDimensionless;}
00762 
00764 
00766       struct Dummy;
00767 
00769 
00774       struct Exp {static ST exec (const Quantity &quantity) 
00775                               {return ST(std::exp (quantity.value ()));}
00776                  };
00777 
00779 
00784       friend ST exp (const Quantity &quantity)
00785         {
00786           return ST(BSUtilities::IF<CheckDimensionality<Quantity>::RET,
00787                       Exp, Dummy>::RET::exec (quantity));
00788         }
00789 
00791 
00796       struct Log {static ST exec (const Quantity &quantity) 
00797                      {return ST(std::log (quantity.value ()));}
00798                  };
00799 
00801 
00806       friend ST log (const Quantity &quantity)
00807         {
00808           return ST(BSUtilities::IF<CheckDimensionality<Quantity>::RET,
00809                       Log, Dummy>::RET::exec (quantity));
00810         }
00811 
00813 
00818       struct Log10 {static ST exec (const Quantity &quantity) 
00819                             {return ST(std::log10 (quantity.value ()));}
00820                  };
00821 
00823 
00828       friend ST log10 (const Quantity &quantity)
00829         {
00830           return ST(BSUtilities::IF<CheckDimensionality<Quantity>::RET,
00831                       Log10, Dummy>::RET::exec (quantity));
00832         }
00833 
00835 
00840       struct Sin {static ST exec (const Quantity &quantity) 
00841                               {return ST(std::sin (quantity.value ()));}
00842                  };
00843 
00845 
00857       friend ST sin (const Quantity &quantity)
00858         {
00859           return ST(BSUtilities::IF<CheckDimensionality<Quantity>::RET,
00860                       Sin, Dummy>::RET::exec (quantity));
00861         }
00862 
00864 
00869       struct Cos {static ST exec (const Quantity &quantity) 
00870                               {return ST(std::cos (quantity.value ()));}
00871                  };
00872 
00874 
00879       friend ST cos (const Quantity &quantity)
00880         {
00881           return ST(BSUtilities::IF<CheckDimensionality<Quantity>::RET,
00882                       Cos, Dummy>::RET::exec (quantity));
00883         }
00884 
00886 
00891       struct Tan {static ST exec (const Quantity &quantity) 
00892                               {return ST(std::tan (quantity.value ()));}
00893                  };
00894 
00896 
00901       friend ST tan (const Quantity &quantity)
00902         {
00903           return ST(BSUtilities::IF<CheckDimensionality<Quantity>::RET,
00904                       Tan, Dummy>::RET::exec (quantity));
00905         }
00906 
00908 
00913       struct Sinh {static ST exec (const Quantity &quantity) 
00914                              {return ST(std::sinh (quantity.value ()));}
00915                  };
00916 
00918 
00923       friend ST sinh (const Quantity &quantity)
00924         {
00925           return ST(BSUtilities::IF<CheckDimensionality<Quantity>::RET,
00926                       Sinh, Dummy>::RET::exec (quantity));
00927         }
00928 
00930 
00935       struct Cosh {static ST exec (const Quantity &quantity) 
00936                              {return ST(std::cosh (quantity.value ()));}
00937                  };
00938 
00940 
00945       friend ST cosh (const Quantity &quantity)
00946         {
00947           return ST(BSUtilities::IF<CheckDimensionality<Quantity>::RET,
00948                       Cosh, Dummy>::RET::exec (quantity));
00949         }
00950 
00952 
00957       struct Tanh {static ST exec (const Quantity &quantity) 
00958                              {return ST(std::tanh (quantity.value ()));}
00959                  };
00960 
00962 
00967       friend ST tanh (const Quantity &quantity)
00968         {
00969           return ST(BSUtilities::IF<CheckDimensionality<Quantity>::RET,
00970                       Tanh, Dummy>::RET::exec (quantity));
00971         }
00972 
00974 
00979       struct Asin {static ST exec (const Quantity &quantity) 
00980                              {return ST(std::asin (quantity.value ()));}
00981                  };
00982 
00984 
00989       friend ST asin (const Quantity &quantity)
00990         {
00991           return ST(BSUtilities::IF<CheckDimensionality<Quantity>::RET,
00992                       Asin, Dummy>::RET::exec (quantity));
00993         }
00994 
00996 
01001       struct Acos {static ST exec (const Quantity &quantity) 
01002                              {return ST(std::acos (quantity.value ()));}
01003                  };
01004 
01006 
01011       friend ST acos (const Quantity &quantity)
01012         {
01013           return ST(BSUtilities::IF<CheckDimensionality<Quantity>::RET,
01014                       Acos, Dummy>::RET::exec (quantity));
01015         }
01016 
01018 
01023       struct Atan {static ST exec (const Quantity &quantity) 
01024                              {return ST(std::atan (quantity.value ()));}
01025                  };
01026 
01028 
01033       friend ST atan (const Quantity &quantity)
01034         {
01035           return ST(BSUtilities::IF<CheckDimensionality<Quantity>::RET,
01036                       Atan, Dummy>::RET::exec (quantity));
01037         }
01038 
01040 
01045       struct Atan2 {static ST exec 
01046                   (const Quantity &quantity, const Quantity & quantity2)
01047         {return ST(std::atan2 
01048             (quantity.standard_value (), quantity2.standard_value ()));}
01049         };
01050 
01052 
01054       friend ST atan2 
01055         (const Quantity<GT, Loki::Typelist<Head, Tail>, DU, ST> 
01056                                                               &quantity,
01057            const Quantity<GT, Loki::Typelist<Head, Tail>, DU, ST> 
01058                                                              &quantity2)
01059         {return ST(Atan2::exec (quantity, quantity2));}
01060 
01062 
01067       friend std::ostream & operator<< 
01068                             (std::ostream &os, const Quantity &quantity)
01069              {return quantity.print (os);}
01070 
01072 
01086       std::ostream & print (std::ostream &os) const
01087         {
01088           std::string name (""); 
01089           std::string symbol ("");
01090           std::string equal ("");
01091 
01092           if (PS.name ())
01093             name = namestring + " ";
01094 
01095           if (PS.symbol ())
01096             symbol = symbolstring + " ";
01097 
01098           if (PS.name () || PS.symbol ())
01099             equal = "= ";
01100 
01101           os << name << symbol << equal;
01102 
01103           return print_value (os);
01104         }
01105 
01107 
01110       virtual std::ostream & print_value (std::ostream &os) const = 0;
01111 
01113       friend void operator<< 
01114         (std::string &str, const Quantity &quantity) {quantity >> str;}
01115 
01117       virtual void operator>> (std::string &str) const = 0;
01118 
01120 
01123       operator std::string () const 
01124         {std::string string; *this >> string; return string;}
01125 
01126       virtual std::ostream & operator>> (std::ostream &os) const = 0;
01127 
01128   };
01129 
01131 //
01132 //  helper classes which use the Quantity template
01133 //
01135 
01137 
01139 template<class Q1, class Q2> struct SameDimensioned;
01140 
01142 
01152 template<template<class, class> class Q1, class GT1, class Head1, 
01153            class Tail1, class DU1, class U1, class ST1,
01154          template<class, class> class Q2, class GT2, class Head2, 
01155            class Tail2, class DU2, class U2, class ST2>
01156   struct SameDimensioned
01157     <Q1<Quantity<GT1, Loki::Typelist<Head1, Tail1>, DU1, ST1>, U1>, 
01158          Q2<Quantity<GT2, Loki::Typelist<Head2, Tail2>, DU2, ST2>, U2> >
01159   {
01160     enum {RET 
01161       = Dimensions::Equal<Dimensions::Dimension<GT1>, 
01162                                      Dimensions::Dimension<GT2> >::RET};
01163   };
01164 
01166 
01171 template<class Q1, class Q2> struct CheckSecondDimension;
01172 
01173 template<template<class, class> class Q1, class GT1, class Head1, 
01174            class Tail1, class DU1, class U1, class ST1,
01175          template<class, class> class Q2, class GT2, class Head2, 
01176            class Tail2, class DU2, class U2, class ST2>
01177   struct CheckSecondDimension
01178     <Q1<Quantity<GT1, Loki::Typelist<Head1, Tail1>, DU1, ST1>, U1>, 
01179          Q2<Quantity<GT2, Loki::Typelist<Head2, Tail2>, DU2, ST2>, U2> >
01180   {
01181     private:
01182       typedef 
01183         Q1<Quantity<GT1, Loki::Typelist<Head1, Tail1>, DU1, ST1>, U1> 
01184                                                                  Quant1;
01185       typedef 
01186         Q2<Quantity<GT2, Loki::Typelist<Head2, Tail2>, DU2, ST2>, U2> 
01187                                                                  Quant2;
01188 
01189     public:
01190       typedef 
01191         typename BSUtilities::IF<SameDimensioned<Quant1, Quant2>::RET, 
01192                                 Quant2, DimensionError<true> >::RET RET;
01193   };
01194 
01195 }
01196 
01197 #endif /* _Quantity_h */

Generated on Sun Jan 15 13:58:00 2006 for Quantity by doxygen 1.3.6