441 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			441 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| // Boost.Units - A C++ library for zero-overhead dimensional analysis and 
 | |
| // unit/quantity manipulation and conversion
 | |
| //
 | |
| // Copyright (C) 2003-2008 Matthias Christian Schabel
 | |
| // Copyright (C) 2008 Steven Watanabe
 | |
| //
 | |
| // Distributed under the Boost Software License, Version 1.0. (See
 | |
| // accompanying file LICENSE_1_0.txt or copy at
 | |
| // http://www.boost.org/LICENSE_1_0.txt)
 | |
| 
 | |
| #ifndef BOOST_UNITS_UNIT_HPP
 | |
| #define BOOST_UNITS_UNIT_HPP
 | |
| 
 | |
| #include <boost/static_assert.hpp>
 | |
| #include <boost/mpl/bool.hpp>
 | |
| #include <boost/mpl/assert.hpp>
 | |
| #include <boost/type_traits/is_same.hpp>
 | |
| 
 | |
| #include <boost/units/config.hpp>
 | |
| #include <boost/units/dimension.hpp>
 | |
| #include <boost/units/operators.hpp>
 | |
| #include <boost/units/units_fwd.hpp>
 | |
| #include <boost/units/homogeneous_system.hpp>
 | |
| #include <boost/units/heterogeneous_system.hpp>
 | |
| #include <boost/units/is_dimension_list.hpp>
 | |
| #include <boost/units/reduce_unit.hpp>
 | |
| #include <boost/units/static_rational.hpp>
 | |
| 
 | |
| namespace boost {
 | |
| 
 | |
| namespace units { 
 | |
| 
 | |
| /// class representing a model-dependent unit with no associated value
 | |
| 
 | |
| /// (e.g. meters, Kelvin, feet, etc...)
 | |
| template<class Dim,class System, class Enable>
 | |
| class unit
 | |
| {
 | |
|     public:
 | |
|         typedef unit<Dim, System>   unit_type;
 | |
|         typedef unit<Dim,System>    this_type;
 | |
|         typedef Dim                 dimension_type; 
 | |
|         typedef System              system_type;
 | |
|         
 | |
|         unit() { }
 | |
|         unit(const this_type&) { }
 | |
|         //~unit() { }  
 | |
|        
 | |
|         this_type& operator=(const this_type&) { return *this; }
 | |
|         
 | |
|         // sun will ignore errors resulting from templates
 | |
|         // instantiated in the return type of a function.
 | |
|         // Make sure that we get an error anyway by putting.
 | |
|         // the check in the destructor.
 | |
|         #ifdef __SUNPRO_CC
 | |
|         ~unit() {
 | |
|             BOOST_MPL_ASSERT((detail::check_system<System, Dim>));
 | |
|             BOOST_MPL_ASSERT((is_dimension_list<Dim>));
 | |
|         }
 | |
|         #else
 | |
|     private:
 | |
|         BOOST_MPL_ASSERT((detail::check_system<System, Dim>));
 | |
|         BOOST_MPL_ASSERT((is_dimension_list<Dim>));
 | |
|         #endif
 | |
| };
 | |
| 
 | |
| }
 | |
| 
 | |
| }
 | |
| 
 | |
| #if BOOST_UNITS_HAS_BOOST_TYPEOF
 | |
| 
 | |
| #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
 | |
| 
 | |
| BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::unit, 2)
 | |
| 
 | |
| #endif
 | |
| 
 | |
