• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*!
2 @file
3 Adapts `std::ratio` for use with Hana.
4 
5 @copyright Louis Dionne 2013-2017
6 Distributed under the Boost Software License, Version 1.0.
7 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
8  */
9 
10 #ifndef BOOST_HANA_EXT_STD_RATIO_HPP
11 #define BOOST_HANA_EXT_STD_RATIO_HPP
12 
13 #include <boost/hana/bool.hpp>
14 #include <boost/hana/concept/integral_constant.hpp>
15 #include <boost/hana/config.hpp>
16 #include <boost/hana/core/when.hpp>
17 #include <boost/hana/fwd/core/to.hpp>
18 #include <boost/hana/fwd/core/tag_of.hpp>
19 #include <boost/hana/fwd/div.hpp>
20 #include <boost/hana/fwd/equal.hpp>
21 #include <boost/hana/fwd/less.hpp>
22 #include <boost/hana/fwd/minus.hpp>
23 #include <boost/hana/fwd/mod.hpp>
24 #include <boost/hana/fwd/mult.hpp>
25 #include <boost/hana/fwd/one.hpp>
26 #include <boost/hana/fwd/plus.hpp>
27 #include <boost/hana/fwd/zero.hpp>
28 
29 #include <cstdint>
30 #include <ratio>
31 #include <type_traits>
32 
33 
34 #ifdef BOOST_HANA_DOXYGEN_INVOKED
35 namespace std {
36     //! @ingroup group-ext-std
37     //! Adaptation of `std::ratio` for Hana.
38     //!
39     //!
40     //! Modeled concepts
41     //! ----------------
42     //! 1. `Comparable`\n
43     //! `std::ratio`s are compared for equality using `std::ratio_equal`.
44     //! @include example/ext/std/ratio/comparable.cpp
45     //!
46     //! 2. `Orderable`\n
47     //! `std::ratio`s are ordered using `std::ratio_less`.
48     //! @include example/ext/std/ratio/orderable.cpp
49     //!
50     //! 3. `Monoid`, `Group`, `Ring`, and `EuclideanRing`\n
51     //! `std::ratio`s are added, subtracted, multiplied and divided using
52     //! `std::ratio_add`, `std::ratio_subtract`, `std::ratio_multiply` and
53     //! `std::ratio_divide`, respectively. Furthermore, the neutral element
54     //! for the additive operation is `std::ratio<0, 1>{}`, and the neutral
55     //! element for the multiplicative operation is `std::ratio<1, 1>{}`.
56     //! @include example/ext/std/ratio/arithmetic.cpp
57     template <std::intmax_t Num, std::intmax_t Denom>
58     class ratio { };
59 }
60 #endif
61 
62 
63 BOOST_HANA_NAMESPACE_BEGIN
64     namespace ext { namespace std { struct ratio_tag; }}
65 
66     template <std::intmax_t num, std::intmax_t den>
67     struct tag_of<std::ratio<num, den>> {
68         using type = ext::std::ratio_tag;
69     };
70 
71     //////////////////////////////////////////////////////////////////////////
72     // Conversion from IntegralConstants
73     //////////////////////////////////////////////////////////////////////////
74     template <typename C>
75     struct to_impl<ext::std::ratio_tag, C, when<
76         hana::IntegralConstant<C>::value
77     >> {
78         template <typename N>
applyto_impl79         static constexpr auto apply(N const&) {
80             return std::ratio<N::value>{};
81         }
82     };
83 
84     //////////////////////////////////////////////////////////////////////////
85     // Comparable
86     //////////////////////////////////////////////////////////////////////////
87     template <>
88     struct equal_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
89         template <typename R1, typename R2>
applyequal_impl90         static constexpr auto apply(R1 const&, R2 const&)
91         { return hana::bool_c<std::ratio_equal<R1, R2>::value>; }
92     };
93 
94     //////////////////////////////////////////////////////////////////////////
95     // Orderable
96     //////////////////////////////////////////////////////////////////////////
97     template <>
98     struct less_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
99         template <typename R1, typename R2>
applyless_impl100         static constexpr auto apply(R1 const&, R2 const&)
101         { return hana::bool_c<std::ratio_less<R1, R2>::value>; }
102     };
103 
104     //////////////////////////////////////////////////////////////////////////
105     // Monoid
106     //////////////////////////////////////////////////////////////////////////
107     template <>
108     struct plus_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
109         template <typename R1, typename R2>
applyplus_impl110         static constexpr std::ratio_add<R1, R2> apply(R1 const&, R2 const&)
111         { return {}; }
112     };
113 
114     template <>
115     struct zero_impl<ext::std::ratio_tag> {
applyzero_impl116         static constexpr std::ratio<0> apply()
117         { return {}; }
118     };
119 
120     //////////////////////////////////////////////////////////////////////////
121     // Group
122     //////////////////////////////////////////////////////////////////////////
123     template <>
124     struct minus_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
125         template <typename R1, typename R2>
applyminus_impl126         static constexpr std::ratio_subtract<R1, R2> apply(R1 const&, R2 const&)
127         { return {}; }
128     };
129 
130     //////////////////////////////////////////////////////////////////////////
131     // Ring
132     //////////////////////////////////////////////////////////////////////////
133     template <>
134     struct mult_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
135         template <typename R1, typename R2>
applymult_impl136         static constexpr std::ratio_multiply<R1, R2> apply(R1 const&, R2 const&)
137         { return {}; }
138     };
139 
140     template <>
141     struct one_impl<ext::std::ratio_tag> {
applyone_impl142         static constexpr std::ratio<1> apply()
143         { return {}; }
144     };
145 
146     //////////////////////////////////////////////////////////////////////////
147     // EuclideanRing
148     //////////////////////////////////////////////////////////////////////////
149     template <>
150     struct div_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
151         template <typename R1, typename R2>
applydiv_impl152         static constexpr std::ratio_divide<R1, R2> apply(R1 const&, R2 const&)
153         { return {}; }
154     };
155 
156     template <>
157     struct mod_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
158         template <typename R1, typename R2>
applymod_impl159         static constexpr std::ratio<0> apply(R1 const&, R2 const&)
160         { return {}; }
161     };
162 BOOST_HANA_NAMESPACE_END
163 
164 #endif // !BOOST_HANA_EXT_STD_RATIO_HPP
165