You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
440 lines
13 KiB
440 lines
13 KiB
// 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
|
|
|