-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathproduct.h
More file actions
259 lines (213 loc) · 7.35 KB
/
product.h
File metadata and controls
259 lines (213 loc) · 7.35 KB
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
/*
* Chris Welshman 2014
*/
#ifndef INCLUDED_PRODUCT
#define INCLUDED_PRODUCT
#include <type_traits>
#include <utility>
#include <iterator>
template<typename It1,typename It2>
struct product_iterator {
typedef typename std::iterator_traits<It1>::value_type value_type_1;
typedef typename std::iterator_traits<It1>::reference reference_1;
typedef typename std::iterator_traits<It1>::difference_type difference_type_1;
typedef typename std::iterator_traits<It1>::iterator_category iterator_category_1;
typedef std::pair<It1,It1> pair_type_1;
typedef typename std::iterator_traits<It2>::value_type value_type_2;
typedef typename std::iterator_traits<It2>::reference reference_2;
typedef typename std::iterator_traits<It2>::difference_type difference_type_2;
typedef typename std::iterator_traits<It2>::iterator_category iterator_category_2;
typedef std::pair<It2,It2> pair_type_2;
typedef std::pair<value_type_1,value_type_2> value_type;
typedef std::pair<reference_1,reference_2> reference;
typedef std::pair<It1,It2> pair_type;
typedef const pair_type* pointer;
typedef std::pair<pair_type_1,pair_type_2> range_type;
//typedef typename std::common_type<difference_type_1,difference_type_2>::type difference_type; // fatal error C1001: An internal error has occurred in the compiler.
typedef difference_type_2 difference_type;
typedef iterator_category_2 iterator_category;
product_iterator() = default;
explicit product_iterator( const range_type& range ) : range(range) {
pair.first = range.first.first;
pair.second = range.second.first;
}
product_iterator( const pair_type_1& range_1, const pair_type_2& range_2 ) : product_iterator(range_type(range_1,range_2)) {}
product_iterator( const range_type& range, const pair_type& pair ) : range(range), pair(pair) {}
reference operator*() const {
return reference( *pair.first, *pair.second );
}
pointer operator->() const {
return &pair;
}
reference_1 first() const {
return reference_1( *pair.first );
}
reference_2 second() const {
return reference_2( *pair.second );
}
product_iterator<It1,It2>& operator++() {
++pair.second;
if( pair.second == range.second.second ) {
++pair.first;
pair.second = range.second.first;
}
return *this;
}
product_iterator<It1,It2> operator++(int) {
product_iterator<It1,It2> temp = *this;
++(*this);
return temp;
}
product_iterator<It1,It2>& operator--() {
if( pair.second == range.second.first ) {
pair.second = range.second.second;
--pair.first;
} else {
--pair.second;
}
return *this;
}
product_iterator<It1,It2> operator--(int) {
product_iterator<It1,It2> temp = *this;
--(*this);
return temp;
}
product_iterator<It1,It2>& operator+=( difference_type offset ) {
difference_type N2 = std::distance( range.second.first, range.second.second );
difference_type k = index(N2) + offset;
difference_type i = k / N2;
difference_type j = k % N2;
pair.first = range.first.first + i;
pair.second = range.second.first + j;
return *this;
}
product_iterator<It1,It2> operator+( difference_type offset ) const {
product_iterator<It1,It2> temp = *this;
return temp += offset;
}
product_iterator<It1,It2>& operator-=( difference_type offset ) {
return *this += -offset;
}
product_iterator<It1,It2> operator-( difference_type offset ) const {
product_iterator<It1,It2> temp = *this;
return temp -= offset;
}
difference_type operator-( const product_iterator<It1,It2>& rhs ) const {
difference_type dfirst = std::distance( rhs.pair.first, pair.first );
difference_type dsecond = std::distance( rhs.pair.second, pair.second );
difference_type N2 = std::distance( range.second.first, range.second.second );
return dfirst * N2 + dsecond;
}
reference operator[]( difference_type offset ) const {
return *(*this + offset);
}
difference_type index() const {
difference_type N2 = std::distance( range.second.first, range.second.second );
return index(N2);
}
bool operator==( const product_iterator<It1,It2>& rhs ) const {
return pair == rhs.pair;
}
bool operator!=( const product_iterator<It1,It2>& rhs ) const {
return !(*this == rhs);
}
bool operator<( const product_iterator<It1,It2>& rhs ) const {
return rhs - *this > 0;
}
bool operator>( const product_iterator<It1,It2>& rhs ) const {
return rhs < *this;
}
bool operator<=( const product_iterator<It1,It2>& rhs ) const {
return !( *this > rhs );
}
bool operator>=( const product_iterator<It1,It2>& rhs ) const {
return !( *this < rhs );
}
protected:
range_type range;
pair_type pair;
difference_type index( difference_type N2 ) const {
return index(
std::distance( range.first.first, pair.first ),
std::distance( range.second.first, pair.second ),
N2
);
}
difference_type index( difference_type i, difference_type j, difference_type N2 ) const {
return N2*i + j;
}
};
template<typename It1,typename It2>
struct product_range {
typedef typename std::iterator_traits<It1>::value_type value_type_1;
typedef typename std::iterator_traits<It2>::value_type value_type_2;
typedef typename std::iterator_traits<It1>::difference_type difference_type_1;
typedef typename std::iterator_traits<It2>::difference_type difference_type_2;
typedef typename std::common_type<difference_type_1,difference_type_2>::type difference_type;
typedef It1 iterator_1;
typedef It2 iterator_2;
typedef product_iterator<iterator_1,iterator_2> iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::pair<It1,It1> pair_type_1;
typedef std::pair<It2,It2> pair_type_2;
typedef std::pair<pair_type_1,pair_type_2> range_type;
typedef std::pair<value_type_1,value_type_2> value_type;
explicit product_range( const range_type& range ) : range(range) {}
product_range( const pair_type_1& range_1, const pair_type_2& range_2 ) : range(range_type(range_1,range_2)) {}
difference_type size() const {
difference_type N1 = std::distance( range.first.first, range.first.second );
difference_type N2 = std::distance( range.second.first, range.second.second );
return N1 * N2;
}
iterator begin() const {
return iterator( range );
}
iterator end() const {
return iterator(
range,
std::make_pair( range.first.second, range.second.first )
);
}
protected:
range_type range;
};
template<typename It1,typename It2>
inline product_range<It1,It2> product( It1&& first_1, It1&& last_1, It2&& first_2, It2&& last_2 ) {
return product_range<It1,It2>(
std::make_pair(
std::forward<It1>(first_1),
std::forward<It1>(last_1)
),
std::make_pair(
std::forward<It2>(first_2),
std::forward<It2>(last_2)
)
);
}
template<typename R1,typename R2>
inline auto product( R1&& r1, R2&& r2 ) {
return product(
begin( std::forward<R1>(r1) ),
end( std::forward<R1>(r1) ),
begin( std::forward<R2>(r2) ),
end( std::forward<R2>(r2) )
);
}
template<typename R1,typename R2>
inline auto cproduct( const R1& r1, const R2& r2 ) {
return product(
cbegin( r1 ),
cend( r1 ),
cbegin( r2 ),
cend( r2 )
);
}
template<typename Range>
inline auto pairs( Range&& r ) {
return product( std::forward<Range>(r), std::forward<Range>(r) );
}
template<typename Range>
inline auto cpairs( const Range& r ) {
return cproduct( r, r );
}
#endif