1 // (C) Copyright Gennadiy Rozental 2011-2014.
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5
6 // See http://www.boost.org/libs/test for the library home page.
7 //
8 ///@file
9 /// Defines monomorphic dataset n+m dimentional *. Samples in this
10 /// dataset is grid of elements in DS1 and DS2. There will be total
11 /// |DS1| * |DS2| samples
12 // ***************************************************************************
13
14 #ifndef BOOST_TEST_DATA_MONOMORPHIC_GRID_HPP_101512GER
15 #define BOOST_TEST_DATA_MONOMORPHIC_GRID_HPP_101512GER
16
17 // Boost.Test
18 #include <boost/test/data/config.hpp>
19
20
21 #if !defined(BOOST_TEST_NO_GRID_COMPOSITION_AVAILABLE) || defined(BOOST_TEST_DOXYGEN_DOC__)
22
23 #include <boost/test/data/monomorphic/dataset.hpp>
24 #include <boost/test/detail/suppress_warnings.hpp>
25
26 //____________________________________________________________________________//
27
28 namespace boost {
29 namespace unit_test {
30 namespace data {
31 namespace monomorphic {
32
33 namespace ds_detail {
34
35 // !! ?? variadic template implementation; use forward_as_tuple?
36 template<typename T1, typename T2>
37 struct grid_traits {
38 typedef std::tuple<T1,T2> type;
39 typedef typename monomorphic::traits<type>::ref_type ref_type;
40
41 static ref_type
tuple_mergeboost::unit_test::data::monomorphic::ds_detail::grid_traits42 tuple_merge(T1 const& a1, T2 const& a2)
43 {
44 return ref_type(a1,a2);
45 }
46 };
47
48 //____________________________________________________________________________//
49
50 template<typename T1, typename T2,typename T3>
51 struct grid_traits<T1,std::tuple<T2,T3>> {
52 typedef std::tuple<T1,T2,T3> type;
53 typedef typename monomorphic::traits<type>::ref_type ref_type;
54
55 static ref_type
tuple_mergeboost::unit_test::data::monomorphic::ds_detail::grid_traits56 tuple_merge(T1 const& a1, std::tuple<T2 const&,T3 const&> const& a2)
57 {
58 return ref_type(a1,get<0>(a2),get<1>(a2));
59 }
60 };
61
62 //____________________________________________________________________________//
63
64 template<typename T1, typename T2,typename T3>
65 struct grid_traits<std::tuple<T1,T2>,T3> {
66 typedef std::tuple<T1,T2,T3> type;
67 typedef typename monomorphic::traits<type>::ref_type ref_type;
68
69 static ref_type
tuple_mergeboost::unit_test::data::monomorphic::ds_detail::grid_traits70 tuple_merge(std::tuple<T1 const&,T2 const&> const& a1, T3 const& a2)
71 {
72 return ref_type(get<0>(a1),get<1>(a1),a2);
73 }
74 };
75
76 //____________________________________________________________________________//
77
78 } // namespace ds_detail
79
80 // ************************************************************************** //
81 // ************** grid ************** //
82 // ************************************************************************** //
83
84
85 //! Implements the dataset resulting from a cartesian product/grid operation on datasets.
86 //!
87 //! The arity of the resulting dataset is the sum of the arity of its operands.
88 template<typename DS1, typename DS2>
89 class grid : public monomorphic::dataset<typename ds_detail::grid_traits<typename boost::decay<DS1>::type::data_type,
90 typename boost::decay<DS2>::type::data_type>::type> {
91 typedef typename boost::decay<DS1>::type::data_type T1;
92 typedef typename boost::decay<DS2>::type::data_type T2;
93
94 typedef typename monomorphic::dataset<T1>::iter_ptr ds1_iter_ptr;
95 typedef typename monomorphic::dataset<T2>::iter_ptr ds2_iter_ptr;
96
97 typedef typename ds_detail::grid_traits<T1,T2>::type T;
98 typedef monomorphic::dataset<T> base;
99 typedef typename base::iter_ptr iter_ptr;
100
101 struct iterator : public base::iterator {
102 typedef typename monomorphic::traits<T>::ref_type ref_type;
103
104 // Constructor
iteratorboost::unit_test::data::monomorphic::grid::iterator105 explicit iterator( ds1_iter_ptr iter1, DS2 const& ds2 )
106 : m_iter1( iter1 )
107 , m_iter2( ds2.begin() )
108 , m_ds2( ds2 )
109 , m_ds2_pos( 0 )
110 {}
111
112 // forward iterator interface
operator *boost::unit_test::data::monomorphic::grid::iterator113 virtual ref_type operator*() { return ds_detail::grid_traits<T1,T2>::tuple_merge( **m_iter1, **m_iter2 ); }
operator ++boost::unit_test::data::monomorphic::grid::iterator114 virtual void operator++()
115 {
116 ++m_ds2_pos;
117 if( m_ds2_pos != m_ds2.size() )
118 ++(*m_iter2);
119 else {
120 m_ds2_pos = 0;
121 ++(*m_iter1);
122 m_iter2 = m_ds2.begin();
123 }
124 }
125
126 private:
127 // Data members
128 ds1_iter_ptr m_iter1;
129 ds2_iter_ptr m_iter2;
130 DS2 const& m_ds2;
131 data::size_t m_ds2_pos;
132 };
133
134 public:
135 enum { arity = boost::decay<DS1>::type::arity + boost::decay<DS2>::type::arity };
136
137 //! Constructor
grid(DS1 && ds1,DS2 && ds2)138 grid( DS1&& ds1, DS2&& ds2 )
139 : m_ds1( std::forward<DS1>( ds1 ) )
140 , m_ds2( std::forward<DS2>( ds2 ) )
141 {}
142
143 //! Move constructor
grid(grid && j)144 grid( grid&& j )
145 : m_ds1( std::forward<DS1>( j.m_ds1 ) )
146 , m_ds2( std::forward<DS2>( j.m_ds2 ) )
147 {}
148
149 // dataset interface
size() const150 virtual data::size_t size() const { return m_ds1.size() * m_ds2.size(); }
begin() const151 virtual iter_ptr begin() const { return boost::make_shared<iterator>( m_ds1.begin(), m_ds2 ); }
152
153 private:
154 // Data members
155 DS1 m_ds1;
156 DS2 m_ds2;
157 };
158
159 //____________________________________________________________________________//
160
161 // A grid dataset is a dataset
162 template<typename DS1, typename DS2>
163 struct is_dataset<grid<DS1,DS2> > : mpl::true_ {};
164
165 //____________________________________________________________________________//
166
167 namespace result_of {
168
169 /// Result type of the grid operation on dataset.
170 template<typename DS1Gen, typename DS2Gen>
171 struct grid {
172 typedef monomorphic::grid<typename DS1Gen::type,typename DS2Gen::type> type;
173 };
174
175 } // namespace result_of
176
177 //____________________________________________________________________________//
178
179
180
181 //! Grid operation
182 template<typename DS1, typename DS2>
183 inline typename boost::lazy_enable_if_c<is_dataset<DS1>::value && is_dataset<DS2>::value,
184 result_of::grid<mpl::identity<DS1>,mpl::identity<DS2>>
185 >::type
operator *(DS1 && ds1,DS2 && ds2)186 operator*( DS1&& ds1, DS2&& ds2 )
187 {
188 BOOST_TEST_DS_ASSERT( !ds1.size().is_inf() && !ds2.size().is_inf(), "Grid dimension can't have infinite size" );
189
190 return grid<DS1,DS2>( std::forward<DS1>( ds1 ), std::forward<DS2>( ds2 ) );
191 }
192
193 //! @overload boost::unit_test::data::operator*
194 template<typename DS1, typename DS2>
195 inline typename boost::lazy_enable_if_c<is_dataset<DS1>::value && !is_dataset<DS2>::value,
196 result_of::grid<mpl::identity<DS1>,data::result_of::make<DS2>>
197 >::type
operator *(DS1 && ds1,DS2 && ds2)198 operator*( DS1&& ds1, DS2&& ds2 )
199 {
200 return std::forward<DS1>(ds1) * data::make(std::forward<DS2>(ds2));
201 }
202
203 //! @overload boost::unit_test::data::operator*
204 template<typename DS1, typename DS2>
205 inline typename boost::lazy_enable_if_c<!is_dataset<DS1>::value && is_dataset<DS2>::value,
206 result_of::grid<data::result_of::make<DS1>,mpl::identity<DS2>>
207 >::type
operator *(DS1 && ds1,DS2 && ds2)208 operator*( DS1&& ds1, DS2&& ds2 )
209 {
210 return data::make(std::forward<DS1>(ds1)) * std::forward<DS2>(ds2);
211 }
212
213 //____________________________________________________________________________//
214
215 } // namespace monomorphic
216
217 } // namespace data
218 } // namespace unit_test
219 } // namespace boost
220
221 #include <boost/test/detail/enable_warnings.hpp>
222
223 #endif // BOOST_TEST_NO_GRID_COMPOSITION_AVAILABLE
224
225 #endif // BOOST_TEST_DATA_MONOMORPHIC_GRID_HPP_101512GER
226
227