blob: e62a019c90215208ab5c2dc97e89b9c6025c8707 [file] [log] [blame]
#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 <typename T>
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<uint8_t>(de::Random &rnd)
{
return (uint8_t)rnd.getUint32();
}
template <>
inline uint16_t getRandomValue<uint16_t>(de::Random &rnd)
{
return (uint16_t)rnd.getUint32();
}
template <>
inline uint32_t getRandomValue<uint32_t>(de::Random &rnd)
{
return rnd.getUint32();
}
template <>
inline uint64_t getRandomValue<uint64_t>(de::Random &rnd)
{
return rnd.getUint64();
}
template <>
inline int8_t getRandomValue<int8_t>(de::Random &rnd)
{
return (int8_t)rnd.getUint32();
}
template <>
inline int16_t getRandomValue<int16_t>(de::Random &rnd)
{
return (int16_t)rnd.getUint32();
}
template <>
inline int32_t getRandomValue<int32_t>(de::Random &rnd)
{
return (int32_t)rnd.getUint32();
}
template <>
inline int64_t getRandomValue<int64_t>(de::Random &rnd)
{
return (int64_t)rnd.getUint64();
}
template <typename T>
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<T>(seed, numValues);
}
static RandomValueIterator end(void)
{
return RandomValueIterator<T>(0, 0);
}
RandomValueIterator &operator++(void);
RandomValueIterator operator++(int);
const T &operator*(void) const
{
return m_curVal;
}
bool operator==(const RandomValueIterator<T> &other) const;
bool operator!=(const RandomValueIterator<T> &other) const;
private:
RandomValueIterator(uint32_t seed, int numLeft);
de::Random m_rnd;
int m_numLeft;
T m_curVal;
};
template <typename T>
RandomValueIterator<T>::RandomValueIterator(uint32_t seed, int numLeft)
: m_rnd(seed)
, m_numLeft(numLeft)
, m_curVal(numLeft > 0 ? getRandomValue<T>(m_rnd) : T())
{
}
template <typename T>
RandomValueIterator<T> &RandomValueIterator<T>::operator++(void)
{
DE_ASSERT(m_numLeft > 0);
m_numLeft -= 1;
m_curVal = getRandomValue<T>(m_rnd);
return *this;
}
template <typename T>
RandomValueIterator<T> RandomValueIterator<T>::operator++(int)
{
RandomValueIterator copy(*this);
++(*this);
return copy;
}
template <typename T>
bool RandomValueIterator<T>::operator==(const RandomValueIterator<T> &other) const
{
return (m_numLeft == 0 && other.m_numLeft == 0) || (m_numLeft == other.m_numLeft && m_rnd == other.m_rnd);
}
template <typename T>
bool RandomValueIterator<T>::operator!=(const RandomValueIterator<T> &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