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
00028 #include "version.h"
00029 #include "Quantity/Unit.h"
00030 #include "Quantity/Dimension.h"
00031 #include "Quantity/QuantityError.h"
00032
00033
00034 #include "BSUtilities/BSUtilities.h"
00035 #include "BSUtilities/TypeToName.h"
00036 #include "BSUtilities/Conversion.h"
00037
00038
00039 #include "loki/Singleton.h"
00040
00041
00042 #include <iostream>
00043 #include <string>
00044 #include <cmath>
00045
00046 #include <typeinfo>
00047
00048
00049 #include <boost/serialization/serialization.hpp>
00050 #include <boost/serialization/nvp.hpp>
00051 #include <boost/serialization/is_abstract.hpp>
00052
00054 namespace quantity {
00055
00057
00059
00061
00077 template<typename Q> struct QuantityTraits;
00078
00080
00082
00083
00085
00086
00087
00088
00090
00092
00101 template<typename UT, typename UL>
00102 class UnitPointerBySymbol
00103 {
00104 public:
00106 static unit::Unit<UT> *result (const std::string &symbol)
00107 {if (UL::Head::Symbol () == symbol)
00108 return new typename UL::Head;
00109 else
00110 return UnitPointerBySymbol<UT, typename UL::Tail>::result
00111 (symbol);
00112 }
00113 };
00114
00116
00120 template<typename UT>
00121 class UnitPointerBySymbol<UT, Loki::NullType>
00122 {
00123 public:
00125
00128 static unit::Unit<UT> *result (const std::string &)
00129 {throw UnitMismatch (); return 0;}
00130 };
00131
00133
00141 template<typename UL>
00142 class UnitIndexBySymbol
00143 {
00144 public:
00145 static int index (const std::string &symbol)
00146 {if (UL::Head::Symbol () == symbol)
00147 return 0;
00148 else
00149 return
00150 UnitIndexBySymbol<typename UL::Tail>::index (symbol) + 1;
00151 }
00152 };
00153
00155
00159 template<>
00160 class UnitIndexBySymbol<Loki::NullType>
00161 {
00162 public:
00164
00167 static int index (const std::string &)
00168 {throw UnitMismatch (); return -1;}
00169 };
00170
00172
00174 template<typename UL>
00175 class ListUnitSymbols
00176 {
00177 public:
00179
00183 static std::vector<std::string> & result
00184 (std::vector<std::string> &stringvector)
00185 {
00186 stringvector.push_back (UL::Head::Symbol ());
00187 return ListUnitSymbols<typename UL::Tail>::result (stringvector);
00188 }
00189 };
00190
00192
00194 template<>
00195 class ListUnitSymbols<Loki::NullType>
00196 {
00197 public:
00199 static std::vector<std::string> & result
00200 (std::vector<std::string> &stringvector)
00201 {
00202 return stringvector;
00203 }
00204 };
00205
00212 template<typename UT, typename UL>
00213 class AllUnitsTemplate
00214 {
00215 private:
00217
00219 typedef
00220 typename unit::CheckUnits<unit::Unit<UT>, UL>::Check Check;
00221
00222 public:
00224 typedef UL Units;
00225
00227
00235 static ::unit::Unit<UT> *unit (const std::string &unitstring)
00236 {return UnitPointerBySymbol<UT, UL>::result (unitstring);}
00237
00239
00242 static std::vector<std::string> allsymbols (void)
00243 {std::vector<std::string> stringvector;
00244 return ListUnitSymbols<UL>::result (stringvector);
00245 }
00246 };
00247
00249
00252 template<typename UT, typename U>
00253 class DefaultUnitTemplate
00254 {
00255 private:
00257
00259 typedef
00260 typename unit::CheckUnit<unit::Unit<UT>, U>::Check Check;
00261
00262 public:
00264 typedef U Unit;
00265 };
00266
00268 template<class U, class TL> struct CheckAgainstAllUnits;
00269
00271
00279 template<typename U, typename Head, typename Tail>
00280 struct CheckAgainstAllUnits<U, Loki::Typelist<Head, Tail> >
00281 {
00282 typedef
00283 typename BSUtilities::IF<BSUtilities::SameType<U, Head>::sameType,
00284 U, typename CheckAgainstAllUnits<U, Tail>::RET >::RET RET;
00285 };
00286
00288
00295 template<typename U>
00296 struct CheckAgainstAllUnits<U, Loki::NullType>
00297 {
00298 typedef unit::UnitError<true> RET;
00299 };
00300
00302
00303
00304
00306
00308
00310 template<bool>
00311 struct DimensionError;
00312
00314
00318 template<>
00319 struct DimensionError<false>
00320 {
00322
00324 static const bool RET = true;
00325 };
00326
00328
00332 template<typename Q>
00333 struct CheckDimensionality
00334 {
00335 public:
00337
00339 static const bool RET =
00340 BSUtilities::IF<Q::Dim::IsDimensionless, DimensionError<false>,
00341 DimensionError<true> >::RET::RET;
00342 };
00343
00345
00347 template<typename Q1, typename Q2> struct SameDimensioned;
00348
00350
00351
00352
00354
00356
00358 template<bool P> class PrintName;
00360
00362 template<bool P> class PrintSymbol;
00363
00365 class PrintStatus
00366 {
00367 private:
00369 static bool _name;
00371 static bool _symbol;
00372
00373 public:
00375
00377 bool name (void) const {return _name;}
00379
00381 bool symbol (void) const {return _symbol;}
00382
00384 template<bool P> friend class PrintName;
00385
00387 template<bool P> friend class PrintSymbol;
00388 };
00389
00391 typedef Loki::SingletonHolder<PrintStatus> PrintStatusHolder;
00392
00393 #define PS PrintStatusHolder::Instance()
00394
00396
00399 template<bool P>
00400 class PrintName
00401 {
00403
00406 void set (bool name) const {PrintStatus::_name = name;}
00407
00409
00415 friend std::ostream & operator<<
00416 (std::ostream &os, const PrintName &print)
00417 {print.set (P); return os;}
00418 };
00419
00421
00424 template<bool P>
00425 class PrintSymbol
00426 {
00428
00431 void set (bool symbol) const {PrintStatus::_symbol = symbol;}
00432
00434
00440 friend std::ostream & operator<<
00441 (std::ostream &os, const PrintSymbol &print)
00442 {print.set (P); return os;}
00443
00444 };
00445
00447
00449 template<bool P> class ReadName;
00450
00452
00454 template<bool P> class ReadSymbol;
00455
00457
00459 template<bool P> class ReadEqual;
00460
00462 class ReadStatus
00463 {
00464 private:
00466 static bool _name;
00467
00469 static bool _symbol;
00470
00472 static bool _equal;
00473
00475
00478 static std::string _unit;
00479
00480 public:
00482
00484 bool name (void) const {return _name;}
00485
00487
00489 bool symbol (void) const {return _symbol;}
00490
00492
00494 bool equal (void) const {return _equal;}
00495
00497
00499 std::string unit (void) const {return _unit;}
00500
00502 template<bool P> friend class ReadName;
00503
00505 template<bool P> friend class ReadSymbol;
00506
00508 template<bool P> friend class ReadEqual;
00509
00511 template<class U> friend class ReadUnit;
00512 };
00513
00515 typedef Loki::SingletonHolder<ReadStatus> ReadStatusHolder;
00516
00517 #define RS ReadStatusHolder::Instance()
00518
00520
00523 template<bool P>
00524 class ReadName
00525 {
00527
00530 void set (bool name) const {ReadStatus::_name = name;}
00531
00533
00539 friend std::istream & operator>>
00540 (std::istream &is, const ReadName &read)
00541 {read.set (P); return is;}
00542 };
00543
00545
00548 template<bool P>
00549 class ReadSymbol
00550 {
00552
00555 void set (bool symbol) const {ReadStatus::_symbol = symbol;}
00556
00558
00564 friend std::istream & operator>>
00565 (std::istream &is, const ReadSymbol &read)
00566 {read.set (P); return is;}
00567
00568 };
00569
00571
00574 template<bool P>
00575 class ReadEqual
00576 {
00578
00581 void set (bool equal) const {ReadStatus::_equal = equal;}
00582
00584
00590 friend std::istream & operator>>
00591 (std::istream &is, const ReadEqual &read)
00592 {read.set (P); return is;}
00593
00594 };
00595
00597
00599 template<typename U>
00600 class ReadUnit
00601 {
00603
00606 void set (std::string unit) const {ReadStatus::_unit = unit;}
00607
00609
00616 friend std::istream & operator>>
00617 (std::istream &is, const ReadUnit<U> &unit)
00618 {unit.set (U::Symbol ()); return is;}
00619
00620 };
00621
00622 typedef Loki::NullType NoUnit;
00623
00625
00627 template<>
00628 class ReadUnit<NoUnit>
00629 {
00631
00634 void set (std::string unit) const {ReadStatus::_unit = unit;}
00635
00637
00643 friend std::istream & operator>>
00644 (std::istream &is, const ReadUnit<NoUnit> &unit)
00645 {unit.set (""); return is;}
00646
00647 };
00648
00649
00651
00652
00653
00655
00657
00659 class Quantities
00660 {
00661 public:
00663
00666 static std::string Version (void)
00667 {return QUANTITIES_VERSION;}
00668
00670
00673 static std::string version (void) {return Version ();}
00674
00676
00678 virtual std::string unitsymbol (void) const = 0;
00679
00681
00683 virtual std::string unitname (void) const = 0;
00684
00686
00688 virtual bool isDimensionless (void) const = 0;
00689
00691
00694 virtual ~Quantities (void) {}
00695
00696 };
00697
00699
00700
00701
00703
00705
00709 template<typename Q, typename ST = double> class Quantity;
00710
00712
00714 template<typename U, typename ST = double> struct Standard;
00715
00717
00722 template<typename UL, typename PL, typename ST = double> class CompStd;
00723
00725
00728 template<typename UT, typename U, typename CULTail, long N, long D,
00729 typename PTail, typename ST>
00730 class CompStd<Loki::Typelist<unit::NonPrefixable<UT, U>, CULTail>,
00731 Loki::Typelist<BSUtilities::Rational<N, D>, PTail>, ST>
00732 {
00733 public:
00734 static ST ratio (void)
00735 {return std::pow (Standard<unit::NonPrefixable<UT, U> >::ratio,
00736 static_cast<double>(N)/static_cast<double>(D))
00737 * CompStd<CULTail, PTail, ST>::ratio ();}
00738
00739 static bool exact (void)
00740 {return (Standard<unit::NonPrefixable<UT, U> >::exact
00741 && CompStd<CULTail, PTail, ST>::exact ());}
00742 };
00743
00745
00748 template<typename UT, typename U, typename P, typename CULTail,
00749 long N, long D, typename PTail, typename ST>
00750 class CompStd<Loki::Typelist<unit::Prefixed<
00751 unit::Prefixable<UT, U>, P>, CULTail>,
00752 Loki::Typelist<BSUtilities::Rational<N, D>, PTail>, ST>
00753 {
00754 public:
00755 static ST ratio (void)
00756 {return std::pow ((Standard<unit::Prefixable<UT, U> >::ratio
00757 * P::Factor), static_cast<double>(N)/static_cast<double>(D))
00758 * CompStd<CULTail, PTail, ST>::ratio ();}
00759
00760 static bool exact (void)
00761 {return (Standard<unit::Prefixable<UT, U> >::exact
00762 && CompStd<CULTail, PTail, ST>::exact ());}
00763 };
00764
00766
00769 template<typename UT, typename CEL, typename UL, typename CULTail,
00770 long N, long D, typename PTail, typename ST>
00771 class CompStd<Loki::Typelist<unit::Composed<
00772 unit::ComposeBase<UT, CEL>, UL>, CULTail>,
00773 Loki::Typelist<BSUtilities::Rational<N, D>, PTail>, ST>
00774 {
00775 public:
00776 static ST ratio (void)
00777 {return std::pow
00778 (Standard<unit::ComposeBase<UT, CEL> >::ratio,
00779 static_cast<double>(N)/static_cast<double>(D))
00780 * CompStd<CULTail, PTail, ST>::ratio ();}
00781 static bool exact (void)
00782 {return (Standard<unit::ComposeBase<UT, CEL> >::exact
00783 && CompStd<CULTail, PTail, ST>::exact ());}
00784 };
00785
00787
00790 template<typename UT, typename U, long N, long D, typename ST>
00791 class CompStd<Loki::Typelist<unit::NonPrefixable<UT, U>,
00792 Loki::NullType>, Loki::Typelist<BSUtilities::Rational<N, D>,
00793 Loki::NullType>, ST>
00794 {
00795 public:
00796 static ST ratio (void) {return std::pow
00797 (Standard<unit::NonPrefixable<UT, U> >::ratio,
00798 static_cast<double>(N)/static_cast<double>(D));}
00799
00800 static bool exact (void)
00801 {return Standard<unit::NonPrefixable<UT, U> >::exact;}
00802 };
00803
00805
00808 template<typename UT, typename U, typename P,
00809 long N, long D, typename ST>
00810 class CompStd<Loki::Typelist<unit::Prefixed<
00811 unit::Prefixable<UT, U>, P>, Loki::NullType>,
00812 Loki::Typelist<BSUtilities::Rational<N, D>, Loki::NullType>, ST>
00813 {
00814 public:
00815 static ST ratio (void) {return std::pow
00816 ((Standard<unit::Prefixable<UT, U> >::ratio * P::Factor),
00817 static_cast<double>(N)/static_cast<double>(D));}
00818
00819 static bool exact (void)
00820 {return Standard<unit::Prefixable<UT, U> >::exact;}
00821 };
00822
00824
00827 template<typename UT, typename CEL, typename UL,
00828 long N, long D, typename ST>
00829 class CompStd<Loki::Typelist<unit::Composed<
00830 unit::ComposeBase<UT, CEL>, UL>, Loki::NullType>,
00831 Loki::Typelist<BSUtilities::Rational<N, D>, Loki::NullType>, ST>
00832 {
00833 public:
00834 static ST ratio (void) {return std::pow
00835 (Standard<unit::ComposeBase<UT, CEL> >::ratio,
00836 static_cast<double>(N)/static_cast<double>(D));}
00837
00838 static bool exact (void)
00839 {return Standard<unit::ComposeBase<UT, CEL> >::exact;}
00840 };
00841
00843
00845 template<typename U, typename ST = double> struct Standardize;
00846
00848
00853 template<typename UT, typename U, typename ST>
00854 struct Standardize<unit::NonPrefixable<UT, U>, ST>
00855 {
00856 static ST VAL (const ST &value)
00857 {return value *
00858 Standard<unit::NonPrefixable<UT, U>, ST>::ratio;}
00859
00860 static bool Exact (void)
00861 {return Standard<unit::NonPrefixable<UT, U>, ST>::exact;}
00862 };
00863
00865
00870 template<typename UT, typename U, typename P, typename ST>
00871 struct Standardize<unit::Prefixed<unit::Prefixable<UT, U>, P>, ST>
00872 {
00873 static ST VAL (const ST &value)
00874 {return ST (value * P::Factor *
00875 Standard<unit::Prefixable<UT, U>, ST>::ratio);}
00876
00877 static bool Exact (void)
00878 {return Standard<unit::Prefixable<UT, U>, ST>::exact;}
00879 };
00880
00882
00887 template<typename UT, typename CUL, typename CEL, typename ST>
00888 struct Standardize<unit::Composed<unit::ComposeBase<UT, CEL>,
00889 CUL>, ST>
00890 {
00891 static ST VAL (const ST &value)
00892 {return ST (value * CompStd<CUL,
00893 typename unit::ComposeBase<UT, CEL>::Powers::Powers, ST>
00894 ::ratio () *
00895 Standard<unit::ComposeBase<UT, CEL>, ST>::ratio);}
00896
00897 static bool Exact (void)
00898 {return CompStd<CUL, typename
00899 unit::ComposeBase<UT, CEL>::Powers::Powers, ST>::exact ();}
00900 };
00901
00903
00905 template<typename U, typename ST = double> struct Reverse;
00906
00908
00913 template<typename UT, typename U, typename ST>
00914 struct Reverse<unit::NonPrefixable<UT, U>, ST>
00915 {
00916 static ST VAL (const ST &value)
00917 {return value /
00918 Standard<unit::NonPrefixable<UT, U>, ST>::ratio;}
00919
00920 static bool Exact (void)
00921 {return Standard<unit::NonPrefixable<UT, U>, ST>::exact;}
00922 };
00923
00925
00930 template<typename UT, typename U, typename P, typename ST>
00931 struct Reverse<unit::Prefixed<unit::Prefixable<UT, U>, P>, ST>
00932 {
00933 static ST VAL (const ST &value)
00934 {return ST (value / (P::Factor *
00935 Standard<unit::Prefixable<UT, U>, ST>::ratio));}
00936
00937 static bool Exact (void)
00938 {return Standard<unit::Prefixable<UT, U>, ST>::exact;}
00939 };
00940
00942
00947 template<typename UT, typename CUL, typename CEL, typename ST>
00948 struct Reverse<unit::Composed<unit::ComposeBase<UT, CEL>, CUL>,
00949 ST>
00950 {
00951 static ST VAL (const ST &value)
00952 {return
00953 ST (value / (CompStd<CUL,
00954 typename unit::ComposeBase<UT, CEL>::Powers::Powers,
00955 ST>::ratio () *
00956 Standard<unit::ComposeBase<UT, CEL>, ST>::ratio));}
00957
00958 static bool Exact (void)
00959 {return CompStd<CUL, typename
00960 unit::ComposeBase<UT, CEL>::Powers::Powers, ST>::exact ();}
00961 };
00962
00964
00966 template<typename UL> struct dynamic_standardize;
00967
00969
00976 template<typename Head, typename Tail>
00977 struct dynamic_standardize<Loki::Typelist<Head, Tail> >
00978 {
00979 template<class U, class ST>
00980 static ST VAL (const ST &value, const U &unit)
00981 {Head test = Head ();
00982 if (typeid(unit) == typeid(test))
00983 return Standardize<Head, ST>::VAL (value);
00984 else
00985 return dynamic_standardize<Tail>::VAL (value, unit);
00986 }
00987 };
00988
00990
00992 template<>
00993 struct dynamic_standardize<Loki::NullType>
00994 {
00995 template<class U, class ST>
00996 static ST VAL (const ST &, const U &)
00997 {throw UnitMismatch (); return ST (0);}
00998 };
00999
01001
01003 template<typename UL> struct dynamic_reverse;
01004
01006
01013 template<typename Head, typename Tail>
01014 struct dynamic_reverse<Loki::Typelist<Head, Tail> >
01015 {
01016 template<class U, class ST>
01017 static ST VAL (const ST &value, const U &unit)
01018 {Head test = Head ();
01019 if (typeid(unit) == typeid (test))
01020 return Reverse<Head, ST>::VAL (value);
01021 else
01022 return dynamic_reverse<Tail>::VAL (value, unit);
01023 }
01024 };
01025
01027
01029 template<>
01030 struct dynamic_reverse<Loki::NullType>
01031 {
01032 template<class U, class ST>
01033 static ST VAL (const ST &, const U &)
01034 {throw UnitMismatch (); return ST (0);}
01035 };
01036
01038
01048 template<typename QT, typename ST> class Quantity : public Quantities
01049 {
01050 public:
01052 typedef QT QuantityType;
01053
01055 typedef typename QuantityTraits<QT>::Dimension Dim;
01057 typedef typename QuantityTraits<QT>::UnitType UT;
01059 typedef typename QuantityTraits<QT>::UnitList UL;
01061 typedef typename QuantityTraits<QT>::DefaultUnit DU;
01063 typedef typename QuantityTraits<QT>::DefaultDerivedQuantityType DDQ;
01064
01065 private:
01067 static const bool Dimensionless = Dim::IsDimensionless;
01068
01070 typedef Quantity<QT, ST> Q;
01071
01072 protected:
01074
01077 std::string namestring;
01079
01082 std::string symbolstring;
01083
01085
01087 unit::Unit<UT> * findBySymbol (const std::string &unitsymbol)
01088 {return UnitPointerBySymbol<UT, UL>::result (unitsymbol);}
01089
01091
01096 template<typename U>
01097 static ST standard (const ST value, const U&)
01098 {return Standardize<typename CheckAgainstAllUnits<U, UL>::RET,
01099 ST> (value);}
01100
01102
01107 template<typename U>
01108 static ST reverse (const ST value, const U& unit)
01109 {return Reverse<typename CheckAgainstAllUnits<U, UL>::RET, ST>
01110 (value);}
01111
01112 public:
01114 Quantity (void) {}
01115
01117
01120 virtual ~Quantity (void) {}
01121
01123
01126 typedef AllUnitsTemplate<UT, UL> AllUnits;
01127
01129
01132 typedef DefaultUnitTemplate<UT, DU> DefaultUnit;
01133
01134 typedef ST StorageType;
01135
01137
01139 virtual void name (const std::string &name) {namestring = name;}
01140
01142
01144 virtual void symbol (const std::string &symbol) {symbolstring = symbol;}
01145
01147
01149 virtual std::string name (void) const {return namestring;}
01150
01152
01154 virtual std::string symbol (void) const {return symbolstring;}
01155
01157
01159 virtual ST standard_value (void) const = 0;
01160
01162
01164 virtual ST value (void) const = 0;
01165
01167
01169 static bool IsDimensionless (void) {return Dimensionless;}
01170
01172
01174 bool isDimensionless (void) const {return IsDimensionless ();}
01175
01177
01182 friend std::ostream & operator<<
01183 (std::ostream &os, const Quantity &quantity)
01184 {return quantity.print (os);}
01185
01187
01201 std::ostream & print (std::ostream &os) const
01202 {
01203 std::string nameFragment ("");
01204 std::string symbolFragment ("");
01205 std::string equal ("");
01206
01207 if (PS.name ())
01208 nameFragment = name () + " ";
01209
01210 if (PS.symbol ())
01211 symbolFragment = symbol () + " ";
01212
01213 if (PS.name () || PS.symbol ())
01214 equal = "= ";
01215
01216 os << nameFragment << symbolFragment << equal;
01217
01218 return print_value (os);
01219 }
01220
01222
01225 virtual std::ostream & print_value (std::ostream &os) const = 0;
01226
01228 friend void operator<<
01229 (std::string &str, const Quantity &quantity) {quantity >> str;}
01230
01232 virtual void operator>> (std::string &str) const = 0;
01233
01235
01238 operator std::string () const
01239 {std::string string; *this >> string; return string;}
01240
01242
01245 virtual std::ostream & operator>> (std::ostream &os) const = 0;
01246
01248
01250
01252 friend class boost::serialization::access;
01253
01255
01257 private:
01258 template<typename Archive>
01259 void serialize (Archive &ar, const unsigned int )
01260 {
01261 ar & BOOST_SERIALIZATION_NVP(namestring);
01262 ar & BOOST_SERIALIZATION_NVP(symbolstring);
01263 }
01264
01265 };
01266
01268
01270
01272
01273
01275
01277
01279 template<typename QT1, typename ST1, typename QT2, typename ST2>
01280 struct SameDimensioned<Quantity<QT1, ST1>, Quantity<QT2, ST2> >
01281 {
01282 enum {EQ = QuantityTraits<QT1>::Dimension::template Equal<
01283 typename QuantityTraits<QT2>::Dimension>::EQ};
01284 };
01285
01287
01288
01290
01292
01294
01296
01313 template<typename Q, typename DQ> struct DerivedQuantityTraits;
01314
01316
01318
01319 template<typename QT, typename SU = typename QuantityTraits<QT>::DefaultUnit,
01320 typename DQT = typename QuantityTraits<QT>::DefaultDerivedQuantityType>
01321 struct DerivedQuantity
01322 {
01323 static const bool OverwriteName = DerivedQuantityTraits<QT, DQT>::OverwriteName;
01324 static const bool OverwriteSymbol = DerivedQuantityTraits<QT, DQT>::OverwriteSymbol;
01325 };
01326
01328
01329
01330
01332
01334
01337 template<typename Q1, typename Q2> struct convertValue;
01338
01339
01340 }
01341
01342 #endif