1#ifndef _TCURANDOMVALUEITERATOR_HPP
2#define _TCURANDOMVALUEITERATOR_HPP
3/*-------------------------------------------------------------------------
4 * drawElements Quality Program Tester Core
5 * ----------------------------------------
6 *
7 * Copyright 2014 The Android Open Source Project
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Random value iterator.
24 *//*--------------------------------------------------------------------*/
25
26#include "tcuDefs.hpp"
27#include "deRandom.hpp"
28
29namespace tcu
30{
31
32template <typename T>
33T getRandomValue (de::Random& rnd)
34{
35	// \note memcpy() is the only valid way to do cast from uint32 to float for instnance.
36	deUint8 data[sizeof(T) + sizeof(T)%4];
37	DE_STATIC_ASSERT(sizeof(data)%4 == 0);
38	for (int vecNdx = 0; vecNdx < DE_LENGTH_OF_ARRAY(data)/4; vecNdx++)
39	{
40		deUint32 rval = rnd.getUint32();
41		for (int compNdx = 0; compNdx < 4; compNdx++)
42			data[vecNdx*4+compNdx] = ((const deUint8*)&rval)[compNdx];
43	}
44	return *(const T*)&data[0];
45}
46
47// Faster implementations for int types.
48template <> inline deUint8	getRandomValue<deUint8>		(de::Random& rnd) { return (deUint8)rnd.getUint32();	}
49template <> inline deUint16	getRandomValue<deUint16>	(de::Random& rnd) { return (deUint16)rnd.getUint32();	}
50template <> inline deUint32	getRandomValue<deUint32>	(de::Random& rnd) { return rnd.getUint32();				}
51template <> inline deUint64	getRandomValue<deUint64>	(de::Random& rnd) { return rnd.getUint64();				}
52template <> inline deInt8	getRandomValue<deInt8>		(de::Random& rnd) { return (deInt8)rnd.getUint32();		}
53template <> inline deInt16	getRandomValue<deInt16>		(de::Random& rnd) { return (deInt16)rnd.getUint32();	}
54template <> inline deInt32	getRandomValue<deInt32>		(de::Random& rnd) { return (deInt32)rnd.getUint32();	}
55template <> inline deInt64	getRandomValue<deInt64>		(de::Random& rnd) { return (deInt64)rnd.getUint64();	}
56
57template <typename T>
58class RandomValueIterator : public std::iterator<std::forward_iterator_tag, T>
59{
60public:
61	static RandomValueIterator	begin					(deUint32 seed, int numValues)	{ return RandomValueIterator<T>(seed, numValues);	}
62	static RandomValueIterator	end						(void)							{ return RandomValueIterator<T>(0, 0);				}
63
64	RandomValueIterator&		operator++				(void);
65	RandomValueIterator			operator++				(int);
66
67	const T&					operator*				(void) const { return m_curVal; }
68
69	bool						operator==				(const RandomValueIterator<T>& other) const;
70	bool						operator!=				(const RandomValueIterator<T>& other) const;
71
72private:
73								RandomValueIterator		(deUint32 seed, int numLeft);
74
75	de::Random					m_rnd;
76	int							m_numLeft;
77	T							m_curVal;
78};
79
80template <typename T>
81RandomValueIterator<T>::RandomValueIterator (deUint32 seed, int numLeft)
82	: m_rnd		(seed)
83	, m_numLeft	(numLeft)
84	, m_curVal	(numLeft > 0 ? getRandomValue<T>(m_rnd) : T())
85{
86}
87
88template <typename T>
89RandomValueIterator<T>& RandomValueIterator<T>::operator++ (void)
90{
91	DE_ASSERT(m_numLeft > 0);
92
93	m_numLeft	-= 1;
94	m_curVal	 = getRandomValue<T>(m_rnd);
95
96	return *this;
97}
98
99template <typename T>
100RandomValueIterator<T> RandomValueIterator<T>::operator++ (int)
101{
102	RandomValueIterator copy(*this);
103	++(*this);
104	return copy;
105}
106
107template <typename T>
108bool RandomValueIterator<T>::operator== (const RandomValueIterator<T>& other) const
109{
110	return (m_numLeft == 0 && other.m_numLeft == 0) || (m_numLeft == other.m_numLeft && m_rnd == other.m_rnd);
111}
112
113template <typename T>
114bool RandomValueIterator<T>::operator!= (const RandomValueIterator<T>& other) const
115{
116	return !(m_numLeft == 0 && other.m_numLeft == 0) && (m_numLeft != other.m_numLeft || m_rnd != other.m_rnd);
117}
118
119} // tcu
120
121#endif // _TCURANDOMVALUEITERATOR_HPP
122