1 #ifndef _VKTPIPELINEUNIQUERANDOMITERATOR_HPP
2 #define _VKTPIPELINEUNIQUERANDOMITERATOR_HPP
3 /*------------------------------------------------------------------------
4  * Vulkan Conformance Tests
5  * ------------------------
6  *
7  * Copyright (c) 2015 The Khronos Group Inc.
8  * Copyright (c) 2015 Imagination Technologies Ltd.
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  *//*!
23  * \file
24  * \brief Iterator over a unique sequence of items
25  *//*--------------------------------------------------------------------*/
26 
27 #include "tcuDefs.hpp"
28 #include "deRandom.hpp"
29 #include <set>
30 #include <vector>
31 
32 namespace vkt
33 {
34 namespace pipeline
35 {
36 
37 template <typename T>
38 class UniqueRandomIterator
39 {
40 public:
41     UniqueRandomIterator(uint32_t numItems, uint32_t numValues, int seed);
~UniqueRandomIterator(void)42     virtual ~UniqueRandomIterator(void)
43     {
44     }
45     bool hasNext(void) const;
46     T next(void);
47     void reset(void);
48 
49 protected:
50     virtual T getIndexedValue(uint32_t index) = 0;
51 
52 private:
53     std::vector<uint32_t> m_indices;
54     size_t m_currentIndex;
55 };
56 
57 template <typename T>
UniqueRandomIterator(uint32_t numItems,uint32_t numValues,int seed)58 UniqueRandomIterator<T>::UniqueRandomIterator(uint32_t numItems, uint32_t numValues, int seed)
59 {
60     de::Random rnd(seed);
61 
62     DE_ASSERT(numItems <= numValues);
63 
64     if (numItems == numValues)
65     {
66         // Fast way to populate the index sequence
67         m_indices = std::vector<uint32_t>(numItems);
68 
69         for (uint32_t itemNdx = 0; itemNdx < numItems; itemNdx++)
70             m_indices[itemNdx] = itemNdx;
71     }
72     else
73     {
74         std::set<uint32_t> uniqueIndices;
75 
76         // Populate set with "numItems" unique values between 0 and numValues - 1
77         while (uniqueIndices.size() < numItems)
78             uniqueIndices.insert(rnd.getUint32() % numValues);
79 
80         // Copy set into index sequence
81         m_indices = std::vector<uint32_t>(uniqueIndices.begin(), uniqueIndices.end());
82     }
83 
84     // Scramble the indices
85     rnd.shuffle(m_indices.begin(), m_indices.end());
86 
87     reset();
88 }
89 
90 template <typename T>
hasNext(void) const91 bool UniqueRandomIterator<T>::hasNext(void) const
92 {
93     return m_currentIndex < m_indices.size();
94 }
95 
96 template <typename T>
next(void)97 T UniqueRandomIterator<T>::next(void)
98 {
99     DE_ASSERT(m_currentIndex < m_indices.size());
100 
101     return getIndexedValue(m_indices[m_currentIndex++]);
102 }
103 
104 template <typename T>
reset(void)105 void UniqueRandomIterator<T>::reset(void)
106 {
107     m_currentIndex = 0;
108 }
109 
110 } // namespace pipeline
111 } // namespace vkt
112 
113 #endif // _VKTPIPELINEUNIQUERANDOMITERATOR_HPP
114