00001
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef _Unit_h
00027 #define _Unit_h
00028
00029
00030 #include "Quantities/Quantity/Prefix.h"
00031 #include "Quantities/Quantity/UnitError.h"
00032
00033
00034 #include "BSUtilities/BSUtilities.h"
00035 #include "BSUtilities/TemplateTools.h"
00036 #include "BSUtilities/Conversion.h"
00037 #include "BSUtilities/BoostSpirit.h"
00038
00039
00040 #include "loki/NullType.h"
00041 #include "loki/EmptyType.h"
00042 #include "loki/TypeManip.h"
00043 #include "loki/Typelist.h"
00044
00045
00046 #include <vector>
00047 #include <string>
00048 #include <climits>
00049
00050
00051 #include <boost/spirit.hpp>
00052 #include <boost/spirit/actor.hpp>
00053 #include <boost/spirit/phoenix/functions.hpp>
00054
00056
00064 namespace unit {
00065
00067
00068
00069
00071
00073
00076 template<bool>
00077 struct InvalidUnit;
00078
00080
00085 template<class U, class UL> struct ValidUnit;
00086
00088
00089
00090
00092
00094
00097 template<class UT> class Unit {};
00098
00100
00101
00102
00104
00106
00114 template<class UT, class U>
00115 class NonPrefixable : public Unit<UT>
00116 {
00117 private:
00122 static const double StandardFactor;
00123
00125 static const bool SI;
00126
00128 static const bool Exact;
00129
00131
00133 static const std::string Namestring;
00134
00136
00138 static const std::string Symbolstring;
00139
00140 public:
00142
00144 static double Factor (void) {return StandardFactor;}
00145
00147
00149 static bool IsSI (void) {return SI;}
00150
00152
00154 static bool IsExact (void) {return Exact;}
00155
00157
00158
00159 static std::string Name (void) {return Namestring;}
00160
00162
00163
00164 static std::string Symbol (void) {return Symbolstring;}
00165
00166 };
00167
00169
00170
00171
00173
00175
00182 template<class UT, class U> class Prefixable : public Unit<UT>
00183 {
00184 private:
00189 static const double StandardFactor;
00190
00192
00194 static const bool SI;
00195
00197
00199 static const bool Exact;
00200
00201 public:
00203
00205 static double BaseFactor (void) {return StandardFactor;}
00206
00208
00209
00210 static bool IsSI (void) {return SI;}
00211
00213
00214
00215 static bool IsExact (void) {return Exact;}
00216
00217 protected:
00219
00220
00221 static const std::string Basename;
00222
00224
00225
00226 static const std::string Basesymbol;
00227
00228 };
00229
00231
00238 template<class BP, class UP = No> class Prefixed;
00239
00241
00250 template<class UT, class U, class UP>
00251 class Prefixed<Prefixable<UT, U>, UP> : public Prefixable<UT, U>
00252 {
00253 public:
00255
00256
00257
00258
00259 static std::string Name (void)
00260 {return UP::Name + Prefixable<UT, U>::Basename;}
00261
00263
00264
00265
00266
00267 static std::string Symbol (void)
00268 {return UP::Symbol + Prefixable<UT, U>::Basesymbol;}
00269
00270 };
00271
00273
00274
00275
00277
00279
00281
00283
00285 template<bool> struct UnitListError;
00286
00288
00292 template<> struct UnitListError<false> {};
00293
00295
00297
00299
00305 template<long N, long D>
00306 struct Power
00307 {static std::string string (void)
00308 {return "^" + BSUtilities::Conversion<long>::to_string(N) + "/"
00309 + BSUtilities::Conversion<long>::to_string(D);}
00310 };
00311
00313
00314
00315
00316
00317
00318 template<long N>
00319 struct Power<N, 1L>
00320 {static std::string string (void)
00321 {return "^" + BSUtilities::Conversion<long>::to_string(N);}
00322 };
00323
00325
00326
00327
00328
00329 template<>
00330 struct Power<1L, 1L>
00331 {static std::string string (void) {return "";}
00332 };
00333
00335
00337
00339
00344 template<typename UL, typename E> class Component;
00345
00347
00352 template<typename UT, typename CL> class ComposeBase;
00353
00355
00365 template<typename UT, typename UL, long N, long D, typename CTail>
00366 class ComposeBase<UT, Loki::Typelist<Component<UL,
00367 BSUtilities::Rational<N, D> >, CTail> >: public Unit<UT>
00368 {
00369 private:
00374 static const double StandardFactor;
00375
00376 public:
00378
00381 static double BaseFactor (void) {return StandardFactor;}
00382
00383 };
00384
00386
00390 template<typename UT>
00391 class ComposeBase<UT, Loki::NullType> : public Unit<UT> {};
00392
00394
00399 template<typename CB, typename CUL> class Composed;
00400
00402
00434 template<typename UT, typename UL, long N, long D, typename CTail,
00435 typename UT1, typename U1, typename CUTail>
00436 class Composed<ComposeBase<UT, Loki::Typelist<Component<UL,
00437 BSUtilities::Rational<N, D> >, CTail> >,
00438 Loki::Typelist<NonPrefixable<UT1, U1>, CUTail> >
00439 : public ComposeBase<UT, Loki::Typelist<Component<UL,
00440 BSUtilities::Rational<N, D> >, CTail> >
00441 {
00442 public:
00443 static std::string Symbol (void)
00444 {return ValidUnit<NonPrefixable<UT1, U1>, UL>::RET::Symbol()
00445 + Power<N, D>::string ()
00446 + BSUtilities::IF<Loki::TL::Length<CUTail>::value,
00447 BSUtilities::Blank, BSUtilities::EmptyString>::RET::string()
00448 + Composed<ComposeBase<UT, CTail>,
00449 typename BSUtilities::IF<Loki::TL::Length<CTail>::value
00450 - Loki::TL::Length<CUTail>::value,
00451 UnitListError<true>, CUTail>::RET>::Symbol ();}
00452 static std::string Name (void)
00453 {return ValidUnit<NonPrefixable<UT1, U1>, UL>::RET::Name()
00454 + Power<N, D>::string ()
00455 + BSUtilities::IF<Loki::TL::Length<CUTail>::value,
00456 BSUtilities::Blank, BSUtilities::EmptyString>::RET::string()
00457 + Composed<ComposeBase<UT, CTail>,
00458 typename BSUtilities::IF<Loki::TL::Length<CTail>::value
00459 - Loki::TL::Length<CUTail>::value,
00460 UnitListError<true>, CUTail>::RET>::Name ();}
00461 static bool IsSI (void)
00462 {return ((NonPrefixable<UT1, U1>::IsSI ()
00463 && Composed<ComposeBase<UT, CTail>,
00464 typename BSUtilities::IF<Loki::TL::Length<CTail>::value
00465 - Loki::TL::Length<CUTail>::value,
00466 UnitListError<true>, CUTail>::RET>::IsSI ()) ? 1 : 0);}
00467 static bool IsExact (void)
00468 {return ((NonPrefixable<UT1, U1>::IsExact ()
00469 && Composed<ComposeBase<UT, CTail>,
00470 typename BSUtilities::IF<Loki::TL::Length<CTail>::value
00471 - Loki::TL::Length<CUTail>::value,
00472 UnitListError<true>, CUTail>::RET>::IsExact ()) ? 1 : 0);}
00473 };
00474
00476
00509 template<typename UT, typename UL, long N, long D, typename CTail,
00510 typename UT1, typename U1, typename UP1, typename CUTail>
00511 class Composed<ComposeBase<UT, Loki::Typelist<Component<UL,
00512 BSUtilities::Rational<N, D> >, CTail> >,
00513 Loki::Typelist<Prefixed<Prefixable<UT1, U1>, UP1>, CUTail> >
00514 : public ComposeBase<UT, Loki::Typelist<Component<UL,
00515 BSUtilities::Rational<N, D> >, CTail> >
00516 {
00517 public:
00518 static std::string Symbol (void)
00519 {return ValidUnit<Prefixed<Prefixable<UT1, U1>, UP1>,
00520 UL>::RET::Symbol()
00521 + Power<N, D>::string()
00522 + BSUtilities::IF<Loki::TL::Length<CUTail>::value,
00523 BSUtilities::Blank, BSUtilities::EmptyString>::RET::string()
00524 + Composed<ComposeBase<UT, CTail>,
00525 typename BSUtilities::IF<Loki::TL::Length<CTail>::value
00526 - Loki::TL::Length<CUTail>::value,
00527 UnitListError<true>, CUTail>::RET>::Symbol ();}
00528 static std::string Name (void)
00529 {return ValidUnit<Prefixed<Prefixable<UT1, U1>, UP1>,
00530 UL>::RET::Name()
00531 + Power<N, D>::string()
00532 + BSUtilities::IF<Loki::TL::Length<CUTail>::value,
00533 BSUtilities::Blank, BSUtilities::EmptyString>::RET::string()
00534 + Composed<ComposeBase<UT, CTail>,
00535 typename BSUtilities::IF<Loki::TL::Length<CTail>::value
00536 - Loki::TL::Length<CUTail>::value,
00537 UnitListError<true>, CUTail>::RET>::Name ();}
00538 static bool IsSI (void)
00539 {return ((Prefixable<UT1, U1>::IsSI ()
00540 && Composed<ComposeBase<UT, CTail>,
00541 typename BSUtilities::IF<Loki::TL::Length<CTail>::value
00542 - Loki::TL::Length<CUTail>::value,
00543 UnitListError<true>, CUTail>::RET>::IsSI ()) ? 1 : 0);}
00544 static bool IsExact (void)
00545 {return ((Prefixable<UT1, U1>::IsExact ()
00546 && Composed<ComposeBase<UT, CTail>,
00547 typename BSUtilities::IF<Loki::TL::Length<CTail>::value
00548 - Loki::TL::Length<CUTail>::value,
00549 UnitListError<true>, CUTail>::RET>::IsExact ()) ? 1 : 0);}
00550 };
00551
00553
00586 template<typename UT, typename UL, long N, long D, typename CTail,
00587 typename UT1, typename CL1, typename UL1, typename CUTail>
00588 class Composed<ComposeBase<UT,
00589 Loki::Typelist<Component<UL, BSUtilities::Rational<N, D> >, CTail> >,
00590 Loki::Typelist<Composed<ComposeBase<UT1, CL1>, UL1>, CUTail> >
00591 : public ComposeBase<UT, Loki::Typelist<Component<UL,
00592 BSUtilities::Rational<N, D> >, CTail> >
00593 {
00594 public:
00595 static std::string Symbol (void)
00596 {return BSUtilities::LeftParenthesis::string()
00597 + ValidUnit<Composed<ComposeBase<UT1, CL1>, UL1>,
00598 UL>::RET::Symbol()
00599 + BSUtilities::RightParenthesis::string()
00600 + Power<N, D>::string()
00601 + BSUtilities::IF<Loki::TL::Length<CUTail>::value,
00602 BSUtilities::Blank, BSUtilities::EmptyString>::RET
00603 ::string()
00604 + Composed<ComposeBase<UT, CTail>,
00605 typename BSUtilities::IF<Loki::TL::Length<CTail>::value
00606 - Loki::TL::Length<CUTail>::value,
00607 UnitListError<true>, CUTail>::RET>::Symbol ();}
00608 static std::string Name (void)
00609 {return BSUtilities::LeftParenthesis::string()
00610 + ValidUnit<Composed<ComposeBase<UT1, CL1>, UL1>,
00611 UL>::RET::Name()
00612 + BSUtilities::RightParenthesis::string()
00613 + Power<N, D>::string()
00614 + BSUtilities::IF<Loki::TL::Length<CUTail>::value,
00615 BSUtilities::Blank, BSUtilities::EmptyString>::RET::string()
00616 + Composed<ComposeBase<UT, CTail>,
00617 typename BSUtilities::IF<Loki::TL::Length<CTail>::value
00618 - Loki::TL::Length<CUTail>::value,
00619 UnitListError<true>, CUTail>::RET>::Name ();}
00620 static bool IsSI (void)
00621 {return ((Composed<ComposeBase<UT1, CL1>, UL1>::IsSI ()
00622 && Composed<ComposeBase<UT, CTail>,
00623 typename BSUtilities::IF<Loki::TL::Length<CTail>::value
00624 - Loki::TL::Length<CUTail>::value,
00625 UnitListError<true>, CUTail>::RET>::IsSI ()) ? 1 : 0);}
00626 static bool IsExact (void)
00627 {return ((Composed<ComposeBase<UT1, CL1>, UL1>::IsExact ()
00628 && Composed<ComposeBase<UT, CTail>,
00629 typename BSUtilities::IF<Loki::TL::Length<CTail>::value
00630 - Loki::TL::Length<CUTail>::value,
00631 UnitListError<true>, CUTail>::RET>::IsExact ()) ? 1 : 0);}
00632 };
00633
00635
00643 template<typename UT, typename CL>
00644 class Composed<ComposeBase<UT, CL>, Loki::NullType>
00645 : public ComposeBase<UT, CL>
00646 {
00647 public:
00648 static std::string Symbol (void) {return "";}
00649 static std::string Name (void) {return "";}
00650 static bool IsSI (void) {return true;}
00651 static bool IsExact (void) {return true;}
00652 };
00653
00655
00657
00659
00665 template<typename U, long N = 1l, long D = 1l> struct Standard;
00666
00668
00679 template<typename UT, typename U, long N, long D>
00680 struct Standard<NonPrefixable<UT, U>, N, D>
00681 {
00682 template<typename T>
00683 static T VAL (const T &value)
00684 {return value * std::pow (T(NonPrefixable<UT, U>::Factor ()),
00685 static_cast<double>(N)/static_cast<double>(D));}
00686 };
00687
00689
00701 template<typename UT, typename U, typename P, long N, long D>
00702 struct Standard<Prefixed<Prefixable<UT, U>, P>, N, D>
00703 {
00704 template<typename T>
00705 static T VAL (const T &value)
00706 {return T (value
00707 * std::pow (P::Factor * Prefixable<UT, U>::BaseFactor (),
00708 static_cast<double>(N)/static_cast<double>(D)));}
00709 };
00710
00712
00717 template<typename CL, typename UL> struct StandardComposed;
00718
00720
00732 template<typename CUL, long N, long D, typename CTail,
00733 typename U, typename UTail>
00734 struct StandardComposed<Loki::Typelist<Component<CUL,
00735 BSUtilities::Rational<N, D> >, CTail>, Loki::Typelist<U, UTail> >
00736 {
00737 template<typename T>
00738 static T VAL (const T &value)
00739 {return Standard<U, N, D>::VAL
00740 (StandardComposed<CTail, UTail>::VAL (value));}
00741 };
00742
00744
00750 template<>
00751 struct StandardComposed<Loki::NullType, Loki::NullType>
00752 {
00753 template<typename T> static T VAL (const T &value) {return value;}
00754 };
00755
00757
00772 template<typename UT, typename CL, typename UL, long N, long D>
00773 struct Standard<Composed<ComposeBase<UT, CL>, UL>, N, D>
00774 {
00775 template<typename T>
00776 static T VAL (const T &value)
00777 {return value * std::pow(StandardComposed<CL, UL>::VAL (1.0)
00778 * ComposeBase<UT, CL>::BaseFactor (),
00779 static_cast<double>(N)/static_cast<double>(D));}
00780 };
00781
00783
00785
00787
00793 template<typename U, long N = 1l, long D = 1l> struct Reverse;
00794
00796
00807 template<typename UT, typename U, long N, long D>
00808 struct Reverse<NonPrefixable<UT, U>, N, D>
00809 {
00810 template<typename T>
00811 static T VAL (const T &value)
00812 {return value / (std::pow (T(NonPrefixable<UT, U>::Factor ()),
00813 static_cast<double>(N)/static_cast<double>(D)));}
00814 };
00815
00817
00829 template<typename UT, typename U, typename P, long N, long D>
00830 struct Reverse<Prefixed<Prefixable<UT, U>, P>, N, D>
00831 {
00832 template<typename T>
00833 static T VAL (const T &value)
00834 {return T (value
00835 / std::pow (P::Factor * Prefixable<UT, U>::BaseFactor (),
00836 static_cast<double>(N)/static_cast<double>(D)));}
00837 };
00838
00840
00845 template<typename CL, typename UL> struct ReverseComposed;
00846
00848
00860 template<typename CUL, long N, long D, typename CTail, typename U,
00861 typename UTail>
00862 struct ReverseComposed<Loki::Typelist<Component<CUL,
00863 BSUtilities::Rational<N, D> >, CTail>, Loki::Typelist<U, UTail> >
00864 {
00865 template<typename T>
00866 static T VAL (const T &value)
00867 {return Reverse<U, N, D>::VAL
00868 (ReverseComposed<CTail, UTail>::VAL (value));}
00869 };
00870
00872
00879 template<>
00880 struct ReverseComposed<Loki::NullType, Loki::NullType>
00881 {
00882 template<typename T> static T VAL (const T &value) {return value;}
00883 };
00884
00886
00901 template<typename UT, typename CL, typename UL, long N, long D>
00902 struct Reverse<Composed<ComposeBase<UT, CL>, UL>, N, D>
00903 {
00904 template<typename T>
00905 static T VAL (const T &value)
00906 {return value * std::pow(ReverseComposed<CL, UL>::VAL (1.0)
00907 / ComposeBase<UT, CL>::BaseFactor (),
00908 static_cast<double>(N)/static_cast<double>(D));
00909 }
00910 };
00911
00913
00915
00917
00931 template<typename U, typename UT, typename U1, typename UTail>
00932 struct ValidUnit<U, Loki::Typelist<NonPrefixable<UT, U1>, UTail> >
00933 {
00934 typedef
00935 typename BSUtilities::IF<BSUtilities::SameType<U,
00936 NonPrefixable<UT, U1> >::sameType, U,
00937 typename ValidUnit<U, UTail>::RET >::RET RET;
00938 };
00939
00941
00948 template<typename U, typename PU, typename PL> class ValidPrefixedUnit;
00949
00951
00963 template<typename U, typename UT, typename U1, typename P, typename PTail>
00964 class ValidPrefixedUnit<U, Prefixable<UT, U1>,
00965 Loki::Typelist<Prefix<P>, PTail> >
00966 {
00967 public:
00968 typedef typename BSUtilities::IF<BSUtilities::SameType<U,
00969 Prefixed<Prefixable<UT, U1>, Prefix<P> > >::sameType, U,
00970 typename ValidPrefixedUnit<U, Prefixable<UT, U1>,
00971 PTail>::RET >::RET RET;
00972 };
00973
00975
00982 template<typename U, typename UT, typename U1>
00983 class ValidPrefixedUnit<U, Prefixable<UT, U1>, Loki::NullType>
00984 {
00985 public:
00986 typedef Loki::NullType RET;
00987 };
00988
00990
01005 template<typename U, typename UT, typename U1, typename UTail>
01006 struct ValidUnit<U, Loki::Typelist<Prefixable<UT, U1>, UTail> >
01007 {
01008 typedef typename BSUtilities::IF<BSUtilities::SameType<
01009 typename ValidPrefixedUnit<U, Prefixable<UT, U1>, Prefixes>::RET,
01010 Loki::NullType>::sameType, typename ValidUnit<U, UTail>::RET,
01011 U>::RET RET;
01012 };
01013
01015
01020 template<typename CL, typename UL> struct ComposingUnits;
01021
01023
01035 template<typename CUL, long N, long D, typename CTail, typename U,
01036 typename UTail>
01037 struct ComposingUnits<Loki::Typelist<Component<CUL,
01038 BSUtilities::Rational<N, D> >, CTail>, Loki::Typelist<U, UTail> >
01039 {
01040 typedef Loki::Typelist<typename ValidUnit<U, CUL>::RET,
01041 typename ComposingUnits<CTail, UTail>::RET> RET;
01042 };
01043
01045
01048 template<>
01049 struct ComposingUnits<Loki::NullType, Loki::NullType>
01050 {
01051 typedef Loki::NullType RET;
01052 };
01053
01055
01061 template<typename U, typename CB> struct ValidComposedUnit;
01062
01064
01072 template<typename UT, typename CL, typename UL>
01073 struct ValidComposedUnit<Composed<ComposeBase<UT, CL>, UL>,
01074 ComposeBase<UT, CL> >
01075 {
01076 public:
01077 typedef typename BSUtilities::IF<BSUtilities::SameType<
01078 Composed<ComposeBase<UT, CL>, typename ComposingUnits<CL, UL>::RET>,
01079 Composed<ComposeBase<UT, CL>, UL> >::sameType,
01080 Composed<ComposeBase<UT, CL>, UL>, Loki::NullType>::RET RET;
01081 };
01082
01084
01094 template<typename U, typename UT, typename CL>
01095 struct ValidComposedUnit<U, ComposeBase<UT, CL> >
01096 {
01097 public:
01098 typedef Loki::NullType RET;
01099 };
01100
01102
01108 template<typename U, typename UT>
01109 struct ValidComposedUnit<U, ComposeBase<UT, Loki::NullType> >
01110 {
01111 public:
01112 typedef Loki::NullType RET;
01113 };
01114
01116
01131 template<typename U, typename UT, typename CL, typename UTail>
01132 struct ValidUnit<U, Loki::Typelist<ComposeBase<UT, CL>, UTail> >
01133 {
01134 typedef typename BSUtilities::IF<BSUtilities::SameType<
01135 typename ValidComposedUnit<U, ComposeBase<UT, CL> >::RET,
01136 Loki::NullType>::sameType, typename ValidUnit<U, UTail>::RET,
01137 U>::RET RET;
01138 };
01139
01140
01142
01151 template<typename U>
01152 struct ValidUnit<U, Loki::NullType>
01153 {
01154 typedef InvalidUnit<true> RET;
01155 };
01156
01158
01160
01162
01168 template<typename UL, long N = 1l, long D = 1l> struct standard;
01169
01171
01189 template<typename UT, typename U, typename UTail, long N, long D>
01190 struct standard<Loki::Typelist<NonPrefixable<UT, U>, UTail>, N, D>
01191 {template<typename T>
01192 static T VAL (const T &value, const std::string &symbol)
01193 {if (NonPrefixable<UT, U>::Symbol () == symbol)
01194 return Standard<NonPrefixable<UT, U>, N, D>::VAL (value);
01195 else
01196 return standard<UTail, N, D>::VAL (value, symbol);
01197 }
01198 };
01199
01201
01202
01203
01204
01205
01206
01207
01208 template<typename U, typename PL, long N = 1l, long D = 1l>
01209 struct standardPrefixed;
01210
01212
01231 template<typename UT, typename U1, typename P, typename PTail,
01232 long N, long D>
01233 struct standardPrefixed<Prefixable<UT, U1>,
01234 Loki::Typelist<Prefix<P>, PTail>, N, D>
01235 {
01236 template<typename T>
01237 static T VAL (const T &value, const std::string &symbol)
01238 {if (Prefixed<Prefixable<UT, U1>, Prefix<P> >::Symbol () == symbol)
01239 return Standard<Prefixed<Prefixable<UT, U1>,
01240 Prefix<P> >, N, D>::VAL (value);
01241 else
01242 return standardPrefixed<Prefixable<UT, U1>,
01243 PTail, N, D>::VAL (value, symbol);
01244 }
01245 };
01246
01248
01260 template<typename UT, typename U1, long N, long D>
01261 struct standardPrefixed<Prefixable<UT, U1>, Loki::NullType, N, D>
01262 {
01263 template<typename T>
01264 static T VAL (const T &, const std::string &)
01265 {throw UnitMismatch (); return T (0);}
01266 };
01267
01269
01286 template<typename UT, typename U, typename UTail, long N, long D>
01287 struct standard<Loki::Typelist<Prefixable<UT, U>, UTail>, N, D>
01288 {
01289 template<typename T>
01290 static T VAL (const T &value, const std::string &symbol)
01291 {try {return standardPrefixed <Prefixable<UT, U>, Prefixes, N, D>::VAL
01292 (value, symbol);
01293 }
01294 catch (UnitMismatch)
01295 {return standard<UTail, N, D>::VAL (value, symbol);}
01296 }
01297 };
01298
01300
01301
01302
01303
01304 template<typename CB> struct standardComposed;
01305
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325 template<typename UT, typename CUL, long N, long D, typename CTail>
01326 struct standardComposed<ComposeBase<UT,
01327 Loki::Typelist<Component<CUL, BSUtilities::Rational<N, D> >, CTail> > >
01328 {
01329 template<typename T>
01330 static T VAL (const T &value, std::vector<std::string> &symbols,
01331 std::vector<long> &numerators, std::vector<long> &denominators)
01332 {if ((numerators[0] == N) && (denominators[0] == D))
01333 {std::string symbol = symbols[0];
01334 symbols.erase(symbols.begin());
01335 numerators.erase(numerators.begin());
01336 denominators.erase(denominators.begin());
01337 return standard<CUL, N, D>::VAL
01338 (standardComposed<ComposeBase<UT, CTail> >
01339 ::VAL (value, symbols, numerators, denominators), symbol);
01340 }
01341 else
01342 throw UnitInputError ("invalid exponent in unit symbol!");
01343 }
01344 };
01345
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365 template<typename UT, typename CUL, long N, long D>
01366 struct standardComposed<ComposeBase<UT, Loki::Typelist<Component<CUL,
01367 BSUtilities::Rational<N, D> >, Loki::NullType> > >
01368 {
01369 template<typename T>
01370 static T VAL (const T &value, std::vector<std::string> &symbols,
01371 std::vector<long> &numerators, std::vector<long> &denominators)
01372 {if ((numerators[0] == N) && (denominators[0] == D))
01373 {return standard<CUL, N, D>::VAL (value, symbols[0]);}
01374 else
01375 throw UnitInputError ("invalid exponent in unit symbol!");
01376 }
01377 };
01378
01380
01382 struct ComposedClosure
01383 : boost::spirit::closure<ComposedClosure, std::string>
01384 {
01385 member1 unit;
01386 };
01387
01389
01396 class ComposedGrammar : public boost::spirit::grammar<ComposedGrammar>
01397 {
01398 private:
01400 std::vector<std::string> &symbols;
01402 std::vector<long> &numerators;
01404 std::vector<long> &denominators;
01406 static boost::spirit::int_parser<long> long_p;
01408 static boost::spirit::uint_parser<long> ulong_p;
01409
01410 public:
01412
01414 ComposedGrammar (std::vector<std::string> &_symbols,
01415 std::vector<long> & _numerators, std::vector<long> &_denominators)
01416 : symbols(_symbols), numerators (_numerators),
01417 denominators (_denominators) {}
01418 public:
01420 template<typename ScannerT>
01421 struct definition
01422 {
01423 boost::spirit::rule<ScannerT, ComposedClosure::context_t>
01424 component;
01425 boost::spirit::rule<ScannerT> composed, symbol, composedComponent,
01426 exponent, numerator, denominator;
01427
01428 definition (ComposedGrammar const& self)
01429 {
01430
01431
01432
01433 composed = component("")
01434 [BSUtilities::push_back(phoenix::var(self.symbols),
01435 phoenix::arg1)] % ' ';
01436 component = symbol >> exponent;
01437 exponent = ('^' >> numerator >> (('/' >> denominator)
01438 | boost::spirit::eps_p
01439 [BSUtilities::push_back(phoenix::var(self.denominators),
01440 phoenix::val(1))]))
01441 | boost::spirit::eps_p
01442 [BSUtilities::push_back(phoenix::var(self.numerators),
01443 phoenix::val(1))][BSUtilities::push_back
01444 (phoenix::var(self.denominators), phoenix::val(1))];
01445 numerator =
01446 long_p[BSUtilities::push_back(phoenix::var(self.numerators),
01447 phoenix::arg1)];
01448 denominator = ulong_p
01449 [BSUtilities::push_back(phoenix::var(self.denominators),
01450 phoenix::arg1)];
01451 composedComponent = '(' >> (*(composedComponent |
01452 (boost::spirit::anychar_p - ')')))
01453 [component.unit = phoenix::construct_<std::string>
01454 (phoenix::arg1, phoenix::arg2)] >> ')';
01455 symbol = (+boost::spirit::alpha_p)
01456 [component.unit = phoenix::construct_<std::string>
01457 (phoenix::arg1, phoenix::arg2)] | composedComponent;
01458 }
01459
01460 boost::spirit::rule<ScannerT> const & start (void) const
01461 {return composed;}
01462 };
01463 };
01464
01466
01492 template<typename UT, typename CUL, long N1, long D1,
01493 typename CTail, typename UTail, long N, long D>
01494 struct standard<Loki::Typelist<ComposeBase<UT,
01495 Loki::Typelist<Component<CUL, BSUtilities::Rational<N1, D1> >,
01496 CTail> >, UTail>, N, D>
01497 {
01498 template<typename T>
01499 static T VAL (const T &value, const std::string &symbol)
01500 {try {std::vector<std::string> symbols;
01501 std::vector<long> numerators;
01502 std::vector<long> denominators;
01503 ComposedGrammar cg (symbols, numerators, denominators);
01504 if (boost::spirit::parse(symbol.c_str(), cg).full)
01505 return standardComposed<ComposeBase<UT,
01506 Loki::Typelist<Component<CUL, BSUtilities::Rational<N1, D1> >,
01507 CTail> > >::VAL (value, symbols, numerators, denominators)
01508 * std::pow (ComposeBase<UT, Loki::Typelist<Component<CUL,
01509 BSUtilities::Rational<N1, D1> >, CTail> >::BaseFactor (),
01510 static_cast<double>(N)/static_cast<double>(D));
01511 else
01512 throw UnitSyntaxError ("syntax error in unit symbol!");
01513
01514 }
01515 catch (UnitMismatch)
01516 {return standard<UTail, N, D>::VAL (value, symbol);}
01517 catch (UnitInputError)
01518 {return standard<UTail, N, D>::VAL (value, symbol);}
01519 }
01520 };
01521
01523
01534 template<long N, long D>
01535 struct standard<Loki::NullType, N, D>
01536 {
01537 template<typename T>
01538 static T VAL (const T &, const std::string &)
01539 {throw UnitMismatch ("unit symbol not found!"); return T (0);}
01540 };
01541
01543
01545
01547
01553 template<typename UL, long N = 1l, long D = 1l> struct reverse;
01554
01556
01576 template<typename UT, typename U, typename UTail, long N, long D>
01577 struct reverse<Loki::Typelist<NonPrefixable<UT, U>, UTail>, N, D >
01578 {
01579 template<typename T>
01580 static T VAL (const T &value, const std::string &symbol)
01581 {if (NonPrefixable<UT, U>::Symbol () == symbol)
01582 return Reverse<NonPrefixable<UT, U>, N, D>::VAL (value);
01583 else
01584 return reverse<UTail>::VAL (value, symbol);
01585 }
01586 };
01587
01589
01590
01591
01592
01593
01594
01595
01596
01597 template<typename U, typename PL, long N = 1l, long D = 1l>
01598 struct reversePrefixed;
01599
01601
01620 template<typename UT, typename U1, typename P, typename PTail,
01621 long N, long D>
01622 struct reversePrefixed<Prefixable<UT, U1>,
01623 Loki::Typelist<Prefix<P>, PTail>, N, D>
01624 {
01625 template<typename T>
01626 static T VAL (const T &value, const std::string &symbol)
01627 {if (Prefixed<Prefixable<UT, U1>, Prefix<P> >::Symbol () == symbol)
01628 return Reverse<Prefixed<Prefixable<UT, U1>,
01629 Prefix<P> >, N, D>::VAL (value);
01630 else
01631 return reversePrefixed<Prefixable<UT, U1>,
01632 PTail, N, D>::VAL (value, symbol);
01633 }
01634 };
01635
01637
01649 template<typename UT, typename U1, long N, long D>
01650 struct reversePrefixed<Prefixable<UT, U1>, Loki::NullType, N, D>
01651 {
01652 template<typename T>
01653 static T VAL (const T &, const std::string &)
01654 {throw UnitMismatch (); return T (0);}
01655 };
01656
01658
01676 template<typename UT, typename U, typename UTail, long N, long D>
01677 struct reverse<Loki::Typelist<Prefixable<UT, U>, UTail>, N, D>
01678 {
01679 template<typename T>
01680 static T VAL (const T &value, const std::string &symbol)
01681 {try {return reversePrefixed <Prefixable<UT, U>, Prefixes, N, D>::VAL
01682 (value, symbol);
01683 }
01684 catch (UnitMismatch)
01685 {return reverse<UTail, N, D>::VAL (value, symbol);}
01686 }
01687 };
01688
01690
01691
01692
01693
01694 template<typename CB> struct reverseComposed;
01695
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715 template<typename UT, typename CUL, long N, long D, typename CTail>
01716 struct reverseComposed<ComposeBase<UT,
01717 Loki::Typelist<Component<CUL, BSUtilities::Rational<N, D> >, CTail> > >
01718 {
01719 template<typename T>
01720 static T VAL (const T &value, std::vector<std::string> &symbols,
01721 std::vector<long> &numerators, std::vector<long> &denominators)
01722 {if ((numerators[0] == N) && (denominators[0] == D))
01723 {std::string symbol = symbols[0];
01724 symbols.erase(symbols.begin());
01725 numerators.erase(numerators.begin());
01726 denominators.erase(denominators.begin());
01727 return reverse<CUL, N, D>::VAL
01728 (reverseComposed<ComposeBase<UT, CTail> >
01729 ::VAL (value, symbols, numerators, denominators), symbol);
01730 }
01731 else
01732 throw UnitInputError ("invalid exponent in unit symbol!");
01733 }
01734 };
01735
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755 template<typename UT, typename CUL, long N, long D>
01756 struct reverseComposed<ComposeBase<UT, Loki::Typelist<Component<CUL,
01757 BSUtilities::Rational<N, D> >, Loki::NullType> > >
01758 {
01759 template<typename T>
01760 static T VAL (const T &value, std::vector<std::string> &symbols,
01761 std::vector<long> &numerators, std::vector<long> &denominators)
01762 {if ((numerators[0] == N) && (denominators[0] == D))
01763 {return reverse<CUL, N, D>::VAL (value, symbols[0]);}
01764 else
01765 throw UnitInputError ("invalid exponent in unit symbol!");
01766 }
01767 };
01768
01770
01797 template<typename UT, typename CUL, long N1, long D1,
01798 typename CTail, typename UTail, long N, long D>
01799 struct reverse<Loki::Typelist<ComposeBase<UT,
01800 Loki::Typelist<Component<CUL, BSUtilities::Rational<N1, D1> >,
01801 CTail> >, UTail>, N, D>
01802 {
01803 template<typename T>
01804 static T VAL (const T &value, const std::string &symbol)
01805 {try {std::vector<std::string> symbols;
01806 std::vector<long> numerators;
01807 std::vector<long> denominators;
01808 ComposedGrammar cg (symbols, numerators, denominators);
01809 if (boost::spirit::parse(symbol.c_str(), cg).full)
01810 return reverseComposed<ComposeBase<UT,
01811 Loki::Typelist<Component<CUL, BSUtilities::Rational<N1, D1> >,
01812 CTail> > >::VAL (value, symbols, numerators, denominators)
01813 / std::pow (ComposeBase<UT, Loki::Typelist<Component<CUL,
01814 BSUtilities::Rational<N1, D1> >, CTail> >::BaseFactor (),
01815 static_cast<double>(N)/static_cast<double>(D));
01816 else
01817 throw UnitSyntaxError ("syntax error in unit symbol!");
01818 }
01819 catch (UnitMismatch)
01820 {return reverse<UTail, N, D>::VAL (value, symbol);}
01821 catch (UnitInputError)
01822 {return standard<UTail, N, D>::VAL (value, symbol);}
01823 }
01824 };
01825
01827
01838 template<long N, long D>
01839 struct reverse<Loki::NullType, N, D>
01840 {
01841 template<typename T>
01842 static T VAL (const T &, const std::string &)
01843 {throw UnitMismatch (); return T (0);}
01844 };
01845
01846 }
01847
01848 #endif