summaryrefslogtreecommitdiff
path: root/boost/units/dimension.hpp
blob: 90334a17df3d4da19d77a5eb2efd45fb34813aa6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// 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) 2007-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_HPP
#define BOOST_UNITS_DIMENSION_HPP

#include <boost/static_assert.hpp>

#include <boost/type_traits/is_same.hpp>

#include <boost/mpl/arithmetic.hpp>

#include <boost/units/static_rational.hpp>
#include <boost/units/detail/dimension_list.hpp>
#include <boost/units/detail/dimension_impl.hpp>

/// \file 
/// \brief Core metaprogramming utilities for compile-time dimensional analysis.

namespace boost {

namespace units {

/// Reduce dimension list to cardinal form. This algorithm collapses duplicate
/// base dimension tags and sorts the resulting list by the tag ordinal value.
/// Dimension lists that resolve to the same dimension are guaranteed to be  
/// represented by an identical type.
///
/// The argument should be an MPL forward sequence containing instances
/// of the @c dim template.
///
/// The result is also an MPL forward sequence.  It also supports the
/// following metafunctions to allow use as a dimension.
///
///    - @c mpl::plus is defined only on two equal dimensions and returns the argument unchanged.
///    - @c mpl::minus is defined only for two equal dimensions and returns the argument unchanged.
///    - @c mpl::negate will return its argument unchanged.
///    - @c mpl::times is defined for any dimensions and adds corresponding exponents.
///    - @c mpl::divides is defined for any dimensions and subtracts the exponents of the
///         right had argument from the corresponding exponents of the left had argument.
///         Missing base dimension tags are assumed to have an exponent of zero.
///    - @c static_power takes a dimension and a static_rational and multiplies all
///         the exponents of the dimension by the static_rational.
///    - @c static_root takes a dimension and a static_rational and divides all
///         the exponents of the dimension by the static_rational.
template<typename Seq>
struct make_dimension_list
{
    typedef typename detail::sort_dims<Seq>::type type;
};

/// Raise a dimension list to a scalar power.
template<typename DL,typename Ex> 
struct static_power
{
    typedef typename detail::static_power_impl<DL::size::value>::template apply<
        DL,
        Ex
    >::type type;    
};

/// Take a scalar root of a dimension list.
template<typename DL,typename Rt> 
struct static_root
{
    typedef typename detail::static_root_impl<DL::size::value>::template apply<
        DL,
        Rt
    >::type type;    
};

} // namespace units

#ifndef BOOST_UNITS_DOXYGEN

namespace mpl {

template<>
struct plus_impl<boost::units::detail::dimension_list_tag,boost::units::detail::dimension_list_tag>
{
    template<class T0, class T1>
    struct apply
    {
        BOOST_STATIC_ASSERT((boost::is_same<T0,T1>::value == true));
        typedef T0 type;
    };
};

template<>
struct minus_impl<boost::units::detail::dimension_list_tag,boost::units::detail::dimension_list_tag>
{
    template<class T0, class T1>
    struct apply
    {
        BOOST_STATIC_ASSERT((boost::is_same<T0,T1>::value == true));
        typedef T0 type;
    };
};

template<>
struct times_impl<boost::units::detail::dimension_list_tag,boost::units::detail::dimension_list_tag>
{
    template<class T0, class T1>
    struct apply
    {
        typedef typename boost::units::detail::merge_dimensions<T0,T1>::type type;
    };
};

template<>
struct divides_impl<boost::units::detail::dimension_list_tag,boost::units::detail::dimension_list_tag>
{
    template<class T0, class T1>
    struct apply
    {
        typedef typename boost::units::detail::merge_dimensions<
            T0,
            typename boost::units::detail::static_inverse_impl<
                T1::size::value
            >::template apply<
                T1
            >::type
        >::type type;
    };
};

template<>
struct negate_impl<boost::units::detail::dimension_list_tag>
{
    template<class T0>
    struct apply
    {
        typedef T0 type;
    };
};

} // namespace mpl

#endif

} // namespace boost

#endif // BOOST_UNITS_DIMENSION_HPP