blob: 834b8bfc30d2bca299e46d1325176cc534bbdbfe [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.
deUint8 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++)
{
deUint32 rval = rnd.getUint32();
for (int compNdx = 0; compNdx < 4; compNdx++)
data[vecNdx*4+compNdx] = ((const deUint8*)&rval)[compNdx];
}
return *(const T*)&data[0];
}
// Faster implementations for int types.
template <> inline deUint8 getRandomValue<deUint8> (de::Random& rnd) { return (deUint8)rnd.getUint32(); }
template <> inline deUint16 getRandomValue<deUint16> (de::Random& rnd) { return (deUint16)rnd.getUint32(); }
template <> inline deUint32 getRandomValue<deUint32> (de::Random& rnd) { return rnd.getUint32(); }
template <> inline deUint64 getRandomValue<deUint64> (de::Random& rnd) { return rnd.getUint64(); }
template <> inline deInt8 getRandomValue<deInt8> (de::Random& rnd) { return (deInt8)rnd.getUint32(); }
template <> inline deInt16 getRandomValue<deInt16> (de::Random& rnd) { return (deInt16)rnd.getUint32(); }
template <> inline deInt32 getRandomValue<deInt32> (de::Random& rnd) { return (deInt32)rnd.getUint32(); }
template <> inline deInt64 getRandomValue<deInt64> (de::Random& rnd) { return (deInt64)rnd.getUint64(); }
template <typename T>
class RandomValueIterator : public std::iterator<std::forward_iterator_tag, T>
{
public:
static RandomValueIterator begin (deUint32 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 (deUint32 seed, int numLeft);
de::Random m_rnd;
int m_numLeft;
T m_curVal;
};
template <typename T>
RandomValueIterator<T>::RandomValueIterator (deUint32 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);
}
} // tcu
#endif // _TCURANDOMVALUEITERATOR_HPP