blob: e03a45da1f2799696357d0dfcc1b503a33d43626 [file] [log] [blame]
Moritz Pflanzer69e44dc2017-07-05 11:02:14 +01001/*
2 * Copyright (c) 2017 ARM Limited.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24#ifndef ARM_COMPUTE_TEST_DATASET_CARTESIAN_PRODUCT
25#define ARM_COMPUTE_TEST_DATASET_CARTESIAN_PRODUCT
26
27#include "Dataset.h"
28
29#include <string>
30#include <tuple>
31#include <utility>
32
33namespace arm_compute
34{
35namespace test
36{
37namespace framework
38{
39namespace dataset
40{
41/** Implementation of a dataset representing all combinations of values of the input datasets.
42 *
43 * For example, for the inputs {1, 2} and {3, 4} this dataset virtually
44 * represents the values {(1, 3), (1, 4), (2, 3), (2, 4)}.
45 */
46template <typename T, typename U>
47class CartesianProductDataset : public Dataset
48{
49private:
50 using iter1_type = typename T::iterator;
51 using iter2_type = typename U::iterator;
52
53public:
54 /** Construct dataset from the given datasets.
55 *
56 * @param[in] dataset1 First dataset.
57 * @param[in] dataset2 Second dataset.
58 */
59 CartesianProductDataset(T &&dataset1, U &&dataset2)
60 : _dataset1{ std::forward<T>(dataset1) },
61 _dataset2{ std::forward<U>(dataset2) }
62 {
63 }
64
65 CartesianProductDataset(CartesianProductDataset &&) = default;
66
67 /** Type of the dataset. */
68 using type = decltype(std::tuple_cat(*std::declval<iter1_type>(), *std::declval<iter2_type>()));
69
70 /** Iterator for the dataset. */
71 struct iterator
72 {
73 iterator(const T *dataset1, const U *dataset2)
74 : _iter1{ dataset1->begin() },
75 _dataset2{ dataset2 },
76 _iter2{ dataset2->begin() }
77 {
78 }
79
80 iterator(const iterator &) = default;
81 iterator &operator=(const iterator &) = default;
82 iterator(iterator &&) = default;
83 iterator &operator=(iterator &&) = default;
84
85 ~iterator() = default;
86
87 std::string description() const
88 {
89 return _iter1.description() + ":" + _iter2.description();
90 }
91
92 CartesianProductDataset::type operator*() const
93 {
94 return std::tuple_cat(*_iter1, *_iter2);
95 }
96
97 iterator &operator++()
98 {
99 ++_second_pos;
100
101 if(_second_pos < _dataset2->size())
102 {
103 ++_iter2;
104 }
105 else
106 {
107 _second_pos = 0;
108 _iter2 = _dataset2->begin();
109
110 ++_iter1;
111 }
112
113 return *this;
114 }
115
116 private:
117 iter1_type _iter1;
118 const U *_dataset2;
119 iter2_type _iter2;
120 int _first_pos{ 0 };
121 int _second_pos{ 0 };
122 };
123
124 /** Iterator pointing at the begin of the dataset.
125 *
126 * @return Iterator for the dataset.
127 */
128 iterator begin() const
129 {
130 return iterator(&_dataset1, &_dataset2);
131 }
132
133 /** Size of the dataset.
134 *
135 * @return Number of values in the dataset.
136 */
137 int size() const
138 {
139 return _dataset1.size() * _dataset2.size();
140 }
141
142private:
143 T _dataset1;
144 U _dataset2;
145};
146
147/** Helper function to create a @ref CartesianProductDataset.
148 *
149 * @param[in] dataset1 First dataset.
150 * @param[in] dataset2 Second dataset.
151 *
152 * @return A grid dataset.
153 */
154template <typename T, typename U>
155CartesianProductDataset<T, U> combine(T &&dataset1, U &&dataset2)
156{
157 return CartesianProductDataset<T, U>(std::forward<T>(dataset1), std::forward<U>(dataset2));
158}
159} // namespace dataset
160} // namespace framework
161} // namespace test
162} // namespace arm_compute
163#endif /* ARM_COMPUTE_TEST_DATASET_CARTESIAN_PRODUCT */