#ifndef KLX_UNITS_HPP #define KLX_UNITS_HPP #include #include "common.hpp" //============================================================================ // <> library //============================================================================ namespace klx { //---------------------------------------------------------------------------- // 次元を表すデータ構造 // とりあえず 長さ/質量/時間/電流 の4つをサポートする。 //---------------------------------------------------------------------------- template struct dimension { // 次元 enum { M=Mp, G=Gp, S=Sp, A=Ap }; // 無次元量か否か? enum { is_zero = (Mp|Gp|Sp|Ap)==0 }; }; namespace detail { // 加算 template struct dimension_add { typedef dimension< (Lhs::M + Rhs::M), (Lhs::G + Rhs::G), (Lhs::S + Rhs::S), (Lhs::A + Rhs::A) > t; }; // 減算 template struct dimension_sub { typedef dimension< (Lhs::M - Rhs::M), (Lhs::G - Rhs::G), (Lhs::S - Rhs::S), (Lhs::A - Rhs::A) > t; }; // 正負反転 template struct dimension_neg { typedef dimension< (- Rhs::M), (- Rhs::G), (- Rhs::S), (- Rhs::A) > t; }; // 乗算 template struct dimension_mul { typedef dimension< (Lhs::M * f), (Lhs::G * f), (Lhs::S * f), (Lhs::A * f) > t; }; } //---------------------------------------------------------------------------- // 前宣言など //---------------------------------------------------------------------------- template class physial_value; template class unit; //---------------------------------------------------------------------------- // 次元付き実数値 //---------------------------------------------------------------------------- template class physical_value { private: typedef physical_value this_type; template friend class unit; private: double value; public: physical_value() : value() {} }; //---------------------------------------------------------------------------- // 単位型 // unit< dimension<1,0,0,0> > cm(0.01); // みたいな使い方をする。"1基本単位" * "factor" == "1この単位" //---------------------------------------------------------------------------- template class unit { public: explicit unit(double f) : factor(f) {} explicit unit(physical_value v) : factor(v.value) {} private: const double factor; private: template friend class physical_value; template friend unit::t> operator*( unit, unit ); template friend unit::t> operator/( unit, unit ); template friend unit::t> operator*( double, unit ); template friend unit::t> operator/( double, unit ); }; //---------------------------------------------------------------------------- // 演算 //---------------------------------------------------------------------------- // unit * unit template inline unit::t> operator*( unit ul, unit ur ) { return unit::t>( ul.factor * ur.factor ); } // unit / unit template inline unit::t> operator/( unit ul, unit ur ) { return unit::t>( ul.factor / ur.factor ); } // double * unit template inline physical_value operator*( double v, unit u ) { return physical_value( v, u ); } // double / unit template inline physical_value::t> operator/( double v, unit u ) { return physical_value::tm>( v, unit::t>(1/u.factor) ); } //---------------------------------------------------------------------------- // よく使う単位達 //---------------------------------------------------------------------------- namespace basic_units { namespace length_units { static unit< dimension<1,0,0,0> > km(1000); static unit< dimension<1,0,0,0> > m(1); static unit< dimension<1,0,0,0> > cm(0.01); static unit< dimension<1,0,0,0> > mm(0.001); static unit< dimension<1,0,0,0> > um(0.000001); static unit< dimension<1,0,0,0> > nm(0.000000001); } namespace weight_units { static unit< dimension<0,1,0,0> > kg(1000); static unit< dimension<0,1,0,0> > g(1); static unit< dimension<0,1,0,0> > mg(0.001); } namespace time_units { } using namespace length_units; using namespace weight_units; using namespace time_units; } } // end namespace #endif // INCLUDE_GUARD