Turi Create  4.0
algorithmic_utils.hpp
1 /* Copyright © 2017 Apple Inc. All rights reserved.
2  *
3  * Use of this source code is governed by a BSD-3-clause license that can
4  * be found in the LICENSE.txt file or at https://opensource.org/licenses/BSD-3-Clause
5  */
6 #ifndef TURI_ALGORITHMIC_UTILS_H_
7 #define TURI_ALGORITHMIC_UTILS_H_
8 
9 #include <algorithm>
10 #include <core/logging/assertions.hpp>
11 
12 namespace turi {
13 
14 /**
15  * \ingroup toolkit_util
16  *
17  * Calls an accumulator on all intersections in two sorted ranges.
18  * This behavior is analogous to std::set_intersection, except that
19  * the intersections are simply accumulated. Matching is performed
20  * through the use of less_than_operator.
21  *
22  * \tparam InputIterator1 The type of an input iterator over the first range.
23  *
24  * \tparam InputIterator2 The type of an input iterator over the second range.
25  *
26  * \param first1 The begin() iterator of the first range.
27  *
28  * \param last1 The end() iterator of the first range.
29  *
30  * \param first2 The begin() iterator of the second range.
31  *
32  * \param last2 The end() iterator of the second range.
33  *
34  * \param less_than_operator A comparison function that determines the
35  * ordering.
36  */
37 template <typename InputIterator1, typename InputIterator2,
38  typename ComparisonFunction, typename AccumulateFunction>
39 static inline void accumulate_intersection(InputIterator1 first1, const InputIterator1& last1,
40  InputIterator2 first2, const InputIterator2& last2,
41  const ComparisonFunction& less_than_operator,
42  const AccumulateFunction& accumulate_matching_pair) {
43 
44  DASSERT_TRUE(std::is_sorted(first1, last1, less_than_operator));
45  DASSERT_TRUE(std::is_sorted(first2, last2, less_than_operator));
46 
47  while (first1 != last1 && first2 != last2) {
48  if (less_than_operator(*first1, *first2) ) {
49  ++first1;
50  } else if (less_than_operator(*first2, *first1) ) {
51  ++first2;
52  } else {
53  accumulate_matching_pair(*first1, *first2);
54  ++first1;
55  ++first2;
56  }
57  }
58 }
59 
60 /**
61  * \ingroup toolkit_util
62  * Calls an accumulator on all intersections in two sorted ranges.
63  * This behavior is analogous to std::set_intersection, except that
64  * the intersections are simply accumulated.
65  *
66  * \tparam InputIterator1 The type of an input iterator over the first range.
67  *
68  * \tparam InputIterator2 The type of an input iterator over the second range.
69  *
70  * \param first1 The begin() iterator of the first range.
71  *
72  * \param last1 The end() iterator of the first range.
73  *
74  * \param first2 The begin() iterator of the second range.
75  *
76  * \param last2 The end() iterator of the second range.
77  *
78  */
79 template <typename InputIterator1, typename InputIterator2, typename AccumulateFunction>
80 static inline void accumulate_intersection(InputIterator1 first1, const InputIterator1& last1,
81  InputIterator2 first2, const InputIterator2& last2,
82  const AccumulateFunction& accumulate_matching_pair) {
83 
84  typedef typename std::remove_reference<decltype(*first1)>::type value1_type;
85  typedef typename std::remove_reference<decltype(*first2)>::type value2_type;
86 
87  accumulate_intersection(first1, last1, first2, last2,
88  [](const value1_type& v1,
89  const value2_type& v2)
90  { return v1 < v2; },
91  accumulate_matching_pair);
92 }
93 
94 /**
95  * \ingroup toolkit_util
96  * Counts the number of intersections in two sorted ranges. This
97  * behavior is analogous to std::set_intersection, except that the
98  * intersections are simply stored and not output.
99  *
100  * \tparam InputIterator1 The type of an input iterator over the first range.
101  *
102  * \tparam InputIterator2 The type of an input iterator over the second range.
103  *
104  * \param first1 The begin() iterator of the first range.
105  *
106  * \param last1 The end() iterator of the first range.
107  *
108  * \param first2 The begin() iterator of the second range.
109  *
110  * \param last2 The end() iterator of the second range.
111  *
112  */
113 template <typename InputIterator1, typename InputIterator2>
114 static size_t count_intersection(InputIterator1 first1, const InputIterator1& last1,
115  InputIterator2 first2, const InputIterator2& last2) {
116 
117  typedef typename std::remove_reference<decltype(*first1)>::type value1_type;
118  typedef typename std::remove_reference<decltype(*first2)>::type value2_type;
119 
120  size_t count = 0;
121  accumulate_intersection(first1, last1, first2, last2,
122  [&](const value1_type&, const value2_type&)
123  { ++count; });
124 
125  return count;
126 }
127 
128 
129 /**
130  * \ingroup toolkit_util
131  * Counts the number of intersections in two sorted ranges. This
132  * behavior is analogous to std::set_intersection, except that the
133  * intersections are simply stored and not output. Matching is
134  * performed through the use of less_than_operator.
135  *
136  * \tparam InputIterator1 The type of an input iterator over the first range.
137  *
138  * \tparam InputIterator2 The type of an input iterator over the second range.
139  *
140  * \param first1 The begin() iterator of the first range.
141  *
142  * \param last1 The end() iterator of the first range.
143  *
144  * \param first2 The begin() iterator of the second range.
145  *
146  * \param last2 The end() iterator of the second range.
147  *
148 * \param less_than_operator A comparison function that determines the
149  * ordering.
150  */
151 template <typename InputIterator1, typename InputIterator2, typename ComparisonFunction>
152 static inline size_t count_intersection(InputIterator1 first1, const InputIterator1& last1,
153  InputIterator2 first2, const InputIterator2& last2,
154  const ComparisonFunction& less_than_operator) {
155 
156  typedef typename std::remove_reference<decltype(*first1)>::type value1_type;
157  typedef typename std::remove_reference<decltype(*first2)>::type value2_type;
158 
159  size_t count = 0;
160  accumulate_intersection(first1, last1, first2, last2,
161  less_than_operator,
162  [&](const value1_type&, const value2_type&)
163  { ++count; });
164 
165  return count;
166 }
167 
168 }
169 
170 #endif /* TURI_ALGORITHMIC_UTILS_H_ */
static size_t count_intersection(InputIterator1 first1, const InputIterator1 &last1, InputIterator2 first2, const InputIterator2 &last2)
static void accumulate_intersection(InputIterator1 first1, const InputIterator1 &last1, InputIterator2 first2, const InputIterator2 &last2, const ComparisonFunction &less_than_operator, const AccumulateFunction &accumulate_matching_pair)
#define DASSERT_TRUE(cond)
Definition: assertions.hpp:364