3 #ifndef CDSLIB_OPT_PERMUTATION_H
4 #define CDSLIB_OPT_PERMUTATION_H
6 #include <stdlib.h> // rand, srand
8 #include <algorithm> // std::shuffle
10 #include <cds/opt/options.h>
12 namespace cds { namespace opt {
14 /// [type-option] Random permutation generator option setter
16 The class represents permutation generator of unique integers from <tt> [0, nLength) </tt>
17 (\p nLenght is not included) in random order.
19 The generator interface is:
22 // Initializes the generator of length nLength
23 generator( size_t nLength );
25 // Returns current value
28 // Goes to next value. Returns false if the permutation is exchausted
31 // Resets the generator to produce the new sequence
37 The permutation generator is intended for <tt>do {} while</tt> loop:
39 permutation_generator gen( 16 );
44 } while ( gen.next() );
46 // Get other permutation
51 } while ( gen.next() );
54 The following \p Generator defined:
55 - opt::v::random_permutation
56 - opt::v::random2_permutation
57 - opt::v::random_shuffle_permutation
58 - opt::v::skew_permutation
60 template <typename Generator>
61 struct permutation_generator {
63 template <typename Base> struct pack: public Base
65 typedef Generator permutation_generator;
72 /// Permutation generator of arbitrary length based on \p rand()
74 The class is suitable for \p opt::permutation_generator option.
76 The generator calculates <tt>n = rand()</tt> and produces the sequence
77 <tt>[n % nLen, (n + 1) % nLen, ..., (n + nLen - 1) % nLen]</tt>.
78 The generator does not allocate any memory.
80 \p Int template argument specifies the type of generated value, it should be any integer.
82 template <typename Int=int>
83 class random_permutation
86 typedef Int integer_type; ///< Type of generated value
90 integer_type m_nStart;
91 integer_type const m_nMod;
95 /// Initializes the generator of arbitrary length \p nLength
96 random_permutation( size_t nLength )
99 , m_nMod( integer_type(nLength) )
104 /// Returns the curent value
105 operator integer_type() const
107 return m_nCur % m_nMod;
110 /// Goes to next value. Returns \p false if the sequence is exhausted
113 return (++m_nCur % m_nMod) != m_nStart;
116 /// Resets the generator to produce new sequence
119 m_nCur = m_nStart = integer_type( rand() ) % m_nMod;
123 /// Permutation generator of power-of-2 length based on \p rand()
125 The class is suitable for \p opt::permutation_generator option.
127 The generator calculates <tt>n = rand()</tt> and produces the sequence
128 <tt>[n % nLen, (n + 1) % nLen, ..., (n + nLen - 1) % nLen]</tt>.
129 The generator does not allocate any memory.
130 \p nLen must be power of two.
132 \p Int template argument specifies the type of generated value, it should be any integer.
134 template <typename Int=int>
135 class random2_permutation
138 typedef Int integer_type; ///< Type of generated value
143 integer_type m_nStart;
144 integer_type const m_nMask;
148 /// Initializes the generator of length \p nLength
150 An assertion is raised if \p nLength is not a power of two.
152 random2_permutation( size_t nLength )
155 , m_nMask( integer_type(nLength) - 1 )
157 // nLength must be power of two
158 assert( (nLength & (nLength - 1)) == 0 );
162 /// Returns the current value
163 operator integer_type() const
165 return m_nCur & m_nMask;
168 /// Goes to next value. Returns \p false if the sequence is exhausted
171 return (++m_nCur & m_nMask) != m_nStart;
174 /// Resets the generator to produce new sequence
177 m_nCur = m_nStart = integer_type( rand() ) & m_nMask;
181 /// Permutation generator based on \p std::shuffle
183 The class is suitable for \p opt::permutation_generator option.
185 The generator produces a permutation of <tt>[0, nLen)</tt> sequence.
186 The generator instance allocates a memory block.
189 - \p Int - specifies the type of generated value, it should be any integer.
190 - \p RandomGenerator - random generator, default is \p std::mt19937
191 - \p RandomDevice - random device, default is \p std::random_device
193 template <typename Int=int, class RandomGenerator = std::mt19937, class RandomDevice = std::random_device >
194 class random_shuffle_permutation
197 typedef Int integer_type; ///< Type of generated value
198 typedef RandomGenerator random_generator; ///< random generator
199 typedef RandomDevice random_device; ///< random device
203 integer_type * m_pCur;
204 integer_type * m_pFirst;
205 integer_type * m_pLast;
207 random_generator m_RandomGenerator;
208 random_device m_RandomDevice;
212 /// Initializes the generator of arbitrary length \p nLength
213 random_shuffle_permutation( size_t nLength )
215 , m_RandomGenerator( m_RandomDevice() )
217 m_pFirst = new integer_type[nLength];
218 m_pLast = m_pFirst + nLength;
219 for ( integer_type i = 0; i < static_cast<integer_type>(nLength); ++i )
224 ~random_shuffle_permutation()
229 /// Returns the current value
230 operator integer_type() const
235 /// Goes to next value. Returns \p false if the sequence is exhausted
238 return ++m_pCur < m_pLast;
241 /// Resets the generator to produce new sequence
244 std::shuffle( m_pFirst, m_pLast, m_RandomGenerator );
249 /// Skew permutation generator
251 This generator produces offset permutation based on \p Generator:
252 <tt>int(Generator) + nOffset</tt>
253 where \p Generator - a permutation generator.
255 The class is suitable for \p opt::permutation_generator option
256 if the goal sequence should be a permutation of <tt>[nOffset, nOffset + nLength)</tt>
258 template <typename Generator>
259 class skew_permutation
262 typedef Generator base_generator; ///< Original permutation generator
263 typedef typename base_generator::integer_type integer_type; ///< Type of generated value
267 base_generator m_Gen;
268 integer_type const m_nOffset;
272 /// Initializes the generator
274 integer_type nOffset, ///< The offset, i.e. first value of generated sequence
275 size_t nLength ///< The length of sequence
278 , m_nOffset( nOffset )
281 /// Returns the current value
282 operator integer_type() const
284 return integer_type(m_Gen) + m_nOffset;
287 /// Goes to next value. Returns \p false if the sequence is exhausted
293 /// Resets the generator to produce new sequence
302 }} // namespace cds::opt
304 #endif // #ifndef CDSLIB_OPT_PERMUTATION_H