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.
347 lines
8.5 KiB
347 lines
8.5 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_DIMENSION_IMPL_HPP |
|
#define BOOST_UNITS_DIMENSION_IMPL_HPP |
|
|
|
#include <boost/mpl/begin_end.hpp> |
|
#include <boost/mpl/deref.hpp> |
|
#include <boost/mpl/if.hpp> |
|
#include <boost/mpl/list.hpp> |
|
#include <boost/mpl/next.hpp> |
|
#include <boost/mpl/size.hpp> |
|
#include <boost/mpl/less.hpp> |
|
|
|
#include <boost/units/config.hpp> |
|
#include <boost/units/dimensionless_type.hpp> |
|
#include <boost/units/static_rational.hpp> |
|
#include <boost/units/units_fwd.hpp> |
|
#include <boost/units/detail/dimension_list.hpp> |
|
#include <boost/units/detail/push_front_if.hpp> |
|
#include <boost/units/detail/push_front_or_add.hpp> |
|
|
|
/// \file |
|
/// \brief Core class and metaprogramming utilities for compile-time dimensional analysis. |
|
|
|
namespace boost { |
|
|
|
namespace units { |
|
|
|
namespace detail { |
|
|
|
template<int N> |
|
struct insertion_sort_dims_insert; |
|
|
|
template<bool is_greater> |
|
struct insertion_sort_dims_comparison_impl; |
|
|
|
// have to recursively add the element to the next sequence. |
|
template<> |
|
struct insertion_sort_dims_comparison_impl<true> { |
|
template<class Begin, int N, class T> |
|
struct apply { |
|
typedef list< |
|
typename Begin::item, |
|
typename insertion_sort_dims_insert<N - 1>::template apply< |
|
typename Begin::next, |
|
T |
|
>::type |
|
> type; |
|
}; |
|
}; |
|
|
|
// either prepend the current element or join it to |
|
// the first remaining element of the sequence. |
|
template<> |
|
struct insertion_sort_dims_comparison_impl<false> { |
|
template<class Begin, int N, class T> |
|
struct apply { |
|
typedef typename push_front_or_add<Begin, T>::type type; |
|
}; |
|
}; |
|
|
|
template<int N> |
|
struct insertion_sort_dims_insert { |
|
template<class Begin, class T> |
|
struct apply { |
|
typedef typename insertion_sort_dims_comparison_impl<mpl::less<typename Begin::item, T>::value>::template apply< |
|
Begin, |
|
N, |
|
T |
|
>::type type; |
|
}; |
|
}; |
|
|
|
template<> |
|
struct insertion_sort_dims_insert<0> { |
|
template<class Begin, class T> |
|
struct apply { |
|
typedef list<T, dimensionless_type> type; |
|
}; |
|
}; |
|
|
|
template<int N> |
|
struct insertion_sort_dims_mpl_sequence { |
|
template<class Begin> |
|
struct apply { |
|
typedef typename insertion_sort_dims_mpl_sequence<N - 1>::template apply<typename mpl::next<Begin>::type>::type next; |
|
typedef typename insertion_sort_dims_insert<(next::size::value)>::template apply<next, typename mpl::deref<Begin>::type>::type type; |
|
}; |
|
}; |
|
|
|
template<> |
|
struct insertion_sort_dims_mpl_sequence<0> { |
|
template<class Begin> |
|
struct apply { |
|
typedef dimensionless_type type; |
|
}; |
|
}; |
|
|
|
template<int N> |
|
struct insertion_sort_dims_impl { |
|
template<class Begin> |
|
struct apply { |
|
typedef typename insertion_sort_dims_impl<N - 1>::template apply<typename Begin::next>::type next; |
|
typedef typename insertion_sort_dims_insert<(next::size::value)>::template apply<next, typename Begin::item>::type type; |
|
}; |
|
}; |
|
|
|
template<> |
|
struct insertion_sort_dims_impl<0> { |
|
template<class Begin> |
|
struct apply { |
|
typedef dimensionless_type type; |
|
}; |
|
}; |
|
|
|
template<class T> |
|
struct sort_dims |
|
{ |
|
typedef typename insertion_sort_dims_mpl_sequence<mpl::size<T>::value>::template apply<typename mpl::begin<T>::type>::type type; |
|
}; |
|
|
|
|
|
template<class T, class Next> |
|
struct sort_dims<list<T, Next> > |
|
{ |
|
typedef typename insertion_sort_dims_impl<list<T, Next>::size::value>::template apply<list<T, Next> >::type type; |
|
}; |
|
|
|
/// sorted sequences can be merged in linear time |
|
template<bool less, bool greater> |
|
struct merge_dimensions_func; |
|
|
|
template<int N1, int N2> |
|
struct merge_dimensions_impl; |
|
|
|
template<> |
|
struct merge_dimensions_func<true, false> |
|
{ |
|
template<typename Begin1, typename Begin2, int N1, int N2> |
|
struct apply |
|
{ |
|
typedef list< |
|
typename Begin1::item, |
|
typename merge_dimensions_impl<N1 - 1, N2>::template apply< |
|
typename Begin1::next, |
|
Begin2 |
|
>::type |
|
> type; |
|
}; |
|
}; |
|
|
|
template<> |
|
struct merge_dimensions_func<false, true> { |
|
template<typename Begin1, typename Begin2, int N1, int N2> |
|
struct apply |
|
{ |
|
typedef list< |
|
typename Begin2::item, |
|
typename merge_dimensions_impl<N2 - 1, N1>::template apply< |
|
typename Begin2::next, |
|
Begin1 |
|
>::type |
|
> type; |
|
}; |
|
}; |
|
|
|
template<> |
|
struct merge_dimensions_func<false, false> { |
|
template<typename Begin1, typename Begin2, int N1, int N2> |
|
struct apply |
|
{ |
|
typedef typename mpl::plus<typename Begin1::item, typename Begin2::item>::type combined; |
|
typedef typename push_front_if<!is_empty_dim<combined>::value>::template apply< |
|
typename merge_dimensions_impl<N1 - 1, N2 - 1>::template apply< |
|
typename Begin1::next, |
|
typename Begin2::next |
|
>::type, |
|
combined |
|
>::type type; |
|
}; |
|
}; |
|
|
|
template<int N1, int N2> |
|
struct merge_dimensions_impl { |
|
template<typename Begin1, typename Begin2> |
|
struct apply |
|
{ |
|
typedef typename Begin1::item dim1; |
|
typedef typename Begin2::item dim2; |
|
|
|
typedef typename merge_dimensions_func<(mpl::less<dim1,dim2>::value == true), |
|
(mpl::less<dim2,dim1>::value == true)>::template apply< |
|
Begin1, |
|
Begin2, |
|
N1, |
|
N2 |
|
>::type type; |
|
}; |
|
}; |
|
|
|
template<typename Sequence1, typename Sequence2> |
|
struct merge_dimensions |
|
{ |
|
typedef typename detail::merge_dimensions_impl<Sequence1::size::value, |
|
Sequence2::size::value>::template |
|
apply< |
|
Sequence1, |
|
Sequence2 |
|
>::type type; |
|
}; |
|
|
|
template<int N> |
|
struct iterator_to_list |
|
{ |
|
template<typename Begin> |
|
struct apply |
|
{ |
|
typedef list< |
|
typename Begin::item, |
|
typename iterator_to_list<N - 1>::template apply< |
|
typename Begin::next |
|
>::type |
|
> type; |
|
}; |
|
}; |
|
|
|
template<> |
|
struct iterator_to_list<0> |
|
{ |
|
template<typename Begin> |
|
struct apply { |
|
typedef dimensionless_type type; |
|
}; |
|
}; |
|
|
|
template<int N> |
|
struct merge_dimensions_impl<N, 0> |
|
{ |
|
template<typename Begin1, typename Begin2> |
|
struct apply |
|
{ |
|
typedef typename iterator_to_list<N>::template apply<Begin1>::type type; |
|
}; |
|
}; |
|
|
|
template<int N> |
|
struct merge_dimensions_impl<0, N> |
|
{ |
|
template<typename Begin1, typename Begin2> |
|
struct apply |
|
{ |
|
typedef typename iterator_to_list<N>::template apply<Begin2>::type type; |
|
}; |
|
}; |
|
|
|
template<> |
|
struct merge_dimensions_impl<0, 0> |
|
{ |
|
template<typename Begin1, typename Begin2> |
|
struct apply |
|
{ |
|
typedef dimensionless_type type; |
|
}; |
|
}; |
|
|
|
template<int N> |
|
struct static_inverse_impl |
|
{ |
|
template<typename Begin> |
|
struct apply { |
|
typedef list< |
|
typename mpl::negate<typename Begin::item>::type, |
|
typename static_inverse_impl<N - 1>::template apply< |
|
typename Begin::next |
|
>::type |
|
> type; |
|
}; |
|
}; |
|
|
|
template<> |
|
struct static_inverse_impl<0> |
|
{ |
|
template<typename Begin> |
|
struct apply |
|
{ |
|
typedef dimensionless_type type; |
|
}; |
|
}; |
|
|
|
template<int N> |
|
struct static_power_impl |
|
{ |
|
template<typename Begin, typename Ex> |
|
struct apply |
|
{ |
|
typedef list< |
|
typename mpl::times<typename Begin::item, Ex>::type, |
|
typename detail::static_power_impl<N - 1>::template apply<typename Begin::next, Ex>::type |
|
> type; |
|
}; |
|
}; |
|
|
|
template<> |
|
struct static_power_impl<0> |
|
{ |
|
template<typename Begin, typename Ex> |
|
struct apply |
|
{ |
|
typedef dimensionless_type type; |
|
}; |
|
}; |
|
|
|
template<int N> |
|
struct static_root_impl { |
|
template<class Begin, class Ex> |
|
struct apply { |
|
typedef list< |
|
typename mpl::divides<typename Begin::item, Ex>::type, |
|
typename detail::static_root_impl<N - 1>::template apply<typename Begin::next, Ex>::type |
|
> type; |
|
}; |
|
}; |
|
|
|
template<> |
|
struct static_root_impl<0> { |
|
template<class Begin, class Ex> |
|
struct apply |
|
{ |
|
typedef dimensionless_type type; |
|
}; |
|
}; |
|
|
|
} // namespace detail |
|
|
|
} // namespace units |
|
|
|
} // namespace boost |
|
|
|
#endif // BOOST_UNITS_DIMENSION_IMPL_HPP
|
|
|