xref: /aosp_15_r20/external/ComputeLibrary/tests/framework/datasets/CartesianProductDataset.h (revision c217d954acce2dbc11938adb493fc0abd69584f3)
1 /*
2  * Copyright (c) 2017-2018 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 
33 namespace arm_compute
34 {
35 namespace test
36 {
37 namespace framework
38 {
39 namespace 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  */
46 template <typename T, typename U>
47 class CartesianProductDataset : public Dataset
48 {
49 private:
50     using T_noref    = typename std::remove_reference<T>::type;
51     using U_noref    = typename std::remove_reference<U>::type;
52     using iter1_type = typename T_noref::iterator;
53     using iter2_type = typename U_noref::iterator;
54 
55 public:
56     /** Construct dataset from the given datasets.
57      *
58      * @param[in] dataset1 First dataset.
59      * @param[in] dataset2 Second dataset.
60      */
CartesianProductDataset(T && dataset1,U && dataset2)61     CartesianProductDataset(T &&dataset1, U &&dataset2)
62         : _dataset1{ std::forward<T>(dataset1) },
63           _dataset2{ std::forward<U>(dataset2) }
64     {
65     }
66 
67     /** Allow instances of this class to be move constructed */
68     CartesianProductDataset(CartesianProductDataset &&) = default;
69 
70     /** Type of the dataset. */
71     using type = decltype(std::tuple_cat(*std::declval<iter1_type>(), *std::declval<iter2_type>()));
72 
73     /** Iterator for the dataset. */
74     struct iterator
75     {
76         /** Construct an iterator.
77          *
78          * @param[in] dataset1 Dataset 1.
79          * @param[in] dataset2 Dataset 2.
80          */
iteratoriterator81         iterator(const T_noref *dataset1, const U_noref *dataset2)
82             : _iter1{ dataset1->begin() },
83               _dataset2{ dataset2 },
84               _iter2{ dataset2->begin() }
85         {
86         }
87 
88         /** Allow instances of this class to be copy constructed */
89         iterator(const iterator &) = default;
90         /** Allow instances of this class to be copied */
91         iterator &operator=(const iterator &) = default;
92         /** Allow instances of this class to be move constructed */
93         iterator(iterator &&) = default;
94         /** Allow instances of this class to be moved */
95         iterator &operator=(iterator &&) = default;
96 
97         /** Default destructor */
98         ~iterator() = default;
99 
100         /** Get the description of the current value.
101          *
102          * @return description of the current value.
103          */
descriptioniterator104         std::string description() const
105         {
106             return _iter1.description() + ":" + _iter2.description();
107         }
108 
109         /** Get the value of the iterator.
110          *
111          * @return the value of the iterator.
112          */
113         CartesianProductDataset::type operator*() const
114         {
115             return std::tuple_cat(*_iter1, *_iter2);
116         }
117 
118         /** Inrement the iterator.
119          *
120          * @return *this;
121          */
122         iterator &operator++()
123         {
124             ++_second_pos;
125 
126             if(_second_pos < _dataset2->size())
127             {
128                 ++_iter2;
129             }
130             else
131             {
132                 _second_pos = 0;
133                 _iter2      = _dataset2->begin();
134 
135                 ++_iter1;
136             }
137 
138             return *this;
139         }
140 
141     private:
142         iter1_type     _iter1;
143         const U_noref *_dataset2;
144         iter2_type     _iter2;
145         int            _first_pos{ 0 };
146         int            _second_pos{ 0 };
147     };
148 
149     /** Iterator pointing at the begin of the dataset.
150      *
151      * @return Iterator for the dataset.
152      */
begin()153     iterator begin() const
154     {
155         return iterator(&_dataset1, &_dataset2);
156     }
157 
158     /** Size of the dataset.
159      *
160      * @return Number of values in the dataset.
161      */
size()162     int size() const
163     {
164         return _dataset1.size() * _dataset2.size();
165     }
166 
167 private:
168     T _dataset1;
169     U _dataset2;
170 };
171 
172 /** Helper function to create a @ref CartesianProductDataset.
173  *
174  * @param[in] dataset1 First dataset.
175  * @param[in] dataset2 Second dataset.
176  *
177  * @return A grid dataset.
178  */
179 template <typename T, typename U>
combine(T && dataset1,U && dataset2)180 CartesianProductDataset<T, U> combine(T &&dataset1, U &&dataset2)
181 {
182     return CartesianProductDataset<T, U>(std::forward<T>(dataset1), std::forward<U>(dataset2));
183 }
184 
185 /** Helper function to create a @ref CartesianProductDataset.
186  *
187  * @param[in] dataset1 First dataset.
188  * @param[in] dataset2 Second dataset.
189  *
190  * @return A grid dataset.
191  */
192 template <typename T, typename U>
193 CartesianProductDataset<T, U>
194 operator*(T &&dataset1, U &&dataset2)
195 {
196     return CartesianProductDataset<T, U>(std::forward<T>(dataset1), std::forward<U>(dataset2));
197 }
198 
199 } // namespace dataset
200 } // namespace framework
201 } // namespace test
202 } // namespace arm_compute
203 #endif /* ARM_COMPUTE_TEST_DATASET_CARTESIAN_PRODUCT */
204