00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef _Variable_h
00025 #define _Variable_h
00026
00027
00028 #include "Quantities/Quantity/Quantity.h"
00029 #include "Quantities/Quantity/QuantityError.h"
00030 #include "Quantities/Quantity/Generic.h"
00031 #include "Quantities/Quantity/Dynamic.h"
00032
00033
00034 #include "loki/Typelist.h"
00035 #include "loki/NullType.h"
00036 #include "loki/HierarchyGenerators.h"
00037
00038
00039 #include <boost/serialization/base_object.hpp>
00040
00041 namespace quantity {
00042
00044
00046
00048
00051 template<bool>
00052 struct VariableError;
00053
00055
00059 template<bool>
00060 struct AssignmentError;
00061
00063
00067 template<>
00068 struct AssignmentError<false>
00069 {
00071
00073 static const bool RET = true;
00074 };
00075
00077
00081 template<bool>
00082 struct OperationError;
00083
00085
00089 template<>
00090 struct OperationError<false>
00091 {
00093
00095 static const bool RET = true;
00096 };
00097
00099
00100
00101
00103
00105
00111 template<template<typename, typename> class Q1, typename QT1,
00112 typename DQT1, typename ST1,
00113 template<typename, typename> class Q2, typename QT2,
00114 typename DQT2, typename ST2>
00115 struct SameDimensioned
00116 <Q1<Quantity<QT1, ST1>, DQT1>, Q2<Quantity<QT2, ST2>, DQT2> >
00117 {
00118 enum {EQ = SameDimensioned<Quantity<QT1, ST1>, Quantity<QT2, ST2> >::EQ};
00119 };
00120
00121
00123
00128 template<class Q1, class Q2> struct CheckSecondDimension;
00129
00130 template<template<typename, typename> class Q1, typename QT1,
00131 typename DQT1, typename ST1,
00132 template<typename, typename> class Q2, class QT2,
00133 typename DQT2, typename ST2>
00134 struct CheckSecondDimension
00135 <Q1<Quantity<QT1, ST1>, DQT1>, Q2<Quantity<QT2, ST2>, DQT2> >
00136 {
00137 public:
00138 typedef typename
00139 BSUtilities::IF<SameDimensioned<Quantity<QT1, ST1>, Quantity<QT2, ST2>
00140 >::EQ, Q2<Quantity<QT2, ST2>, DQT2>, DimensionError<true> >::RET RET;
00141 };
00142
00144
00145
00146
00148
00150
00152 template<typename QT, typename DQT>
00153 struct OverwriteNameString
00154 {static std::string exec (void)
00155 {return DerivedQuantityTraits<QT, DQT>::NameString ();}
00156 };
00157
00159
00162 template<typename QT>
00163 struct UseNameString
00164 {static std::string exec (void)
00165 {return QuantityTraits<QT>::NameString ();}
00166 };
00167
00169
00173 template<typename QT, typename DQT>
00174 struct Name
00175 {static std::string exec (void)
00176 {return BSUtilities::IF<DerivedQuantityTraits<QT, DQT>::OverwriteName,
00177 OverwriteNameString<QT, DQT>, UseNameString<QT> >::RET::exec();}
00178 };
00179
00181
00183 template<typename QT, typename DQT>
00184 struct OverwriteSymbolString
00185 {static std::string exec (void)
00186 {return DerivedQuantityTraits<QT, DQT>::SymbolString ();}
00187 };
00188
00190
00193 template<typename QT>
00194 struct UseSymbolString
00195 {static std::string exec (void)
00196 {return QuantityTraits<QT>::SymbolString ();}
00197 };
00198
00200
00204 template<typename QT, typename DQT>
00205 struct Symbol
00206 {static std::string exec (void)
00207 {return BSUtilities::IF<DerivedQuantityTraits<QT, DQT>::OverwriteSymbol,
00208 OverwriteSymbolString<QT, DQT>, UseSymbolString<QT> >::RET::exec();}
00209 };
00210
00212
00213
00214
00216
00218
00221 template<typename Q1, typename Q2> struct GenerateVariable;
00222
00224
00225
00226
00228
00230
00235 template<typename BQ, typename DQ = DerivedQuantity<typename BQ::QT,
00236 typename BQ::DU, typename BQ::DDQ> > class Variable;
00237
00239
00248 template<typename QT, typename ST, typename DQSU, typename DQT>
00249 class Variable<Quantity<QT, ST>, DerivedQuantity<QT, DQSU, DQT> >
00250 : public Quantity<QT, ST>
00251 {
00252 public:
00254
00256 typedef typename QuantityTraits<QT>::Dimension DIM;
00257
00259
00261 typedef typename QuantityTraits<QT>::UnitType UT;
00262
00264
00266 typedef typename QuantityTraits<QT>::UnitList UL;
00267
00269
00272 typedef Quantity<QT, ST> BQ;
00273
00275
00278 typedef typename BQ::DU DU;
00279
00281
00283 typedef typename unit::ValidUnit<DQSU, UL>::RET SU;
00284
00286
00288 typedef Variable<BQ, DerivedQuantity<QT, SU, DQT> > V;
00289
00290 private:
00292
00296 ST _value;
00297
00299
00301
00302 public:
00304
00310 Variable (void) : BQ (), _value (ST(0))
00311 {name (Name<QT, DQT>::exec ()); symbol (Symbol<QT, DQT>::exec ());}
00312
00314
00320 Variable (const ST &value) : BQ (), _value (value)
00321 {name (Name<QT, DQT>::exec ()); symbol(Symbol<QT, DQT>::exec ());}
00322
00324
00331 Variable (const ST &value, const std::string &namestring,
00332 const std::string &symbolstring) : BQ (), _value (value)
00333 {BQ::name (namestring); BQ::symbol (symbolstring);}
00334
00336
00343 template<typename NU>
00344 Variable (const ST &value, const NU &)
00345 : BQ (), _value (unit::Reverse<SU>::VAL
00346 (unit::Standard<typename unit::ValidUnit<NU, UL>::RET>::VAL
00347 (value)))
00348 {name (Name<QT, DQT>::exec ()); symbol(Symbol<QT, DQT>::exec ());}
00349
00351
00361 template<typename NU>
00362 Variable (const ST &value, const NU &,
00363 const std::string &namestring, const std::string &symbolstring)
00364 : BQ (), _value (unit::Reverse<SU>::VAL
00365 (unit::Standard<typename unit::ValidUnit<NU, UL>::RET>::VAL
00366 (value)))
00367 {BQ::name (namestring); BQ::symbol (symbolstring);}
00368
00370
00382 Variable (const ST value, const std::string &unitsymbol) : BQ ()
00383 {name (Name<QT, DQT>::exec ()); symbol(Symbol<QT, DQT>::exec ());
00384 _value = unit::Reverse<SU>::VAL
00385 (unit::standard<UL>::VAL (value, unitsymbol));
00386 }
00387
00389
00399 Variable (const ST value, const char * unitsymbol) : BQ ()
00400 {name (Name<QT, DQT>::exec ()); symbol (Symbol<QT, DQT>::exec ());
00401 _value = unit::Reverse<SU>::VAL
00402 (unit::standard<UL>::VAL (value, std::string (unitsymbol)));
00403 }
00404
00406
00408
00410
00412
00414
00419 template<template<typename, typename> class SM, typename SST>
00420 Variable (const SM<Quantity<QT, SST>, DQT> &quantity)
00421 : BQ (), _value (quantity.value ())
00422 {name (quantity.BQ::name ()); symbol (quantity.BQ::symbol ());}
00423
00425
00435 template<template<typename, typename> class SM,
00436 typename SST, typename SSU, typename SDQT>
00437 Variable (const SM<Quantity<QT, SST>,
00438 DerivedQuantity<QT, SSU, SDQT> > &quantity)
00439 : BQ (), _value (unit::Reverse<SU>::VAL
00440 (unit::Standard<SSU>::VAL (quantity.value ())))
00441 {name (quantity.Quantity<QT, SST>::name ());
00442 symbol (quantity.Quantity<QT, SST>::symbol ());}
00443
00445
00452 template<template<typename, typename> class SM,
00453 typename SDIM, typename SST, typename SSU, typename SDQT>
00454 Variable (const SM<Quantity<GenericClass<SDIM>, SST>,
00455 DerivedQuantity<GenericClass<SDIM>, SSU, SDQT> > &quantity)
00456 : BQ (), _value (unit::Reverse<SU>::VAL
00457 (unit::Standard<typename
00458 CheckSecondDimension<V,
00459 SM<Quantity<GenericClass<SDIM>, SST>,
00460 DerivedQuantity<GenericClass<SDIM>, SSU, SDQT> > >
00461 ::RET::SU>::VAL (quantity.value ())))
00462 {name (quantity.Quantity<GenericClass<SDIM>, SST>::name ());
00463 symbol (quantity.Quantity<GenericClass<SDIM>, SST>::symbol ());}
00464
00466
00479 template<template<typename, typename> class SM,
00480 typename SQT, typename SST, typename SSU, typename SDQT>
00481 Variable (const SM<Quantity<SQT, SST>,
00482 DerivedQuantity<SQT, SSU, SDQT> > &quantity)
00483 : BQ (), _value (convertValue<V, SM<Quantity<SQT, SST>,
00484 DerivedQuantity<SQT, SSU, SDQT> > >::exec (quantity))
00485 {name (quantity.Quantity<SQT, SST>::name ());
00486 symbol (quantity.Quantity<SQT, SST>::symbol ());}
00487
00488
00490
00494 template<typename SST>
00495 Variable (const Dynamic<SST> &dynamic)
00496 {if (dynamic.isCommensurable (*this))
00497 _value = unit::Reverse<SU>::VAL (dynamic.value ());
00498 else
00499 {throw DimensionMismatch ();}
00500
00501 }
00502
00504
00506
00508
00510
00512
00519 Variable & operator= (const Variable &variable)
00520 {if (this != &variable)
00521 {_value = variable.value ();}
00522 return *this;
00523 }
00524
00526
00549 template<template<typename, typename> class SM, typename SST,
00550 typename SSU, typename SDQT>
00551 Variable & operator= (const SM<Quantity<QT, SST>,
00552 DerivedQuantity<QT, SSU, SDQT> > &quantity)
00553 {_value = unit::Reverse<SU>::VAL (unit::Standard<SSU>::VAL
00554 (quantity.value ()));
00555 return *this;
00556 }
00557
00559
00586 template<typename SDIM, typename SST, typename SSU, typename SDQT>
00587 Variable & operator=
00588 (const Variable<Quantity<GenericClass<SDIM>, SST>,
00589 DerivedQuantity<GenericClass<SDIM>, SSU, SDQT> > &quantity)
00590 {_value = unit::Reverse<SU>::VAL
00591 (unit::Standard<typename
00592 CheckSecondDimension<V,
00593 Variable<Quantity<GenericClass<SDIM>, SST>,
00594 DerivedQuantity<GenericClass<SDIM>, SSU, SDQT> > >
00595 ::RET::SU>::VAL (quantity.value ()));
00596 return *this;
00597 }
00598
00600
00615 template<template<typename, typename> class SM,
00616 typename SQT, typename SST, typename SSU, typename SDQT>
00617 Variable & operator=
00618 (const SM<Quantity<SQT, SST>, DerivedQuantity<SQT, SSU, SDQT> > &quantity)
00619 {*this = V(quantity);
00620 return *this;
00621 }
00622
00624
00632 template<typename SST>
00633 Variable & operator= (const Dynamic<SST> &dynamic)
00634 {if (dynamic.isCommensurable (*this))
00635 _value = unit::Reverse<SU>::VAL (dynamic.value ());
00636 else
00637 {throw DimensionMismatch ();}
00638 return *this;
00639 }
00640
00642
00648 Variable & operator= (const std::string &str)
00649 {this->read_value (str); return *this;}
00650
00652
00658 Variable & operator= (const char * str) {this->read_value (str); return *this;}
00659
00661
00671 template <typename T>
00672 Variable & operator= (const T &);
00673
00675
00677
00679
00681
00682 public:
00684
00686 ST value (void) const {return _value;}
00687
00689
00692 ST standard_value (void) const
00693 {return unit::Standard<SU>::VAL (_value);}
00694
00696
00702 template<typename NU>
00703 Variable<Quantity<QT, ST>,
00704 DerivedQuantity<QT, NU, DQT> > value (const NU &) const
00705 {return Variable<Quantity<QT, ST>, DerivedQuantity<QT, NU, DQT> >
00706 (unit::Reverse<typename unit::ValidUnit<NU, UL>::RET>::VAL
00707 (unit::Standard<SU>::VAL (_value)));}
00708
00710
00720 ST value (const std::string &unitsymbol)
00721 {ST value;
00722 value = unit::reverse<UL>::VAL
00723 (unit::Standard<SU>::VAL (_value), unitsymbol);
00724 return value;
00725 }
00726
00728 static std::string QuantityName (void)
00729 {return Name<QT, DQT>::exec ();}
00730
00732
00734 ST value (const char * unitsymbol)
00735 {return value (std::string (unitsymbol));}
00736
00738
00740 std::string unitsymbol (void) const {return SU::Symbol ();}
00741
00743
00745 static std::string Unitsymbol (void) {return SU::Symbol ();}
00746
00748
00750 std::string unitname (void) const {return SU::Name ();}
00751
00753
00755 static std::string Unitname (void) {return SU::Name ();}
00756
00758
00760
00762
00764
00766
00780 Variable & operator+= (const Variable &variable)
00781 {if(BSUtilities::IF<BSUtilities::SameType<UL,
00782 Loki::Typelist<unit::NonPrefixable<unit::GenericUnitBase<DIM>, unit::GenericUnit>,
00783 Loki::NullType> >::sameType, AssignmentError<true>,
00784 AssignmentError<false> >::RET::RET)
00785 _value += variable.value ();
00786 return *this;
00787 }
00788
00790
00805 template <template<typename, typename> class M1, typename ST1,
00806 typename SU1, typename DQT1>
00807 Variable & operator+= (const M1<Quantity<QT, ST1>,
00808 DerivedQuantity<QT, SU1, DQT1> > &quantity)
00809 {_value = unit::Reverse<SU>::VAL
00810 (unit::Standard<SU>::VAL (_value) +
00811 unit::Standard<SU1>::VAL (quantity.value ()));
00812 return *this;
00813 }
00814
00816
00832 template <template<typename, typename> class M1,
00833 typename DIM1, typename ST1, typename SU1, typename DQT1>
00834 Variable & operator+= (const M1<Quantity<GenericClass<DIM1>, ST1>,
00835 DerivedQuantity<GenericClass<DIM1>, SU1, DQT1> > &quantity)
00836 {_value = unit::Reverse<SU>::VAL
00837 (unit::Standard<SU>::VAL (_value) +
00838 unit::Standard<typename CheckSecondDimension<V,
00839 M1<Quantity<GenericClass<DIM1>, ST1>,
00840 DerivedQuantity<GenericClass<DIM1>, SU1, DQT1> > >
00841 ::RET::SU>::VAL (quantity.value ()));
00842 return *this;
00843 }
00844
00846
00863 template<template<typename, typename> class M1,
00864 typename QT1, typename ST1, typename SU1, typename DQT1>
00865 Variable & operator+= (const M1<Variable<QT1, ST1>,
00866 DerivedQuantity<QT1, SU1, DQT1> > &quantity)
00867 {
00868 static const bool RET =
00869 BSUtilities::IF<BSUtilities::SameType<QT, QT1>::sameType,
00870 DimensionError<false>, DimensionError<true> >::RET::RET;
00871 return *this;
00872 }
00873
00875
00879 template<template<typename, typename> class M1,
00880 typename QT1, typename ST1, typename SU1, typename DQT1>
00881 struct PlusGenerated
00882 {static V exec
00883 (const V &variable,
00884 const M1<Quantity<QT1, ST1>, DerivedQuantity<QT1, SU1, DQT1> > &quantity)
00885 {return V (unit::Reverse<SU>::VAL
00886 (unit::Standard<SU>::VAL (variable.value ())
00887 + unit::Standard<typename CheckSecondDimension<
00888 V, M1<Quantity<QT1, ST1>, DerivedQuantity<QT1, SU1, DQT1> > >
00889 ::RET::SU>::VAL (quantity.value ())));
00890 }
00891 };
00892
00894
00897 template<class Q>
00898 struct Plus
00899 {static V exec (const V &variable, const Q &quantity)
00900 {V new_object (variable);
00901 return new_object += quantity;
00902 }
00903 };
00904
00906
00912 template <template<typename, typename> class M1,
00913 typename QT1, typename ST1, typename SU1, typename DQT1>
00914 Variable operator+ (const M1<Quantity<QT1, ST1>,
00915 DerivedQuantity<QT1, SU1, DQT1> > &quantity) const
00916 {return BSUtilities::IF<BSUtilities::SameType<UL,
00917 Loki::Typelist<unit::NonPrefixable<unit::GenericUnitBase<DIM>,
00918 unit::GenericUnit>, Loki::NullType> >::sameType,
00919 typename PlusGenerated<M1, QT1, ST1, SU1, DQT1>::PlusGenerated,
00920 typename Plus<M1<Quantity<QT1, ST1>, DerivedQuantity<QT1, SU1, DQT1> > >
00921 ::Plus>::RET::exec (*this, quantity);
00922 }
00923
00925
00932 template <typename SST>
00933 Variable operator+ (const Dynamic<SST> &quantity) const
00934 {Variable new_variable (quantity);
00935 return *this + new_variable;
00936 }
00937
00939
00946 template<template<typename, typename> class M1, typename ST1>
00947 friend Variable operator+
00948 (const Dynamic<ST1> &quantity1,
00949 const M1<BQ, DerivedQuantity<QT, SU, DQT> > &quantity2)
00950 {Variable new_variable (quantity1);
00951 return new_variable + quantity2;
00952 }
00953
00955
00969 Variable & operator-= (const Variable &variable)
00970 {if(BSUtilities::IF<BSUtilities::SameType<UL,
00971 Loki::Typelist<unit::NonPrefixable<unit::GenericUnitBase<DIM>,
00972 unit::GenericUnit>, Loki::NullType> >::sameType,
00973 AssignmentError<true>, AssignmentError<false> >::RET::RET)
00974 _value -= variable.value ();
00975 return *this;
00976 }
00977
00979
00994 template <template<typename, typename> class M1, typename ST1,
00995 typename SU1, typename DQT1>
00996 Variable & operator-= (const M1<Quantity<QT, ST1>,
00997 DerivedQuantity<QT, SU1, DQT1> > &quantity)
00998 {_value = unit::Reverse<SU>::VAL
00999 (unit::Standard<SU>::VAL (_value) -
01000 unit::Standard<SU1>::VAL (quantity.value ()));
01001 return *this;
01002 }
01003
01005
01021 template <template<typename, typename> class M1,
01022 typename DIM1, typename ST1, typename SU1, typename DQT1>
01023 Variable & operator-=
01024 (const M1<Quantity<GenericClass<DIM1>, ST1>,
01025 DerivedQuantity<GenericClass<DIM1>, SU1, DQT1> > &quantity)
01026 {_value = unit::Reverse<SU>::VAL
01027 (unit::Standard<SU>::VAL (_value) -
01028 unit::Standard<typename CheckSecondDimension<
01029 V, M1<Quantity<GenericClass<DIM1>, ST1>,
01030 DerivedQuantity<GenericClass<DIM1>, SU1, DQT1> > >
01031 ::RET::SU>::VAL (quantity.value ()));
01032 return *this;
01033 }
01034
01036
01053 template<template<typename, typename> class M1,
01054 typename QT1, typename ST1, typename SU1, typename DQT1>
01055 Variable & operator-= (const M1<Quantity<QT1, ST1>,
01056 DerivedQuantity<QT1, SU1, DQT1> > &quantity)
01057 {
01058 static const bool RET =
01059 BSUtilities::IF<BSUtilities::SameType<QT, QT1>::sameType,
01060 DimensionError<false>, DimensionError<true> >::RET::RET;
01061 return *this;
01062 }
01063
01065
01069 template<template<typename, typename> class M1,
01070 typename QT1, typename ST1, typename SU1, typename DQT1>
01071 struct MinusGenerated
01072 {static V exec (const V &variable,
01073 const M1<Quantity<QT1, ST1>, DerivedQuantity<QT1, SU1, DQT1> > &quantity)
01074 {return V (unit::Reverse<SU>::VAL
01075 (unit::Standard<SU>::VAL (variable.value ())
01076 - unit::Standard<typename CheckSecondDimension<
01077 V, M1<Quantity<QT1, ST1>, DerivedQuantity<QT1, SU1, DQT1> > >
01078 ::RET::SU>::VAL (quantity.value ())));
01079 }
01080 };
01081
01083
01086 template<typename Q>
01087 struct Minus
01088 {static V exec (const V &variable, const Q &quantity)
01089 {V new_object (variable);
01090 return new_object -= quantity;
01091 }
01092 };
01093
01095
01101 template <template<typename, typename> class M1,
01102 typename QT1, typename ST1, typename SU1, typename DQT1>
01103 Variable operator- (const M1<Quantity<QT1, ST1>,
01104 DerivedQuantity<QT1, SU1, DQT1> > &quantity) const
01105 {return BSUtilities::IF<BSUtilities::SameType<UL,
01106 Loki::Typelist<unit::NonPrefixable<unit::GenericUnitBase<DIM>,
01107 unit::GenericUnit>, Loki::NullType> >::sameType,
01108 typename MinusGenerated<M1, QT1, ST1, SU1, DQT1>::MinusGenerated,
01109 typename Minus<M1<Quantity<QT1, ST1>, DerivedQuantity<QT1, SU1, DQT1> > >
01110 ::Minus>::RET::exec (*this, quantity);
01111 }
01112
01114
01121 Variable operator- (const Dynamic<ST> &quantity) const
01122 {Variable new_variable (quantity);
01123 return *this - new_variable;
01124 }
01125
01127
01134 template<template<typename, typename> class M1, typename ST1>
01135 friend Variable operator-
01136 (const Dynamic<ST1> &quantity1,
01137 const M1<BQ, DerivedQuantity<QT, SU, DQT> > &quantity2)
01138 {Variable new_variable (quantity1);
01139 return new_variable - quantity2;
01140 }
01141
01143
01146 Variable & operator*= (const ST factor)
01147 {_value *= factor;
01148 return *this;
01149 }
01150
01152
01154 Variable operator* (const ST factor) const
01155 {V new_object (*this);
01156 return new_object *= factor;
01157 }
01158
01160
01163 template<typename RHSST>
01164 Dynamic<RHSST> operator * (const Dynamic<RHSST> &rhs) const
01165 {return rhs * (*this);}
01166
01168
01180 template <template<typename, typename> class Q>
01181 friend V operator*
01182 (const ST factor, const Q<Quantity<QT, ST>,
01183 DerivedQuantity<QT, SU, DQT> > &variable)
01184 {return V (variable) *= factor;}
01185
01187
01190 template<template<typename, typename> class FM, typename FQT, typename FST, typename FSU,
01191 typename FDQT>
01192 typename GenerateVariable<V,
01193 FM<Quantity<FQT, FST>, DerivedQuantity<FQT, FSU, FDQT> > >::Add
01194 operator* (const FM<Quantity<FQT, FST>, DerivedQuantity<FQT, FSU, FDQT> > &factor) const
01195 {
01196 return typename
01197 GenerateVariable<V, FM<Quantity<FQT, FST>, DerivedQuantity<FQT, FSU, FDQT> > >::Add
01198 (standard_value () * factor.standard_value ());
01199 }
01200
01202
01206 Variable & operator/= (const ST divisor)
01207 {_value /= divisor;
01208 return *this;
01209 }
01210
01212
01214 Variable operator/ (const ST divisor) const
01215 {V new_object (*this);
01216 return new_object /= divisor;
01217 }
01218
01220
01225 template<class Q>
01226 typename GenerateVariable<Variable, Q>::Sub operator/
01227 (const Q &factor) const
01228 {
01229 return typename GenerateVariable<Variable, Q>::Sub
01230 (standard_value () / factor.standard_value ());
01231 }
01232
01234
01237 friend
01238 typename GenerateVariable<Variable, Loki::NullType>::Inv
01239 operator/ (const ST numerator, const Variable &factor)
01240 {
01241 return typename
01242 GenerateVariable<Variable, Loki::NullType>::Inv
01243 (numerator / factor.standard_value ());
01244 }
01245
01247
01250 const Variable operator+ (void) const
01251 {return Variable (*this);}
01252
01254
01257 const Variable operator- (void) const
01258 {return Variable (*this) *= ST(-1.0);}
01259
01261
01264 Variable & operator++ ()
01265 {++_value;
01266 return *this;
01267 }
01268
01270
01273 Variable & operator-- ()
01274 {--_value;
01275 return *this;
01276 }
01277
01279
01284 const Variable operator++ (int)
01285 {Variable temp (*this);
01286 ++*this;
01287 return temp;
01288 }
01289
01291
01296 const Variable operator-- (int)
01297 {Variable temp (*this);
01298 --*this;
01299 return temp;
01300 }
01301
01303
01305
01307
01309
01311
01325 #define QUANTITY_COMPARISON_OPERATORS(mode, opName, opType) \
01326 bool opName (const mode &rhs) const \
01327 {return _value opType rhs.value ();} \
01328 template <template<typename, typename> class RM, typename RST, typename RSU, typename RDQT> \
01329 bool opName (const RM<Quantity<QT, RST>, DerivedQuantity<QT, RSU, RDQT> > &rhs) const \
01330 {return standard_value () opType rhs.standard_value ();} \
01331 template <template<typename, typename> class RM, \
01332 typename RQT, typename RST, typename RSU, typename RDQT> \
01333 bool opName (const RM<Quantity<RQT, RST>, DerivedQuantity<RQT, RSU, RDQT> > &rhs) const \
01334 {return (*this opType V(rhs));} \
01335 bool opName (const Dynamic<ST> &dynamic) const \
01336 {if (dynamic.isCommensurable (*this)) \
01337 return standard_value () opType dynamic.value (); \
01338 else \
01339 {throw DimensionMismatch ();} }
01340
01341 QUANTITY_COMPARISON_OPERATORS(Variable, operator==, ==)
01342 QUANTITY_COMPARISON_OPERATORS(Variable, operator!=, !=)
01343 QUANTITY_COMPARISON_OPERATORS(Variable, operator>, >)
01344 QUANTITY_COMPARISON_OPERATORS(Variable, operator<, <)
01345 QUANTITY_COMPARISON_OPERATORS(Variable, operator>=, >=)
01346 QUANTITY_COMPARISON_OPERATORS(Variable, operator<=, <=)
01347
01349
01351
01353
01355
01357
01363 template<long N, long D>
01364 typename GenerateVariable<Variable,
01365 BSUtilities::Rational<N, D> >::Mult
01366 pow (const BSUtilities::Rational<N, D> &) const
01367 {return std::pow (standard_value (),
01368 static_cast<double>(N)/static_cast<double>(D));}
01369
01371
01377 template<int I>
01378 typename GenerateVariable<Variable,
01379 BSUtilities::Rational<I, long(1)> >::Mult
01380 pow (const typename Loki::Int2Type<I>) const
01381 {return std::pow (standard_value (), I);}
01382
01384
01390 template<class T>
01391 Dynamic<ST> pow (const T &exp) const
01392 {return Dynamic<ST>::pow (*this, exp);}
01393
01395
01402 typename
01403 GenerateVariable<Variable, BSUtilities::Rational<1, 2>
01404 >::Mult sqrt (void) const
01405 {
01406 return typename
01407 GenerateVariable<Variable, BSUtilities::Rational<1, 2>
01408 >::Mult (std::sqrt(standard_value ()));
01409 }
01410
01412
01414
01416
01418
01420
01423 std::ostream & print_value (std::ostream &os) const
01424 {return os << _value << " " << SU::Symbol ();}
01425
01427
01429 void operator>> (std::string &str) const
01430 {str = BSUtilities::Conversion<Variable>::to_string (*this);}
01431
01433
01437 std::ostream & operator>> (std::ostream &os) const
01438 {return this->print (os);}
01439
01441
01443 void read_value (const std::string &str);
01444
01446
01448 friend void operator>>
01449 (const std::string &str, Variable &variable)
01450 {variable.read_value (str);}
01451
01453 void operator<< (const std::string &str) {read_value (str);}
01454
01456
01460 std::istream & operator<< (std::istream &is)
01461 {std::string string; getline (is, string);
01462 this->read_value (string); return is;}
01463
01465
01468 friend std::istream & operator>>
01469 (std::istream &is, Variable &variable) {return variable << is;}
01470
01472
01474
01476
01478
01479 private:
01481 friend class boost::serialization::access;
01482
01484
01486 template<typename Archive>
01487 void serialize (Archive &ar, const unsigned int )
01488 {
01489 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(BQ);
01490 ar & BOOST_SERIALIZATION_NVP(_value);
01491 }
01492
01494
01496
01497 };
01498
01500
01502
01507 template<typename QT, typename ST, typename SU, typename DQT>
01508 void Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> >::read_value
01509 (const std::string &str)
01510 {
01511 std::string value;
01512 std::string unit;
01513
01514 std::string::size_type start;
01515 std::string::size_type end;
01516
01517 start = str.find_first_not_of (" \0");
01518 end = start;
01519
01520 if (RS.name ())
01521 {
01522 if (start == std::string::npos)
01523 throw InputError ();
01524
01525 else
01526 {
01527 end = str.find_first_of (" \0", start);
01528
01529 if (end == std::string::npos)
01530 BQ::namestring = str.substr (start);
01531
01532 else
01533 BQ::namestring = (str.substr (start, end - start));
01534 }
01535 }
01536
01537 start = str.find_first_not_of (" \0", end);
01538 end = start;
01539
01540 if (RS.symbol ())
01541 {
01542 if (start == std::string::npos)
01543 throw InputError ();
01544
01545 else
01546 {
01547 end = str.find_first_of (" \0", start);
01548
01549 if (end == std::string::npos)
01550 BQ::symbolstring = str.substr (start);
01551
01552 else
01553 BQ::symbolstring = (str.substr (start, end - start));
01554 }
01555 }
01556
01557 start = str.find_first_not_of (" \0", end);
01558 end = start;
01559
01560 if (RS.equal () && (RS.name () || RS.symbol ()))
01561 {
01562 if (start == std::string::npos)
01563 throw InputError ();
01564
01565 else
01566 {
01567 end = str.find_first_of (" \0", start);
01568
01569 if (end == std::string::npos)
01570 throw InputError ();
01571
01572 else if (str.substr (start, end - start) != "=")
01573 throw InputError ();
01574 }
01575 }
01576
01577 start = str.find_first_not_of (" \0", end);
01578 end = start;
01579
01580 if (start == std::string::npos)
01581 throw InputError ();
01582
01583 else
01584 {
01585 end = str.find_first_of (" \0", start);
01586
01587 if (end == std::string::npos)
01588 value = str.substr (start);
01589
01590 else
01591 value = str.substr (start, end - start);
01592
01593 start = str.find_first_not_of (" \0", end);
01594
01595 if (start == std::string::npos)
01596 unit = "";
01597
01598 else
01599 {
01600 end = str.find_first_of (" \0\n", start);
01601
01602 if ((end = std::string::npos))
01603 unit = str.substr (start);
01604
01605 else
01606 unit = str.substr (start, end - start);
01607 }
01608 }
01609
01610 ST intermediate;
01611
01612 try {
01613 intermediate = BSUtilities::Conversion<ST>::string_to (value);
01614 }
01615
01616 catch (BSUtilities::ConversionFailure) {throw InputError ();}
01617
01618 start = unit.find_first_not_of (" \0");
01619 end = start;
01620
01621
01622
01623
01624 if (start == std::string::npos)
01625 {
01626 std::string assume_unit;
01627
01628
01629
01630
01631
01632 if ((assume_unit = RS.unit ()) != "")
01633 {
01634 try {
01635 intermediate = unit::Reverse<SU>::VAL
01636 (unit::standard<UL>::VAL (intermediate, assume_unit));
01637 }
01638
01639 catch (unit::UnitMismatch) {throw InputError ();}
01640 catch (unit::UnitSyntaxError) {throw InputError ();}
01641
01642 }
01643 }
01644
01645
01646
01647
01648
01649 else
01650 {
01651 end = unit.find_first_of (" \0", start);
01652 try {
01653 intermediate = unit::Reverse<SU>::VAL
01654 (unit::standard<UL>::VAL (intermediate, unit.substr (start)));
01655 }
01656 catch (unit::UnitMismatch) {throw InputError ();}
01657 catch (unit::UnitSyntaxError) {throw InputError ();}
01658 }
01659
01660 _value = intermediate;
01661
01662 }
01663
01665
01669 template<template<typename, typename> class Q1, typename QT1, typename DQT1,
01670 template<typename, typename> class Q2, typename QT2, typename DQT2,
01671 typename ST>
01672 struct GenerateVariable
01673 <Q1<Quantity<QT1, ST>, DQT1>, Q2<Quantity<QT2, ST>, DQT2> >
01674 {
01675 private:
01676 typedef typename QuantityTraits<QT1>::Dimension Dim1;
01677 typedef typename QuantityTraits<QT2>::Dimension Dim2;
01678
01680 typedef typename Dim1::template Add<Dim2> AddT;
01681 typedef Quantity<GenericClass<typename AddT::Res>, ST> AddNewQ;
01682
01684 typedef typename Dim1::template Sub<Dim2> SubT;
01685 typedef Quantity<GenericClass<typename SubT::Res>, ST> SubNewQ;
01686
01687 public:
01689
01691 typedef Variable<AddNewQ> Add;
01692
01694
01696 typedef Variable<SubNewQ> Sub;
01697 };
01698
01700
01703 template<template<typename, typename> class Q,
01704 typename QT, typename ST, typename DQT>
01705 struct GenerateVariable <Q<Quantity<QT, ST>, DQT>, Loki::NullType>
01706 {
01707 private:
01709 typedef typename QuantityTraits<QT>::Dimension::Inv InvT;
01710 typedef Quantity<GenericClass<typename InvT::Res>, ST> InvNewQ;
01711
01712 public:
01714
01716 typedef Variable<InvNewQ> Inv;
01717 };
01718
01720
01723 template<template<typename, typename> class Q, typename QT,
01724 class ST, class DQT, long N, long D>
01725 struct GenerateVariable
01726 <Q<Quantity<QT, ST>, DQT>, BSUtilities::Rational<N, D> >
01727 {
01728 private:
01730 typedef typename QuantityTraits<QT>::Dimension::template
01731 Mult<N, D> MultT;
01732
01733 typedef Quantity<GenericClass<typename MultT::Res>, ST> MultNewQ;
01734
01735 public:
01737
01739 typedef Variable<MultNewQ> Mult;
01740 };
01741
01743
01750 template<template<typename, typename> class Q, typename QT,
01751 typename ST, typename SU, typename DQT>
01752 inline typename GenerateVariable
01753 <Q<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> >, BSUtilities::Rational<1, 2> >::Mult
01754 sqrt (const Q<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> > &quantity)
01755 {
01756 return typename
01757 GenerateVariable<Q<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> >,
01758 BSUtilities::Rational<1, 2> >::Mult (quantity.sqrt());
01759 }
01760
01762
01769 template<template<typename, typename> class Q, typename QT,
01770 typename ST, typename SU, typename DQT, int I>
01771 inline typename GenerateVariable
01772 <Q<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> >, BSUtilities::Rational<I, long(1)> >::Mult
01773 pow (const Q<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> > &quantity,
01774 typename Loki::Int2Type<I>)
01775 {
01776 return typename
01777 GenerateVariable<Q<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> >,
01778 BSUtilities::Rational<long(I), long(1)> >::Mult
01779 (quantity.pow(Loki::Int2Type<I> ()));
01780 }
01781
01783
01791 template<template<typename, typename> class Q, typename QT,
01792 typename ST, typename SU, typename DQT, long N, long D>
01793 inline typename GenerateVariable
01794 <Q<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> >, BSUtilities::Rational<N, D> >::Mult
01795 pow (const Q<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> > &quantity,
01796 const BSUtilities::Rational<N, D> &)
01797 { return typename
01798 GenerateVariable <Q<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> >,
01799 BSUtilities::Rational<N, D> >::Mult
01800 (quantity.pow(BSUtilities::Rational<N, D> ()));
01801 }
01802
01804
01809 template<template<typename, typename> class Q, typename QT,
01810 typename ST, typename SU, typename DQT, typename T>
01811 inline Dynamic<ST>
01812 pow (const Q<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> > &quantity, const T &exp)
01813 {return Dynamic<ST> (quantity.pow(exp));}
01814
01816
01818 template<template<typename, typename> class Q, typename QT,
01819 typename ST, typename SU, typename DQT>
01820 inline Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> >
01821 abs (const Q<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> > &variable)
01822 {return Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> >
01823 (std::abs (variable.value ()));}
01824
01826
01828 template<template<typename, typename> class Q, typename QT,
01829 typename ST, typename SU, typename DQT>
01830 inline Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> >
01831 ceil (const Q<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> > &variable)
01832 {return Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> >
01833 (std::ceil (variable.value ()));}
01834
01836
01838 template<template<typename, typename> class Q, typename QT,
01839 typename ST, typename SU, typename DQT>
01840 inline Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> >
01841 floor (const Q<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> > &variable)
01842 {return Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> >
01843 (std::floor (variable.value ()));}
01844
01846
01848 template<template<typename, typename> class Q, typename QT,
01849 typename ST, typename SU, typename DQT>
01850 inline Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> >
01851 frexp (const Q<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> > &variable, int *exponent)
01852 {return Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> >
01853 (std::frexp (variable.value (), exponent));}
01854
01856
01858 template<template<typename, typename> class Q, typename QT,
01859 typename ST, typename SU, typename DQT>
01860 inline Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> >
01861 ldexp (const Q<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> > &variable, int exponent)
01862 {return Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> >
01863 (std::ldexp (variable.value (), exponent));}
01864
01866
01873 template<template<typename, typename> class Q1,
01874 template<typename, typename> class Q2, typename QT,
01875 typename ST, typename SU, typename DQT>
01876 inline Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> >
01877 fmod (const Q1<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> > &quantity1,
01878 const Q2<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> > &quantity2)
01879 {return
01880 Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> >
01881 (std::fmod (quantity1.value (), quantity2.value ()));
01882 }
01883
01885
01891 template<template<typename, typename> class Q1,
01892 template<typename, typename> class Q2, typename QT,
01893 typename ST, typename SU, typename DQT1, class DQT2>
01894 inline Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT1> >
01895 fmod (const Q1<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT1> > &quantity1,
01896 const Q2<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT2> > &quantity2)
01897 {return
01898 Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT1> >
01899 (unit::Reverse<SU>::VAL
01900 (std::fmod (quantity1.standard_value (), quantity2.standard_value ())));
01901 }
01902
01904
01910 template <template<typename, typename> class Q1, typename QT1,
01911 typename ST, typename SU1, typename DQT1,
01912 template<typename, typename> class Q2, typename QT2, typename SU2, typename DQT2>
01913 inline Variable<Quantity<QT1, ST>, DerivedQuantity<QT1, SU1, DQT1> >
01914 fmod (const Q1<Quantity<QT1, ST>, DerivedQuantity<QT1, SU1, DQT1> > &quantity1,
01915 const Q2<Quantity<QT2, ST>, DerivedQuantity<QT2, SU2, DQT2> > &quantity2)
01916 {return Variable<Quantity<QT1, ST>, DerivedQuantity<QT1, SU1, DQT1> >
01917 (unit::Reverse<SU1>::VAL
01918 (std::fmod (quantity1.standard_value (), unit::Standard<typename CheckSecondDimension<
01919 Q1<Quantity<QT1, ST>, DerivedQuantity<QT1, SU1, DQT1> >,
01920 Q2<Quantity<QT2, ST>, DerivedQuantity<QT2, SU2, DQT2> >
01921 >::RET::SU>::VAL (quantity2.value ()))));
01922 }
01923
01925
01928 template<template<typename, typename> class Q, typename QT,
01929 typename ST, typename SU, typename DQT>
01930 inline Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> >
01931 modf (const Q<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> > &quantity,
01932 Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> > *integral)
01933 {ST i_ptr;
01934 Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> >
01935 new_variable (std::modf (quantity.value (), &i_ptr));
01936 Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> > int_quantity (i_ptr);
01937 *integral = int_quantity; return new_variable;
01938 }
01939
01941
01945 template<template<typename, typename> class Q, typename QT,
01946 typename ST, typename SU1, typename DQT1, typename SU2, typename DQT2>
01947 inline Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU1, DQT1> >
01948 modf (const Q<Quantity<QT, ST>, DerivedQuantity<QT, SU1, DQT1> > &quantity,
01949 Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU2, DQT2> > *integral)
01950 {ST i_ptr;
01951 Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU1, DQT1> >
01952 new_variable (std::modf (quantity.value (), &i_ptr));
01953 *integral = Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU2, DQT2> >
01954 (Variable<Quantity<QT, ST>, DerivedQuantity<QT, SU1, DQT1> >(i_ptr));
01955 return new_variable;
01956 }
01957
01959
01963 template<template<typename, typename> class Q, typename QT1,
01964 typename SU1, typename DQT1, typename QT2, typename SU2, typename DQT2, typename ST>
01965 inline Variable<Quantity<QT1, ST>, DerivedQuantity<QT1, SU1, DQT1> >
01966 modf (const Q<Quantity<QT1, ST>, DerivedQuantity<QT1, SU1, DQT1> > &quantity,
01967 Variable<Quantity<QT2, ST>, DerivedQuantity<QT2, SU2, DQT2> > *integral)
01968 {ST i_ptr;
01969 typename CheckSecondDimension<Variable<Quantity<QT2, ST>, DerivedQuantity<QT2, SU2, DQT2> >,
01970 Variable<Quantity<QT1, ST>, DerivedQuantity<QT1, SU1, DQT1> > >::RET
01971 new_variable (unit::Reverse<SU1>::VAL
01972 (std::modf (quantity.standard_value (), &i_ptr)));
01973 *integral = Variable<Quantity<QT2, ST>, DerivedQuantity<QT2, SU2, DQT2> >
01974 (Variable<Quantity<QT1, ST>, DerivedQuantity<QT1, SU1, DQT1> >(i_ptr));
01975 return new_variable;
01976 }
01977
01979
01980
01982
01984
01986 struct Dummy;
01987
01989
02004 #define QUANTITY_VARIABLE_DIMENSIONLESS_MATHFCT(function, helper) \
02005 template<typename QT, typename ST> struct helper {static ST exec (const Quantity<QT, ST> &quantity) \
02006 {return ST(std::function (quantity.value ()));}}; \
02007 template<template<typename, typename> class M, typename QT, typename ST, typename SU, typename DQT> \
02008 inline typename GenerateVariable<M<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> >, \
02009 BSUtilities::Rational<0> >::Mult \
02010 function (const M<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> > &quantity) \
02011 {return typename GenerateVariable<M<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> >, \
02012 BSUtilities::Rational<0> >::Mult (BSUtilities::IF<CheckDimensionality<Quantity<QT, ST> >::RET, \
02013 typename helper<QT, ST>::helper, Dummy>::RET::exec (quantity));}
02014
02015 QUANTITY_VARIABLE_DIMENSIONLESS_MATHFCT(exp, expHelper)
02016 QUANTITY_VARIABLE_DIMENSIONLESS_MATHFCT(log, logHelper)
02017 QUANTITY_VARIABLE_DIMENSIONLESS_MATHFCT(log10, log10Helper)
02018 QUANTITY_VARIABLE_DIMENSIONLESS_MATHFCT(sin, sinHelper)
02019 QUANTITY_VARIABLE_DIMENSIONLESS_MATHFCT(cos, cosHelper)
02020 QUANTITY_VARIABLE_DIMENSIONLESS_MATHFCT(tan, tanHelper)
02021 QUANTITY_VARIABLE_DIMENSIONLESS_MATHFCT(sinh, sinhHelper)
02022 QUANTITY_VARIABLE_DIMENSIONLESS_MATHFCT(cosh, coshHelper)
02023 QUANTITY_VARIABLE_DIMENSIONLESS_MATHFCT(tanh, tanhHelper)
02024 QUANTITY_VARIABLE_DIMENSIONLESS_MATHFCT(asin, asinHelper)
02025 QUANTITY_VARIABLE_DIMENSIONLESS_MATHFCT(acos, acosHelper)
02026 QUANTITY_VARIABLE_DIMENSIONLESS_MATHFCT(atan, atanHelper)
02027
02029
02036 template<template<typename, typename> class M1, typename QT1, typename ST1, typename SU1, typename DQT1,
02037 template<typename, typename> class M2, typename QT2, typename ST2, typename SU2, typename DQT2>
02038 inline typename GenerateVariable<M1<Quantity<QT1, ST1>, DerivedQuantity<QT1, SU1, DQT1> >,
02039 M2<Quantity<QT2, ST2>, DerivedQuantity<QT1, SU2, DQT2> > >::Sub
02040 atan2 (const M1<Quantity<QT1, ST1>, DerivedQuantity<QT1, SU1, DQT1> > &quantity,
02041 const M2<Quantity<QT2, ST2>, DerivedQuantity<QT1, SU2, DQT2> > &quantity2)
02042 {return typename GenerateVariable<typename BSUtilities::IF<SameDimensioned<Quantity<QT1, ST1>,
02043 Quantity<QT2, ST2> >::EQ, M1<Quantity<QT1, ST1>, DerivedQuantity<QT1, SU1, DQT1> >,
02044 DimensionError<true> >::RET, M2<Quantity<QT2, ST2>, DerivedQuantity<QT1, SU2, DQT2> > >::Sub
02045 (std::atan2 (quantity.standard_value (), quantity2.standard_value ()));}
02046
02048
02050
02051 }
02052
02053 #endif