StatMech
Loading...
Searching...
No Matches
IntegerComposition.hpp
Go to the documentation of this file.
1#pragma once
10#include "Headers/mydebug.hpp"
11#include <Eigen/Dense>
12#include <iostream>
13
14#ifndef __NVCC__
15 #define __host__
16 #define __device__
17#endif
18
19#if __has_include(<omp.h>)
20 #include <omp.h>
21__host__ __device__ static inline int get_max_threads() {
22 #ifdef __CUDA_ARCH__
23 return 1;
24 #else
25 return omp_get_max_threads();
26 #endif
27}
28__host__ __device__ static inline int get_thread_num() {
29 #ifdef __CUDA_ARCH__
30 return 0;
31 #else
32 return omp_get_thread_num();
33 #endif
34}
35#else
36constexpr static inline int get_max_threads() { return 1; }
37constexpr static inline int get_thread_num() { return 0; }
38#endif
39
40template<class T>
42 template<class U, void* dummy = (&U::operator[], &U::resize, nullptr)>
43 static std::true_type test(U*);
44 static std::false_type test(...);
45
46 public:
47 static constexpr bool value = decltype(test((T*)nullptr))::value;
48};
49template<class T>
50inline constexpr bool is_container_v = is_container<T>::value;
51
58 private:
59 typedef unsigned long Index_t;
60 int m_N;
62 int m_Max;
64 Eigen::MatrixX<Index_t> workA;
65 Eigen::MatrixX<Index_t> workB;
66
67 public:
75 __host__ __device__ IntegerComposition() { debug_constructor_printf(Default); }
76 __host__ __device__ IntegerComposition(int N, int Length, int Max);
77 __host__ __device__ IntegerComposition(IntegerComposition const& other)
78 : m_N(other.value()),
79 m_Length(other.length()),
80 m_Max(other.max()),
81 m_dim(other.dim()),
82 workA(other.workA),
83 workB(other.workB) {
84 debug_constructor_printf((Copy));
85 }
86
87 __host__ __device__ int value() const { return m_N; };
88 __host__ __device__ int length() const { return m_Length; };
89 __host__ __device__ int max() const { return m_Max; };
90 __host__ __device__ Index_t dim() const { return m_dim; };
91
99 __host__ void status(void) const {
100 std::cout << "IntegerComposition.status()"
101 << "\n"
102 << "\tValue:" << this->m_N << "\n"
103 << "\tLength:" << this->m_Length << "\n"
104 << "\tMax: " << this->m_Max << "\n"
105 << "\tDim: " << this->m_dim << std::endl;
106 std::cout << "workA:\n"
107 << workA << "\n"
108 << "workB:\n"
109 << workB << std::endl;
110 }
111
121 template<typename Vector_t>
122 __host__ __device__ Index_t partToOrdinal(Vector_t const& vec) const;
123
133 template<class Vector_t>
134 __host__ __device__ void ordinalToPart(Vector_t& vec, Index_t const num) const;
135
136 __host__ __device__ Eigen::RowVectorXi ordinalToPart(Index_t const num) const {
137 Eigen::RowVectorXi res(this->m_Length);
138 this->ordinalToPart(res, num);
139 return res;
140 }
141
142 template<typename Index_>
143 __host__ __device__ int locNumber(Index_ const num, Index_ const pos) const;
144
145 template<class Vector_t>
146 __host__ __device__ Index_t translate(Index_t const num, int trans,
147 Vector_t& workSpace) const;
148
149 __host__ __device__ Index_t translate(Index_t const num, int trans) const {
150 Eigen::ArrayXi config(m_Length);
151 return this->translate(num, trans, config);
152 }
153};
154
155inline IntegerComposition::IntegerComposition(int N, int Length, int Max)
156 : m_N(N),
157 m_Length(Length),
158 m_Max(Max < N ? Max : N),
159 workA(N + 1, Length),
160 workB(N + 1, Length) {
161 // debug_printf("IntegerComposition::IntegerComposition(%d,%d,%d) : Dim = %d\n", (int)N,
162 // (int)Length, (int)Max, (int)m_dim);
163 if(Length <= 1) {
164 m_dim = Length;
165 return;
166 }
167
168 int max = std::min(Max, N);
169 auto& Dims = workB;
170 for(int l = 0; l < Length; ++l) Dims(0, l) = 1;
171 for(int n = N; n > max; --n) {
172 Dims(n, 1) = 0;
173 Dims(n, 0) = 0;
174 workA(n, 0) = 0;
175 }
176 for(int n = max; n >= 0; --n) {
177 Dims(n, 1) = 1;
178 Dims(n, 0) = 0;
179 workA(n, 0) = 0;
180 }
181 // Recursively calculate Dims(l,n) for remaining (l,n)
182 for(int l = 2; l < Length; ++l)
183 for(int n = 1; n <= N; ++n) {
184 Dims(n, l) = 0;
185 for(int k = 0; k <= std::min(max, n); ++k) { Dims(n, l) += Dims(n - k, l - 1); }
186 }
187 // std::cout << Dims << "\n" << std::endl;
188
189 for(int l = 1; l < Length; ++l) {
190 workA(0, l) = Dims(N, Length - l);
191 for(int n = 1; n <= N; ++n) workA(n, l) = workA(n - 1, l) + Dims(N - n, Length - l);
192 }
193 // std::cout << workA << "\n" << std::endl;
194
195 for(int l = 0; l < Length; ++l) workB(0, l) = 0;
196 for(int n = 1; n <= N; ++n) {
197 for(int l = 1; l < Length - 1; ++l) workB(n, l) = workA(n - 1, l) - workA(n - 1, l + 1);
198 workB(n, Length - 1) = workA(n - 1, Length - 1);
199 }
200 // std::cout << workB << "\n" << std::endl;
201
202 m_dim = workA(max, 1);
203 // std::cout << "Dim = " << m_dim << std::endl;
204 debug_printf("(END) IntegerComposition::IntegerComposition(%d,%d,%d) : Dim = %d\n", (int)N,
205 (int)Length, (int)Max, (int)m_dim);
206}
207
208template<typename Vector_t>
210 Vector_t const& vec) const {
211 IntegerComposition::Index_t z = 0, res = 0;
212 for(int l = 1; l != int(m_Length); ++l) {
213 assert(m_Length - l >= 0);
214 assert(m_Length - l < vec.size());
215 z += vec[m_Length - l];
216
217 assert(z < workB.rows());
218 assert(l < workB.cols());
219 res += workB(z, l);
220 }
221 return res;
222}
223
224template<typename Vector_t>
225__host__ __device__ inline void IntegerComposition::ordinalToPart(
226 Vector_t& vec, IntegerComposition::Index_t const num) const {
227 IntegerComposition::Index_t num_copy = num;
228 int z = 0, zprev = 0;
229#ifndef __CUDA_ARCH__
230 vec.resize(m_Length);
231#else
232 assert(vec.size() >= m_Length);
233#endif
234 // if constexpr(is_container_v<Vector_t>) { vec.resize(m_Length); }
235 for(int l = 1; l != m_Length; ++l) {
236 assert(z < workA.rows());
237 assert(l < workA.cols());
238 while(workA(z, l) <= num_copy) z += 1;
239
240 assert(m_Length - l >= 0);
241 assert(m_Length - l < vec.size());
242 vec[m_Length - l] = z - zprev;
243 zprev = z;
244
245 assert(z < workB.rows());
246 assert(l < workB.cols());
247 num_copy -= workB(z, l);
248 }
249 vec[0] = m_N - z;
250}
251
252template<typename Index_>
253__host__ __device__ inline int IntegerComposition::locNumber(Index_ const num,
254 Index_ const pos) const {
255 // Eigen::ArrayXi config(m_Length);
256 // this->ordinalToPart(config, num);
257 // return config(pos);
258
259 auto num_copy = num;
260 auto position = ((pos % m_Length) + m_Length) % m_Length;
261 int z = 0, zprev = 0;
262 int l;
263 for(l = 1; l != m_Length - position; ++l) {
264 assert(z < workA.rows());
265 assert(l < workA.cols());
266 while(workA(z, l) <= num_copy) z += 1;
267 zprev = z;
268
269 assert(z < workB.rows());
270 assert(l < workB.cols());
271 num_copy -= workB(z, l);
272 }
273 assert(z < workA.rows());
274 assert(l < workA.cols());
275 if(pos == 0) { return m_N - z; }
276 else {
277 while(workA(z, l) <= num_copy) z += 1;
278 return z - zprev;
279 }
280}
281
282template<class Vector_t>
284 IntegerComposition::Index_t const num, int trans, Vector_t& workSpace) const {
285 if(workSpace.size() < m_Length)
286 debug_printf("%s\n\tworkSpace.size()=%d\n", __PRETTY_FUNCTION__, (int)workSpace.size());
287 assert(workSpace.size() >= m_Length);
288 // debug_printf("%s\n\t workSpace=%p, workSpace.size()=%d, m_Length=%d\n", __PRETTY_FUNCTION__,
289 // workSpace.data(), (int)workSpace.size(), (int)m_Length);
290 this->ordinalToPart(workSpace, num);
291 Index_t z = 0, res = 0;
292 for(int l = 0; l < int(m_Length); ++l) {
293 // if(!(z < workB.rows()) || !(l < workB.cols())) {
294 // debug_printf("\t (z=%d, l=%d), workB.rows()=%d, workB.cols()=%d\n", (int)z, (int)l,
295 // (int)workB.rows(), (int)workB.cols());
296 // }
297 assert(z < workB.rows());
298 assert(l < workB.cols());
299 res += workB(z, l);
300
301 assert(int(m_Length - 1 - l + trans) % workSpace.size() < workSpace.size());
302 z += workSpace[int(m_Length - 1 - l + trans) % workSpace.size()];
303 }
304 return res;
305}
constexpr bool is_container_v
Definition IntegerComposition.hpp:50
Lists a weak composition of an integer N up to length L with a constraint that each summand does not ...
Definition IntegerComposition.hpp:57
__host__ __device__ IntegerComposition()
Construct a new Integer Composition object.
Definition IntegerComposition.hpp:75
__host__ __device__ int locNumber(Index_ const num, Index_ const pos) const
Definition IntegerComposition.hpp:253
__host__ __device__ Index_t translate(Index_t const num, int trans) const
Definition IntegerComposition.hpp:149
int m_Length
Definition IntegerComposition.hpp:61
__host__ void status(void) const
Show the status of the instance.
Definition IntegerComposition.hpp:99
__host__ __device__ IntegerComposition(IntegerComposition const &other)
Definition IntegerComposition.hpp:77
__host__ __device__ Eigen::RowVectorXi ordinalToPart(Index_t const num) const
Definition IntegerComposition.hpp:136
int m_N
Definition IntegerComposition.hpp:60
__host__ __device__ Index_t dim() const
Definition IntegerComposition.hpp:90
Eigen::MatrixX< Index_t > workB
Definition IntegerComposition.hpp:65
unsigned long Index_t
Definition IntegerComposition.hpp:59
__host__ __device__ int max() const
Definition IntegerComposition.hpp:89
__host__ __device__ void ordinalToPart(Vector_t &vec, Index_t const num) const
Converts an ordinal number of a composition of the integer N to a vector form.
Definition IntegerComposition.hpp:225
__host__ __device__ int value() const
Definition IntegerComposition.hpp:87
int m_Max
Definition IntegerComposition.hpp:62
__host__ __device__ Index_t translate(Index_t const num, int trans, Vector_t &workSpace) const
Definition IntegerComposition.hpp:283
__host__ __device__ int length() const
Definition IntegerComposition.hpp:88
__host__ __device__ Index_t partToOrdinal(Vector_t const &vec) const
Converts an composition of the integer N from a vector form to an ordinal number.
Definition IntegerComposition.hpp:209
Eigen::MatrixX< Index_t > workA
Definition IntegerComposition.hpp:64
Index_t m_dim
Definition IntegerComposition.hpp:63
Definition IntegerComposition.hpp:41
static std::false_type test(...)
static std::true_type test(U *)
static constexpr bool value
Definition IntegerComposition.hpp:47