3 #ifndef CDSLIB_OPT_PERMUTATION_H
4 #define CDSLIB_OPT_PERMUTATION_H
6 #include <cds/opt/options.h>
7 #include <stdlib.h> // rand, srand
10 namespace cds { namespace opt {
12 /// [type-option] Random permutation generator option setter
14 The class represents permutation generator of unique integers from <tt> [0, nLength) </tt>
15 (\p nLenght is not included) in random order.
17 The generator interface is:
20 // Initializes the generator of length nLength
21 generator( size_t nLength );
23 // Returns current value
26 // Goes to next value. Returns false if the permutation is exchausted
29 // Resets the generator to produce the new sequence
35 The permutation generator is intended for <tt>do {} while</tt> loop:
37 permutation_generator gen( 16 );
42 } while ( gen.next() );
44 // Get other permutation
49 } while ( gen.next() );
52 The following \p Generator defined:
53 - opt::v::random_permutation
54 - opt::v::random2_permutation
55 - opt::v::random_shuffle_permutation
56 - opt::v::skew_permutation
58 template <typename Generator>
59 struct permutation_generator {
61 template <typename Base> struct pack: public Base
63 typedef Generator permutation_generator;
70 /// Permutation generator of arbitrary length based on \p rand()
72 The class is suitable for \p opt::permutation_generator option.
74 The generator calculates <tt>n = rand()</tt> and produces the sequence
75 <tt>[n % nLen, (n + 1) % nLen, ..., (n + nLen - 1) % nLen]</tt>.
76 The generator does not allocate any memory.
78 \p Int template argument specifies the type of generated value, it should be any integer.
80 template <typename Int=int>
81 class random_permutation
84 typedef Int integer_type; ///< Type of generated value
88 integer_type m_nStart;
89 integer_type const m_nMod;
93 /// Initializes the generator of arbitrary length \p nLength
94 random_permutation( size_t nLength )
97 , m_nMod( integer_type(nLength) )
102 /// Returns the curent value
103 operator integer_type() const
105 return m_nCur % m_nMod;
108 /// Goes to next value. Returns \p false if the sequence is exhausted
111 return (++m_nCur % m_nMod) != m_nStart;
114 /// Resets the generator to produce new sequence
117 m_nCur = m_nStart = integer_type( rand() ) % m_nMod;
121 /// Permutation generator of power-of-2 length based on \p rand()
123 The class is suitable for \p opt::permutation_generator option.
125 The generator calculates <tt>n = rand()</tt> and produces the sequence
126 <tt>[n % nLen, (n + 1) % nLen, ..., (n + nLen - 1) % nLen]</tt>.
127 The generator does not allocate any memory.
128 \p nLen must be power of two.
130 \p Int template argument specifies the type of generated value, it should be any integer.
132 template <typename Int=int>
133 class random2_permutation
136 typedef Int integer_type; ///< Type of generated value
141 integer_type m_nStart;
142 integer_type const m_nMask;
146 /// Initializes the generator of length \p nLength
148 An assertion is raised if \p nLength is not a power of two.
150 random2_permutation( size_t nLength )
153 , m_nMask( integer_type(nLength) - 1 )
155 // nLength must be power of two
156 assert( (nLength & (nLength - 1)) == 0 );
160 /// Returns the current value
161 operator integer_type() const
163 return m_nCur & m_nMask;
166 /// Goes to next value. Returns \p false if the sequence is exhausted
169 return (++m_nCur & m_nMask) != m_nStart;
172 /// Resets the generator to produce new sequence
175 m_nCur = m_nStart = integer_type( rand() ) & m_nMask;
179 /// Permutation generator based on \p std::shuffle
181 The class is suitable for \p opt::permutation_generator option.
183 The generator produces a permutation of <tt>[0, nLen)</tt> sequence.
184 The generator instance allocates a memory block.
187 - \p Int - specifies the type of generated value, it should be any integer.
188 - \p RandomGenerator - random generator, default is \p std::mt19937
189 - \p RandomDevice - random device, default is \p std::random_device
191 template <typename Int=int, class RandomGenerator = std::mt19937, class RandomDevice = std::random_device >
192 class random_shuffle_permutation
195 typedef Int integer_type; ///< Type of generated value
196 typedef RandomGenerator random_generator; ///< random generator
197 typedef RandomDevice random_device; ///< random device
201 integer_type * m_pCur;
202 integer_type * m_pFirst;
203 integer_type * m_pLast;
205 random_generator m_RandomGenerator;
206 random_device m_RandomDevice;
210 /// Initializes the generator of arbitrary length \p nLength
211 random_shuffle_permutation( size_t nLength )
213 , m_RandomGenerator( m_RandomDevice() )
215 m_pFirst = new integer_type[nLength];
216 m_pLast = m_pFirst + nLength;
217 for ( integer_type i = 0; i < static_cast<integer_type>(nLength); ++i )
222 ~random_shuffle_permutation()
227 /// Returns the current value
228 operator integer_type() const
233 /// Goes to next value. Returns \p false if the sequence is exhausted
236 return ++m_pCur < m_pLast;
239 /// Resets the generator to produce new sequence
242 std::shuffle( m_pFirst, m_pLast, m_RandomGenerator );
247 /// Skew permutation generator
249 This generator produces offset permutation based on \p Generator:
250 <tt>int(Generator) + nOffset</tt>
251 where \p Generator - a permutation generator.
253 The class is suitable for \p opt::permutation_generator option
254 if the goal sequence should be a permutation of <tt>[nOffset, nOffset + nLength)</tt>
256 template <typename Generator>
257 class skew_permutation
260 typedef Generator base_generator; ///< Original permutation generator
261 typedef typename base_generator::integer_type integer_type; ///< Type of generated value
265 base_generator m_Gen;
266 integer_type const m_nOffset;
270 /// Initializes the generator
272 integer_type nOffset, ///< The offset, i.e. first value of generated sequence
273 size_t nLength ///< The length of sequence
276 , m_nOffset( nOffset )
279 /// Returns the current value
280 operator integer_type() const
282 return integer_type(m_Gen) + m_nOffset;
285 /// Goes to next value. Returns \p false if the sequence is exhausted
291 /// Resets the generator to produce new sequence
300 }} // namespace cds::opt
302 #endif // #ifndef CDSLIB_OPT_PERMUTATION_H