DOCI-Exact  1.0
Permutation.cpp
Go to the documentation of this file.
1 #include <iostream>
2 #include <limits>
3 #include <stdexcept>
4 #include <assert.h>
5 
6 #include "Permutation.h"
7 
8 using namespace doci;
9 
14 Permutation::Permutation(unsigned int n)
15 {
16  if(sizeof(mybitset)*8 < n)
17  throw std::overflow_error("Cannot store permutations in assigned type");
18 
19  this->n = n;
20 
21  // set n lowest bits to 1
22  reset();
23 }
24 
31 {
32 #if defined(USELONG)
33 #define MY_CTZ(x) __builtin_ctzl(x)
34 #elif defined(USELONGLONG)
35 #define MY_CTZ(x) __builtin_ctzll(x)
36 #endif
37 
38  // current permutation of bits
39  auto &v = current; // current permutation of bits
40 
41  // from https://graphics.stanford.edu/~seander/bithacks.html#NextBitPermutation
42  auto t = v | (v - 1); // t gets v's least significant 0 bits set to 1
43  // Next set to 1 the most significant bit to change,
44  // set to 0 the least significant ones, and add the necessary 1 bits.
45  auto w = (t + 1) | (((~t & -~t) - 1) >> (MY_CTZ(v) + 1));
46 
47  // new/next permutation of bits
48  current = w;
49 
50  return current;
51 }
52 
57 mybitset Permutation::get() const
58 {
59  return current;
60 }
61 
67 {
68  current = (1L<<n)-1L;
69 }
70 
78 unsigned long long Permutation::CalcCombinations(unsigned int L, unsigned int N)
79 {
80  assert(L >= N);
81 
82  if(0 == L)
83  return 0;
84  if(0 == N)
85  return 1;
86  if(L == N)
87  return 1;
88  if(1 == N)
89  return L;
90 
91  unsigned long long result = 1;
92 
93  for(unsigned int i=1;i<=N;++i, --L)
94  {
95  auto g = gcd(result, i);
96  result /= g;
97  auto t = L / (i / g);
98 
99  if(result > std::numeric_limits<unsigned long long>::max() / t)
100  throw std::overflow_error("Overflow in CalcCombinations");
101 
102  result *= t;
103  }
104 
105  return result;
106 }
107 
114 unsigned long long Permutation::gcd(unsigned long long x, unsigned long long y)
115 {
116  assert(x >= y);
117 
118  while (y != 0)
119  {
120  unsigned long long t = x % y;
121  x = y;
122  y = t;
123  }
124 
125  return x;
126 }
127 
132 unsigned int Permutation::getMax()
133 {
134  return sizeof(mybitset)*8;
135 }
136 
137 /* vim: set ts=3 sw=3 expandtab :*/
Permutation(unsigned int)
Definition: Permutation.cpp:14
virtual mybitset next()
Definition: Permutation.cpp:30
static unsigned long long CalcCombinations(unsigned int, unsigned int)
Definition: Permutation.cpp:78
virtual mybitset get() const
Definition: Permutation.cpp:57
static unsigned long long gcd(unsigned long long, unsigned long long)
virtual void reset()
Definition: Permutation.cpp:66
static unsigned int getMax()