#ifndef _VKTPIPELINEUNIQUERANDOMITERATOR_HPP #define _VKTPIPELINEUNIQUERANDOMITERATOR_HPP /*------------------------------------------------------------------------ * Vulkan Conformance Tests * ------------------------ * * Copyright (c) 2015 The Khronos Group Inc. * Copyright (c) 2015 Imagination Technologies Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief Iterator over a unique sequence of items *//*--------------------------------------------------------------------*/ #include "tcuDefs.hpp" #include "deRandom.hpp" #include #include namespace vkt { namespace pipeline { template class UniqueRandomIterator { public: UniqueRandomIterator (deUint32 numItems, deUint32 numValues, int seed); virtual ~UniqueRandomIterator (void) {} bool hasNext (void) const; T next (void); void reset (void); protected: virtual T getIndexedValue (deUint32 index) = 0; private: std::vector m_indices; size_t m_currentIndex; }; template UniqueRandomIterator::UniqueRandomIterator (deUint32 numItems, deUint32 numValues, int seed) { de::Random rnd(seed); DE_ASSERT(numItems <= numValues); if (numItems == numValues) { // Fast way to populate the index sequence m_indices = std::vector(numItems); for (deUint32 itemNdx = 0; itemNdx < numItems; itemNdx++) m_indices[itemNdx] = itemNdx; } else { std::set uniqueIndices; // Populate set with "numItems" unique values between 0 and numValues - 1 while (uniqueIndices.size() < numItems) uniqueIndices.insert(rnd.getUint32() % numValues); // Copy set into index sequence m_indices = std::vector(uniqueIndices.begin(), uniqueIndices.end()); } // Scramble the indices rnd.shuffle(m_indices.begin(), m_indices.end()); reset(); } template bool UniqueRandomIterator::hasNext (void) const { return m_currentIndex < m_indices.size(); } template T UniqueRandomIterator::next (void) { DE_ASSERT(m_currentIndex < m_indices.size()); return getIndexedValue(m_indices[m_currentIndex++]); } template void UniqueRandomIterator::reset (void) { m_currentIndex = 0; } } // pipeline } // vkt #endif // _VKTPIPELINEUNIQUERANDOMITERATOR_HPP