#ifndef _TCURANDOMVALUEITERATOR_HPP #define _TCURANDOMVALUEITERATOR_HPP /*------------------------------------------------------------------------- * drawElements Quality Program Tester Core * ---------------------------------------- * * Copyright 2014 The Android Open Source Project * * 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 Random value iterator. *//*--------------------------------------------------------------------*/ #include "tcuDefs.hpp" #include "deRandom.hpp" namespace tcu { template T getRandomValue(de::Random &rnd) { // \note memcpy() is the only valid way to do cast from uint32 to float for instnance. uint8_t data[sizeof(T) + sizeof(T) % 4]; DE_STATIC_ASSERT(sizeof(data) % 4 == 0); for (int vecNdx = 0; vecNdx < DE_LENGTH_OF_ARRAY(data) / 4; vecNdx++) { uint32_t rval = rnd.getUint32(); for (int compNdx = 0; compNdx < 4; compNdx++) data[vecNdx * 4 + compNdx] = ((const uint8_t *)&rval)[compNdx]; } return *(const T *)&data[0]; } // Faster implementations for int types. template <> inline uint8_t getRandomValue(de::Random &rnd) { return (uint8_t)rnd.getUint32(); } template <> inline uint16_t getRandomValue(de::Random &rnd) { return (uint16_t)rnd.getUint32(); } template <> inline uint32_t getRandomValue(de::Random &rnd) { return rnd.getUint32(); } template <> inline uint64_t getRandomValue(de::Random &rnd) { return rnd.getUint64(); } template <> inline int8_t getRandomValue(de::Random &rnd) { return (int8_t)rnd.getUint32(); } template <> inline int16_t getRandomValue(de::Random &rnd) { return (int16_t)rnd.getUint32(); } template <> inline int32_t getRandomValue(de::Random &rnd) { return (int32_t)rnd.getUint32(); } template <> inline int64_t getRandomValue(de::Random &rnd) { return (int64_t)rnd.getUint64(); } template class RandomValueIterator { public: using iterator_category = std::forward_iterator_tag; using value_type = T; using difference_type = std::ptrdiff_t; using pointer = T *; using reference = T &; static RandomValueIterator begin(uint32_t seed, int numValues) { return RandomValueIterator(seed, numValues); } static RandomValueIterator end(void) { return RandomValueIterator(0, 0); } RandomValueIterator &operator++(void); RandomValueIterator operator++(int); const T &operator*(void) const { return m_curVal; } bool operator==(const RandomValueIterator &other) const; bool operator!=(const RandomValueIterator &other) const; private: RandomValueIterator(uint32_t seed, int numLeft); de::Random m_rnd; int m_numLeft; T m_curVal; }; template RandomValueIterator::RandomValueIterator(uint32_t seed, int numLeft) : m_rnd(seed) , m_numLeft(numLeft) , m_curVal(numLeft > 0 ? getRandomValue(m_rnd) : T()) { } template RandomValueIterator &RandomValueIterator::operator++(void) { DE_ASSERT(m_numLeft > 0); m_numLeft -= 1; m_curVal = getRandomValue(m_rnd); return *this; } template RandomValueIterator RandomValueIterator::operator++(int) { RandomValueIterator copy(*this); ++(*this); return copy; } template bool RandomValueIterator::operator==(const RandomValueIterator &other) const { return (m_numLeft == 0 && other.m_numLeft == 0) || (m_numLeft == other.m_numLeft && m_rnd == other.m_rnd); } template bool RandomValueIterator::operator!=(const RandomValueIterator &other) const { return !(m_numLeft == 0 && other.m_numLeft == 0) && (m_numLeft != other.m_numLeft || m_rnd != other.m_rnd); } } // namespace tcu #endif // _TCURANDOMVALUEITERATOR_HPP