Cayley
Pseudo-Random Bits from Finite Groups
Permutation.cpp
Go to the documentation of this file.
1 
4 #include <string.h> //for memcpy
5 #include "Permutation.h"
6 #include "Includes.h"
7 
9 //Constructors and destructors.
10 
11 #pragma region structors
12 
16 
17 CPerm::CPerm(uint8_t n): m_nSize(n){
18  m_nMap = new uint8_t[n];
19 
20  for(uint8_t i=0; i<m_nSize; i++)
21  m_nMap[i] = i;
22 } //constructor
23 
30 
31 CPerm::CPerm(uint8_t n, uintx_t m): CPerm(n){
32  uintx_t* factorial = new uintx_t[n]; //factorials
33  factorial[0] = 1;
34 
35  for(uint8_t i=1; i<n; i++)
36  factorial[i] = uint32_t(i)*factorial[i - 1];
37 
38  const uintx_t nfactorial = uint32_t(n)*factorial[n - 1];
39  m %= nfactorial; //prevent m from being larger than n!
40 
41  uint32_t* c = new uint32_t[n]; //c[i] will be the number of p[0..i-1] < p[i]
42  uint32_t* d = new uint32_t[n]; //helper
43 
44  for(int i=0; i<n; i++){ //initialize c and d
45  c[i] = 0;
46  d[i] = i;
47  } //for
48 
49  //compute c[0..n-1]
50 
51  for(int i=n-1; i>0; i--){
52  c[i] = uint32_t(m/factorial[i]);
53  m = m%factorial[i];
54  } //for
55 
56  //use c[] and d[] to compute the permutation
57 
58  for(int i=n-1; i>=0; i--){
59  m_nMap[i] = d[c[i]];
60  for(int j=c[i]; j<i; j++)
61  d[j] = d[j + 1];
62  } //for
63 
64  //clean up and exit
65 
66  delete [] factorial;
67  delete [] d;
68  delete [] c;
69 } //constructor
70 
75 
76 CPerm::CPerm(uint8_t n, uint8_t init[]): CPerm(n){
77  for(uint8_t i=0; i<m_nSize; i++)
78  m_nMap[i] = init[i];
79 } //constructor
80 
83 
84 CPerm::CPerm(const CPerm& p): CPerm(p.m_nSize){
85  for(uint8_t i=0; i<m_nSize; i++)
86  m_nMap[i] = p.m_nMap[i];
87 } //copy constructor
88 
90 
92  delete [] m_nMap;
93 } //destructor
94 
95 #pragma endregion structors
96 
98 // Randomization functions.
99 
100 #pragma region randomization
101 
105 
106 void CPerm::Randomize(uint64_t (*rng)(void)){
107  for(uint8_t i=0; i<m_nSize-1; i++){
108  const int j = rng()%((uint64_t)m_nSize - i) + i; //random target
109  std::swap(m_nMap[i], m_nMap[j]);
110  } //for
111 } //Randomize
112 
116 
117 void CPerm::RandomizeOdd(uint64_t (*rng)(void)){
118  int nCount = 0; //number of transpositions
119 
120  for(uint8_t i=0; i<m_nSize-2; i++){ //all except last pair to enforce oddness
121  const int j = rng()%((uint64_t)m_nSize - i) + i; //random target
122 
123  if(i != j){ //not self-target
124  std::swap(m_nMap[i], m_nMap[j]); //make the transposition
125  ++nCount; //one more transposition, obviously
126  } //if
127  } //for
128 
129  if(nCount ^ 1) //even permutation, ruh-roh
130  std::swap(m_nMap[m_nSize - 2], m_nMap[m_nSize - 1]); //fix it
131 } //RandomizeOdd
132 
138 
139  void CPerm::Randomize(uint32_t s[]){
140  for(uint8_t i=0; i<m_nSize-1; i++){
141  const uint8_t j = s[i]%(m_nSize - i) + i; //random target
142  printf("(%u, %u) ", i, j);
143  std::swap(m_nMap[i], m_nMap[j]);
144  } //for
145  printf("\n");
146  } //Randomize
147 
148 #pragma endregion randomization
149 
151 // Reader functions and tests.
152 
153 #pragma region readersandtests
154 
158 
159 uint8_t CPerm::GetSize() const{
160  return m_nSize;
161 } //GetSize
162 
166 
167 bool CPerm::IsIdentity() const{
168  for(uint8_t i=0; i<m_nSize; i++)
169  if(m_nMap[i] != i)return false;
170 
171  return true;
172 } //IsIdentity
173 
174 #pragma endregion readersandtests
175 
177 // print functions
178 
179 #pragma region printing
180 
182 
183 void CPerm::printmap() const{
184  for(uint8_t i=0; i<m_nSize-1; i++)
185  printf("%u, ", m_nMap[i]);
186  printf("%u\n", m_nMap[m_nSize - 1]);
187 } //printmap
188 
190 
191 void CPerm::printnum() const{
192  printf("%s\n", GetNum<uintx_t>().GetString().c_str());
193 } //printnum
194 
195 #pragma endregion printing
196 
198 // operators
199 
200 #pragma region operators
201 
205 
206 uint8_t CPerm::operator[](uint8_t n) const{
207  return m_nMap[n];
208 } //operator[]
209 
213 
215  assert(p.m_nSize == m_nSize); //safety
216 
217  if(this != &p)
218  memcpy(m_nMap, p.m_nMap, m_nSize);
219 
220  return *this;
221 } //operator=
222 
229 
230 bool operator!=(const CPerm& p0, const CPerm& p1){
231  return !(p0 == p1);
232 } //operator!=
233 
239 
240 bool operator==(const CPerm& p0, const CPerm& p1){
241  assert(p0.m_nSize == p1.m_nSize); //safety
242 
243  bool ok = true; //true if we think they are equal
244 
245  for(uint8_t i=0; i<p0.m_nSize && ok; i++) //note early exit
246  ok = ok && (p0.m_nMap[i] == p1.m_nMap[i]); //maps must be identical
247 
248  return ok;
249 } //operator==
250 
254 
255 const CPerm& CPerm::operator*=(const CPerm& p){
256  const uint8_t* pmap = p.m_nMap; //p's map table
257 
258  for(uint8_t i=0; i<m_nSize; i++){ //for each map entry
259  uint8_t& m = m_nMap[i]; //current map entry
260  m = pmap[m]; //apply second map
261  } //for
262 
263  return *this;
264 } //operator*=
265 
272 
273 template<class uint> uint CPerm::GetNum() const{
274  uint n = 0; //return result
275  uint ifactorial = 1; //0!
276 
277  for(uint8_t i=1; i<m_nSize; i++){
278  ifactorial *= i; //i!
279  int count = 0; //number of earlier entries less than the i'th one
280 
281  for(uint8_t j=0; j<i; j++)
282  count += m_nMap[j] < m_nMap[i];
283 
284  n += count*ifactorial;
285  } //for
286 
287  return n;
288 } //GetNum
289 
291 //explicit template instantiations
292 
293 template uintx_t CPerm::GetNum<uintx_t>() const;
294 template uint64_t CPerm::GetNum<uint64_t>() const;
295 template uint32_t CPerm::GetNum<uint32_t>() const;
296 template uint16_t CPerm::GetNum<uint16_t>() const;
297 template uint8_t CPerm::GetNum<uint8_t>() const;
298 
299 #pragma endregion operators
bool IsIdentity() const
Identity permutation test.
uint8_t operator[](uint8_t n) const
Get nth element of map.
uint8_t m_nSize
Number of things being permuted.
Definition: Permutation.h:23
uint GetNum() const
Get reverse lexicographic number.
void printnum() const
Print reverse lexicographic number.
void printmap() const
Print as a map.
Useful includes.
CPerm(uint8_t n)
Constructor.
Definition: Permutation.cpp:17
uint8_t GetSize() const
Get size.
const CPerm & operator *=(const CPerm &p)
Permutation composition.
Permutation.
Definition: Permutation.h:20
The extensible unsigned integer class.
Definition: uintx_t.h:14
bool operator==(const CPerm &p0, const CPerm &p1)
Is equal to.
~CPerm()
Destructor.
Definition: Permutation.cpp:91
uint8_t * m_nMap
Permutation sends i to m_nMap[i].
Definition: Permutation.h:22
Declaration of the permutation CPerm.
void RandomizeOdd(uint64_t(*rng)(void))
Set to random odd permutation.
void Randomize(uint64_t(*rng)(void))
Set to random permutation.
bool operator!=(const CPerm &p0, const CPerm &p1)
Is not equal to.
CPerm & operator=(const CPerm &p)
Assignment operator.