| namespace boost {
 | |
| 
 | |
| namespace units {
 | |
| 
 | |
| /// Returns a unique type for every unit.
 | |
| template<class Dim, class System>
 | |
| struct reduce_unit<unit<Dim, System> >
 | |
| {
 | |
|     typedef unit<
 | |
|         Dim,
 | |
|         typename detail::make_heterogeneous_system<
 | |
|             Dim,
 | |
|             System
 | |
|         >::type
 | |
|     > type;
 | |
| };
 | |
| 
 | |
| /// INTERNAL ONLY
 | |
| template<class S1,class S2> 
 | |
| struct is_implicitly_convertible :
 | |
|     boost::is_same<typename reduce_unit<S1>::type, typename reduce_unit<S2>::type>
 | |
| { };
 | |
| 
 | |
| /// unit unary plus typeof helper
 | |
| /// INTERNAL ONLY
 | |
| template<class Dim,class System>
 | |
| struct unary_plus_typeof_helper< unit<Dim,System> >
 | |
| {
 | |
|     typedef unit<Dim,System>    type;
 | |
| };
 | |
| 
 | |
| /// unit unary minus typeof helper
 | |
| /// INTERNAL ONLY
 | |
| template<class Dim,class System>
 | |
| struct unary_minus_typeof_helper< unit<Dim,System> >
 | |
| {
 | |
|     typedef unit<Dim,System>    type;
 | |
| };
 | |
| 
 | |
| /// unit add typeof helper
 | |
| /// INTERNAL ONLY
 | |
| template<class Dim,
 | |
|          class System>
 | |
| struct add_typeof_helper< unit<Dim,System>,unit<Dim,System> >
 | |
| {
 | |
|     typedef unit<Dim,System> type;
 | |
| };
 | |
| 
 | |
| /// unit subtract typeof helper
 | |
| /// INTERNAL ONLY
 | |
| template<class Dim,
 | |
|          class System>
 | |
| struct subtract_typeof_helper< unit<Dim,System>,unit<Dim,System> >
 | |
| {
 | |
|     typedef unit<Dim,System>   type;
 | |
| };
 | |
| 
 | |
| /// unit multiply typeof helper for two identical homogeneous systems
 | |
| /// INTERNAL ONLY
 | |
| template<class Dim1,
 | |
|          class Dim2,
 | |
|          class System>
 | |
| struct multiply_typeof_helper< unit<Dim1,homogeneous_system<System> >,
 | |
|                                unit<Dim2,homogeneous_system<System> > >
 | |
| {
 | |
|     typedef unit<typename mpl::times<Dim1,Dim2>::type,homogeneous_system<System> >    type;
 | |
| };
 | |
| 
 | |
| /// unit multiply typeof helper for two different homogeneous systems
 | |
| /// INTERNAL ONLY
 | |
| template<class Dim1,
 | |
|          class Dim2,
 | |
|          class System1,
 | |
|          class System2>
 | |
| struct multiply_typeof_helper< unit<Dim1,homogeneous_system<System1> >,
 | |
|                                unit<Dim2,homogeneous_system<System2> > >
 | |
| {
 | |
|     typedef unit<
 | |
|         typename mpl::times<Dim1,Dim2>::type,
 | |
|         typename detail::multiply_systems<
 | |
|             typename detail::make_heterogeneous_system<Dim1, System1>::type,
 | |
|             typename detail::make_heterogeneous_system<Dim2, System2>::type
 | |
|         >::type
 | |
|     > type;
 | |
| };
 | |
| 
 | |
| /// unit multiply typeof helper for a heterogeneous and a homogeneous system
 | |
| /// INTERNAL ONLY
 | |
| template<class Dim1,
 | |
|          class Dim2,
 | |
|          class System1,
 | |
|          class System2>
 | |
| struct multiply_typeof_helper< unit<Dim1,heterogeneous_system<System1> >,
 | |
|                                unit<Dim2,homogeneous_system<System2> > >
 | |
| {
 | |
|     typedef unit<
 | |
|         typename mpl::times<Dim1,Dim2>::type,
 | |
|         typename detail::multiply_systems<
 | |
|             heterogeneous_system<System1>,
 | |
|             typename detail::make_heterogeneous_system<Dim2, System2>::type
 | |
|         >::type
 | |
|     > type;
 | |
| };
 | |
| 
 | |
| /// unit multiply typeof helper for a homogeneous and a heterogeneous system
 | |
| /// INTERNAL ONLY
 | |
| template<class Dim1,
 | |
|          class Dim2,
 | |
|          class System1,
 | |
|          class System2>
 | |
| struct multiply_typeof_helper< unit<Dim1,homogeneous_system<System1> >,
 | |
|                                unit<Dim2,heterogeneous_system<System2> > >
 | |
| {
 | |
|     typedef unit<
 | |
|         typename mpl::times<Dim1,Dim2>::type,
 | |
|         typename detail::multiply_systems<
 | |
|             typename detail::make_heterogeneous_system<Dim1, System1>::type,
 | |
|             heterogeneous_system<System2>
 | |
|         >::type
 | |
|     > type;
 | |
| };
 | |
| 
 | |
| /// unit multiply typeof helper for two heterogeneous systems
 | |
| /// INTERNAL ONLY
 | |
| template<class Dim1,
 | |
|          class Dim2,
 | |
|          class System1,
 | |
|          class System2>
 | |
| struct multiply_typeof_helper< unit<Dim1,heterogeneous_system<System1> >,
 | |
|                                unit<Dim2,heterogeneous_system<System2> > >
 | |
| {
 | |
|     typedef unit<
 | |
|         typename mpl::times<Dim1,Dim2>::type,
 | |
|         typename detail::multiply_systems<
 | |
|             heterogeneous_system<System1>,
 | |
|             heterogeneous_system<System2>
 | |
|         >::type
 | |
|     > type;
 | |
| };
 | |
| 
 | |
| /// unit divide typeof helper for two identical homogeneous systems
 | |
| /// INTERNAL ONLY
 | |
| template<class Dim1,
 | |
|          class Dim2,
 | |
|          class System>
 | |
| struct divide_typeof_helper< unit<Dim1,homogeneous_system<System> >,
 | |
|                              unit<Dim2,homogeneous_system<System> > >
 | |
| {
 | |
|     typedef unit<typename mpl::divides<Dim1,Dim2>::type,homogeneous_system<System> >    type;
 | |
| };
 | |
| 
 | |
| /// unit divide typeof helper for two different homogeneous systems
 | |
| /// INTERNAL ONLY
 | |
| template<class Dim1,
 | |
|          class Dim2,
 | |
|          class System1,
 | |
|          class System2>
 | |
| struct divide_typeof_helper< unit<Dim1,homogeneous_system<System1> >,
 | |
|                              unit<Dim2,homogeneous_system<System2> > >
 | |
| {
 | |
|     typedef unit<
 | |
|         typename mpl::divides<Dim1,Dim2>::type,
 | |
|         typename detail::divide_systems<
 | |
|             typename detail::make_heterogeneous_system<Dim1, System1>::type,
 | |
|             typename detail::make_heterogeneous_system<Dim2, System2>::type
 | |
|         >::type
 | |
|     > type;
 | |
| };
 | |
| 
 | |
| /// unit divide typeof helper for a heterogeneous and a homogeneous system
 | |
| /// INTERNAL ONLY
 | |
| template<class Dim1,
 | |
|          class Dim2,
 | |
|          class System1,
 | |
|          class System2>
 | |
| struct divide_typeof_helper< unit<Dim1,heterogeneous_system<System1> >,
 | |
|                              unit<Dim2,homogeneous_system<System2> > >
 | |
| {
 | |
|     typedef unit<
 | |
|         typename mpl::divides<Dim1,Dim2>::type,
 | |
|         typename detail::divide_systems<
 | |
|             heterogeneous_system<System1>,
 | |
|             typename detail::make_heterogeneous_system<Dim2, System2>::type
 | |
|         >::type
 | |
|     > type;
 | |
| };
 | |
| 
 | |
| /// unit divide typeof helper for a homogeneous and a heterogeneous system
 | |
| /// INTERNAL ONLY
 | |
| template<class Dim1,
 | |
|          class Dim2,
 | |
|          class System1,
 | |
|          class System2>
 | |
| struct divide_typeof_helper< unit<Dim1,homogeneous_system<System1> >,
 | |
|                              unit<Dim2,heterogeneous_system<System2> > >
 | |
| {
 | |
|     typedef unit<
 | |
|         typename mpl::divides<Dim1,Dim2>::type,
 | |
|         typename detail::divide_systems<
 | |
|             typename detail::make_heterogeneous_system<Dim1, System1>::type,
 | |
|             heterogeneous_system<System2>
 | |
|         >::type
 | |
|     > type;
 | |
| };
 | |
| 
 | |
| /// unit divide typeof helper for two heterogeneous systems
 | |
| /// INTERNAL ONLY
 | |
| template<class Dim1,
 | |
|          class Dim2,
 | |
|          class System1,
 | |
|          class System2>
 | |
| struct divide_typeof_helper< unit<Dim1,heterogeneous_system<System1> >,
 | |
|                              unit<Dim2,heterogeneous_system<System2> > >
 | |
| {
 | |
|     typedef unit<
 | |
|         typename mpl::divides<Dim1,Dim2>::type,
 | |
|         typename detail::divide_systems<
 | |
|             heterogeneous_system<System1>,
 | |
|             heterogeneous_system<System2>
 | |
|         >::type
 | |
|     > type;
 | |
| };
 | |
| 
 | |
| /// raise unit to a @c static_rational power
 | |
| template<class Dim,class System,long N,long D> 
 | |
| struct power_typeof_helper<unit<Dim,System>,static_rational<N,D> >                
 | |
| { 
 | |
|     typedef unit<typename static_power<Dim,static_rational<N,D> >::type,typename static_power<System, static_rational<N,D> >::type>     type; 
 | |
|     
 | |
|     static type value(const unit<Dim,System>&)  
 | |
|     { 
 | |
|         return type();
 | |
|     }
 | |
| };
 | |
| 
 | |
| /// take the @c static_rational root of a unit
 | |
| template<class Dim,class System,long N,long D> 
 | |
| struct root_typeof_helper<unit<Dim,System>,static_rational<N,D> >                
 | |
| { 
 | |
|     typedef unit<typename static_root<Dim,static_rational<N,D> >::type,typename static_root<System, static_rational<N,D> >::type>      type; 
 | |
|     
 | |
|     static type value(const unit<Dim,System>&)  
 | |
|     { 
 | |
|         return type();
 | |
|     }
 | |
| };
 | |
| 
 | |
| /// unit runtime unary plus
 | |
| template<class Dim,class System>
 | |
| typename unary_plus_typeof_helper< unit<Dim,System> >::type
 | |
| operator+(const unit<Dim,System>&)
 | |
| { 
 | |
|     typedef typename unary_plus_typeof_helper< unit<Dim,System> >::type type;
 | |
|     
 | |
|     return type();
 | |
| }
 | |
| 
 | |
| /// unit runtime unary minus
 | |
| template<class Dim,class System>
 | |
| typename unary_minus_typeof_helper< unit<Dim,System> >::type
 | |
| operator-(const unit<Dim,System>&)
 | |
| { 
 | |
|     typedef typename unary_minus_typeof_helper< unit<Dim,System> >::type    type;
 | |
|     
 | |
|     return type();
 | |
| }
 | |
| 
 | |
| /// runtime add two units
 | |
| template<class Dim1,
 | |
|          class Dim2,
 | |
|          class System1,
 | |
|          class System2>
 | |
| typename add_typeof_helper< unit<Dim1,System1>,
 | |
|                             unit<Dim2,System2> >::type
 | |
| operator+(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
 | |
| {
 | |
|     BOOST_STATIC_ASSERT((boost::is_same<System1,System2>::value == true));
 | |
|     
 | |
|     typedef System1                                                     system_type;
 | |
|     typedef typename add_typeof_helper< unit<Dim1,system_type>,
 | |
|                                         unit<Dim2,system_type> >::type  type;
 | |
|     
 | |
|     return type();
 | |
| }
 | |
| 
 | |
| /// runtime subtract two units
 | |
| template<class Dim1,
 | |
|          class Dim2,
 | |
|          class System1,
 | |
|          class System2>
 | |
| typename subtract_typeof_helper< unit<Dim1,System1>,
 | |
|                                  unit<Dim2,System2> >::type
 | |
| operator-(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
 | |
| {
 | |
|     BOOST_STATIC_ASSERT((boost::is_same<System1,System2>::value == true));
 | |
|     
 | |
|     typedef System1                                                         system_type;
 | |
|     typedef typename subtract_typeof_helper< unit<Dim1,system_type>,
 | |
|                                              unit<Dim2,system_type> >::type type;
 | |
|     
 | |
|     return type();
 | |
| }
 | |
| 
 | |
| /// runtime multiply two units
 | |
| template<class Dim1,
 | |
|          class Dim2,
 | |
|          class System1,
 | |
|          class System2>
 | |
| typename multiply_typeof_helper< unit<Dim1,System1>,
 | |
|                                  unit<Dim2,System2> >::type
 | |
| operator*(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
 | |
| {
 | |
|     typedef typename multiply_typeof_helper< unit<Dim1,System1>,
 | |
|                                              unit<Dim2,System2> >::type type;
 | |
|     
 | |
|     return type();
 | |
| }
 | |
| 
 | |
| /// runtime divide two units
 | |
| template<class Dim1,
 | |
|          class Dim2,
 | |
|          class System1,
 | |
|          class System2>
 | |
| typename divide_typeof_helper< unit<Dim1,System1>,
 | |
|                                unit<Dim2,System2> >::type
 | |
| operator/(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
 | |
| {
 | |
|     typedef typename divide_typeof_helper< unit<Dim1,System1>,
 | |
|                                            unit<Dim2,System2> >::type   type;
 | |
|     
 | |
|     return type();
 | |
| }
 | |
| 
 | |
| /// unit runtime @c operator==
 | |
| template<class Dim1,
 | |
|          class Dim2,
 | |
|          class System1,
 | |
|          class System2>
 | |
| inline
 | |
| bool 
 | |
| operator==(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
 | |
| {
 | |
|     return boost::is_same<typename reduce_unit<unit<Dim1,System1> >::type, typename reduce_unit<unit<Dim2,System2> >::type>::value;
 | |
| }
 | |
| 
 | |
| /// unit runtime @c operator!=
 | |
| template<class Dim1,
 | |
|          class Dim2,
 | |
|          class System1,
 | |
|          class System2>
 | |
| inline
 | |
| bool 
 | |
| operator!=(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
 | |
| {
 | |
|     return !boost::is_same<typename reduce_unit<unit<Dim1,System1> >::type, typename reduce_unit<unit<Dim2,System2> >::type>::value;
 | |
| }
 | |
| 
 | |
| } // namespace units
 | |
| 
 | |
| } // namespace boost
 | |
| 
 | |
| #endif // BOOST_UNITS_UNIT_HPP
 | 
