00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00045
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
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
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
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
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