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
29 namespace tcu
30 {
31
32 template <typename T>
getRandomValue(de::Random & rnd)33 T getRandomValue(de::Random &rnd)
34 {
35 // \note memcpy() is the only valid way to do cast from uint32 to float for instnance.
36 uint8_t 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 uint32_t rval = rnd.getUint32();
41 for (int compNdx = 0; compNdx < 4; compNdx++)
42 data[vecNdx * 4 + compNdx] = ((const uint8_t *)&rval)[compNdx];
43 }
44 return *(const T *)&data[0];
45 }
46
47 // Faster implementations for int types.
48 template <>
getRandomValue(de::Random & rnd)49 inline uint8_t getRandomValue<uint8_t>(de::Random &rnd)
50 {
51 return (uint8_t)rnd.getUint32();
52 }
53 template <>
getRandomValue(de::Random & rnd)54 inline uint16_t getRandomValue<uint16_t>(de::Random &rnd)
55 {
56 return (uint16_t)rnd.getUint32();
57 }
58 template <>
getRandomValue(de::Random & rnd)59 inline uint32_t getRandomValue<uint32_t>(de::Random &rnd)
60 {
61 return rnd.getUint32();
62 }
63 template <>
getRandomValue(de::Random & rnd)64 inline uint64_t getRandomValue<uint64_t>(de::Random &rnd)
65 {
66 return rnd.getUint64();
67 }
68 template <>
getRandomValue(de::Random & rnd)69 inline int8_t getRandomValue<int8_t>(de::Random &rnd)
70 {
71 return (int8_t)rnd.getUint32();
72 }
73 template <>
getRandomValue(de::Random & rnd)74 inline int16_t getRandomValue<int16_t>(de::Random &rnd)
75 {
76 return (int16_t)rnd.getUint32();
77 }
78 template <>
getRandomValue(de::Random & rnd)79 inline int32_t getRandomValue<int32_t>(de::Random &rnd)
80 {
81 return (int32_t)rnd.getUint32();
82 }
83 template <>
getRandomValue(de::Random & rnd)84 inline int64_t getRandomValue<int64_t>(de::Random &rnd)
85 {
86 return (int64_t)rnd.getUint64();
87 }
88
89 template <typename T>
90 class RandomValueIterator
91 {
92 public:
93 using iterator_category = std::forward_iterator_tag;
94 using value_type = T;
95 using difference_type = std::ptrdiff_t;
96 using pointer = T *;
97 using reference = T &;
98
begin(uint32_t seed,int numValues)99 static RandomValueIterator begin(uint32_t seed, int numValues)
100 {
101 return RandomValueIterator<T>(seed, numValues);
102 }
end(void)103 static RandomValueIterator end(void)
104 {
105 return RandomValueIterator<T>(0, 0);
106 }
107
108 RandomValueIterator &operator++(void);
109 RandomValueIterator operator++(int);
110
operator *(void) const111 const T &operator*(void) const
112 {
113 return m_curVal;
114 }
115
116 bool operator==(const RandomValueIterator<T> &other) const;
117 bool operator!=(const RandomValueIterator<T> &other) const;
118
119 private:
120 RandomValueIterator(uint32_t seed, int numLeft);
121
122 de::Random m_rnd;
123 int m_numLeft;
124 T m_curVal;
125 };
126
127 template <typename T>
RandomValueIterator(uint32_t seed,int numLeft)128 RandomValueIterator<T>::RandomValueIterator(uint32_t seed, int numLeft)
129 : m_rnd(seed)
130 , m_numLeft(numLeft)
131 , m_curVal(numLeft > 0 ? getRandomValue<T>(m_rnd) : T())
132 {
133 }
134
135 template <typename T>
operator ++(void)136 RandomValueIterator<T> &RandomValueIterator<T>::operator++(void)
137 {
138 DE_ASSERT(m_numLeft > 0);
139
140 m_numLeft -= 1;
141 m_curVal = getRandomValue<T>(m_rnd);
142
143 return *this;
144 }
145
146 template <typename T>
operator ++(int)147 RandomValueIterator<T> RandomValueIterator<T>::operator++(int)
148 {
149 RandomValueIterator copy(*this);
150 ++(*this);
151 return copy;
152 }
153
154 template <typename T>
operator ==(const RandomValueIterator<T> & other) const155 bool RandomValueIterator<T>::operator==(const RandomValueIterator<T> &other) const
156 {
157 return (m_numLeft == 0 && other.m_numLeft == 0) || (m_numLeft == other.m_numLeft && m_rnd == other.m_rnd);
158 }
159
160 template <typename T>
operator !=(const RandomValueIterator<T> & other) const161 bool RandomValueIterator<T>::operator!=(const RandomValueIterator<T> &other) const
162 {
163 return !(m_numLeft == 0 && other.m_numLeft == 0) && (m_numLeft != other.m_numLeft || m_rnd != other.m_rnd);
164 }
165
166 } // namespace tcu
167
168 #endif // _TCURANDOMVALUEITERATOR_HPP
169