1 | #ifndef COMB_HPP |
2 | #define COMB_HPP |
3 | |
4 | #define COMB_ERROR 1001lu |
5 | |
6 | #include "util/se_util.hpp" |
7 | |
8 | /*! \brief Position of the element of dimension d in the hyper-cube of dimension dim |
9 | * |
10 | * These objects are returned by the Hyper-cube static functions |
11 | * The number of non-zero d define the dimensionality of the object ( +1 or -1 its position in the hypercube) |
12 | * |
13 | * ## Example |
14 | * |
15 | \verbatim |
16 | |
17 | (0,1) |
18 | (-1,1) +---------+ (1,1) |
19 | | | |
20 | | | |
21 | (-1,0)| (0,0) | (1,0) |
22 | | | |
23 | | | |
24 | (-1,-1) +---------+ (1,-1) |
25 | (0,-1) |
26 | \endverbatim |
27 | * |
28 | * |
29 | * \tparam dim of the hyper-cube |
30 | * |
31 | * |
32 | */ |
33 | template<unsigned int dim> |
34 | struct comb |
35 | { |
36 | //! Array that store the combination |
37 | char c[dim]; |
38 | |
39 | /*! \brief check if it is a valid combination |
40 | * |
41 | * \return true if it is valid |
42 | * |
43 | */ |
44 | |
45 | inline bool isValid() |
46 | { |
47 | for (size_t i = 0 ; i < dim ; i++) |
48 | { |
49 | if (c[i] != 1 && c[i] != -1 && c[i] != 0) |
50 | { |
51 | return false; |
52 | } |
53 | } |
54 | |
55 | return true; |
56 | } |
57 | |
58 | /*! \brief Check if the combination is a sub-element |
59 | * |
60 | * \param cmb combination to check if it is sub-element |
61 | * |
62 | * \return true if cmb is a sub-element of this combination |
63 | * |
64 | */ |
65 | |
66 | inline bool isSub(comb<dim> cmb) |
67 | { |
68 | for (size_t i = 0 ; i < dim ; i++) |
69 | { |
70 | if (c[i] != 0 && c[i] != cmb.c[i]) |
71 | { |
72 | return false; |
73 | } |
74 | } |
75 | |
76 | return true; |
77 | } |
78 | |
79 | /*! \brief Set all the elements to zero |
80 | * |
81 | */ |
82 | |
83 | inline void zero() |
84 | { |
85 | for (size_t i = 0 ; i < dim ; i++) |
86 | { |
87 | c[i] = 0; |
88 | } |
89 | } |
90 | |
91 | /*! \brief Set all the elements to -1 |
92 | * |
93 | */ |
94 | |
95 | inline void mone() |
96 | { |
97 | for (size_t i = 0 ; i < dim ; i++) |
98 | { |
99 | c[i] = -1; |
100 | } |
101 | } |
102 | |
103 | /*! \brief Bitwise operator & |
104 | * |
105 | * \return Result combination |
106 | * |
107 | */ |
108 | inline comb<dim> operator&(char c_) |
109 | { |
110 | comb<dim> ret; |
111 | |
112 | for (size_t i = 0 ; i < dim ; i++) |
113 | { |
114 | ret.c[i] = c[i] & c_; |
115 | } |
116 | |
117 | return ret; |
118 | } |
119 | |
120 | /*! \brief Flip the sign of the combination |
121 | * |
122 | * |
123 | */ |
124 | inline void sign_flip() |
125 | { |
126 | for (size_t i = 0 ; i < dim ; i++) |
127 | { |
128 | c[i] = -c[i]; |
129 | } |
130 | } |
131 | |
132 | /*! \brief Subtract the combinations and return the result |
133 | * |
134 | * \return Result combination |
135 | * |
136 | */ |
137 | inline comb<dim> operator-(const comb<dim> & t) |
138 | { |
139 | comb<dim> ret; |
140 | |
141 | for (size_t i = 0 ; i < dim ; i++) |
142 | { |
143 | ret.c[i] = c[i] - t.c[i]; |
144 | } |
145 | |
146 | return ret; |
147 | } |
148 | |
149 | /*! \brief flip the coefficent of the combination to be < 0 |
150 | * |
151 | * |
152 | * * 0 --> 0 |
153 | * * 1 --> -1 |
154 | * * 2 --> -2 |
155 | * * -1 --> -1 |
156 | * |
157 | * \return flipped combination |
158 | * |
159 | */ |
160 | inline comb<dim> flip() |
161 | { |
162 | comb<dim> ret; |
163 | |
164 | for (size_t i = 0 ; i < dim ; i++) |
165 | { |
166 | ret.c[i] = -abs(c[i]); |
167 | } |
168 | |
169 | return ret; |
170 | } |
171 | |
172 | /*! \brief Subtract the combinations and return the result |
173 | * |
174 | * \return Result combination |
175 | * |
176 | */ |
177 | inline comb<dim> operator-() |
178 | { |
179 | comb<dim> ret; |
180 | |
181 | for (size_t i = 0 ; i < dim ; i++) |
182 | { |
183 | ret.c[i] = -c[i]; |
184 | } |
185 | |
186 | return ret; |
187 | } |
188 | |
189 | /*! \brief sum the combinations and return the result |
190 | * |
191 | * \return Result combination |
192 | * |
193 | */ |
194 | inline comb<dim> operator+(const comb<dim> & t) |
195 | { |
196 | comb<dim> ret; |
197 | |
198 | for (size_t i = 0 ; i < dim ; i++) |
199 | { |
200 | ret.c[i] = c[i] + t.c[i]; |
201 | } |
202 | |
203 | return ret; |
204 | } |
205 | |
206 | /*! \brief Compare two combination |
207 | * |
208 | * check if they match |
209 | * |
210 | * \param t combination to check |
211 | * \return true if the two combination match, false otherwise |
212 | * |
213 | */ |
214 | inline bool operator!=(const comb<dim> & t) const |
215 | { |
216 | // Check if the two combination match |
217 | |
218 | for (size_t i = 0 ; i < dim ; i++) |
219 | { |
220 | if (c[i] != t.c[i]) |
221 | return true; |
222 | } |
223 | |
224 | // They match |
225 | |
226 | return false; |
227 | } |
228 | |
229 | /*! \brief Compare two combination |
230 | * |
231 | * check if they match |
232 | * |
233 | * \param t combination to check |
234 | * \return true if the two combination match, false otherwise |
235 | * |
236 | */ |
237 | inline bool operator==(const comb<dim> & t) const |
238 | { |
239 | return !this->operator!=(t); |
240 | } |
241 | |
242 | /*! \brief Get the i combination coefficient |
243 | * |
244 | * \param i coefficent |
245 | * \return the coefficent of the combination at position i |
246 | * |
247 | */ |
248 | |
249 | inline char operator[](int i) const |
250 | { |
251 | return c[i]; |
252 | } |
253 | |
254 | /*! \brief get the combination array pointer |
255 | * |
256 | * \return an array of char representing the combination |
257 | * |
258 | */ |
259 | |
260 | inline char * getComb() |
261 | { |
262 | return c; |
263 | } |
264 | |
265 | /*! \brief get the combination array pointer |
266 | * |
267 | * \return an array of char representing the combination |
268 | * |
269 | */ |
270 | |
271 | inline const char * getComb() const |
272 | { |
273 | return c; |
274 | } |
275 | |
276 | /*! \brief get the index i of the combination |
277 | * |
278 | * NOTE: used on expression template |
279 | * |
280 | * \param i index |
281 | * |
282 | * \return value of the i index |
283 | * |
284 | */ |
285 | inline char value(int i) const |
286 | { |
287 | return c[i]; |
288 | } |
289 | |
290 | |
291 | /* \brief It return the number of zero in the combination |
292 | * |
293 | * \return number of zero |
294 | * |
295 | */ |
296 | inline int n_zero() const |
297 | { |
298 | int zero = 0; |
299 | |
300 | for (size_t i = 0 ; i < dim ; i++) |
301 | { |
302 | if (c[i] == 0) zero++; |
303 | } |
304 | |
305 | return zero; |
306 | } |
307 | |
308 | //! Default constructor |
309 | comb() |
310 | {} |
311 | |
312 | /*! \brief Constructor from a list of numbers |
313 | * |
314 | * \param c list of numbers |
315 | * |
316 | */ |
317 | comb(std::initializer_list<char> c) |
318 | { |
319 | size_t i = 0; |
320 | for(char x : c) |
321 | {this->c[c.size() - i - 1] = x;i++;} |
322 | } |
323 | |
324 | /*! \brief Check if any alement in the combination is <= 0 |
325 | * |
326 | * +----#----+ |
327 | * | | |
328 | * | | |
329 | * # * # |
330 | * | | |
331 | * | | |
332 | * +----#----+ |
333 | * |
334 | * Is negative return true when the combination indicate * the down-left vertex + and down and left edge # |
335 | * |
336 | */ |
337 | bool isNegative() |
338 | { |
339 | for (size_t i = 0; i < dim ; i++) |
340 | { |
341 | if (c[i] > 0) |
342 | return false; |
343 | } |
344 | |
345 | return true; |
346 | } |
347 | |
348 | /*! \brief Convert a combination into string |
349 | * |
350 | * \return a string reppresentation of the combination |
351 | * |
352 | */ |
353 | std::string to_string() const |
354 | { |
355 | size_t i; |
356 | |
357 | std::stringstream str; |
358 | str << "(" ; |
359 | |
360 | // convert to string |
361 | for (i = 0 ; i < dim - 1 ; i++) |
362 | str << std::to_string(c[i]) << "," ; |
363 | |
364 | str << std::to_string(c[i]) << ")" ; |
365 | |
366 | return str.str(); |
367 | } |
368 | |
369 | /*! \brief Linearization |
370 | * |
371 | * From the combination produce a number |
372 | * |
373 | * \return the number |
374 | * |
375 | */ |
376 | size_t inline lin() const |
377 | { |
378 | size_t ret = 0; |
379 | size_t accu = 1; |
380 | |
381 | for (size_t i = 0 ; i < dim ; i++) |
382 | { |
383 | ret += (c[i] + 1) * accu; |
384 | accu *= 3; |
385 | } |
386 | |
387 | return ret; |
388 | } |
389 | }; |
390 | |
391 | /*! brief specialization of comb in case of dim 0 |
392 | * |
393 | * |
394 | */ |
395 | |
396 | template<> |
397 | struct comb<0> |
398 | { |
399 | //! FIX |
400 | char c[0]; |
401 | |
402 | /*! \brief check if it is a valid combination |
403 | * |
404 | * \return true if it is valid |
405 | * |
406 | */ |
407 | |
408 | inline bool isValid() |
409 | { |
410 | return true; |
411 | } |
412 | |
413 | /*! \brief Check if the combination is a sub-element |
414 | * |
415 | * \param cmb combination to check if it is sub-element |
416 | * |
417 | * \return true if cmb is a sub-element of this combination |
418 | * |
419 | */ |
420 | |
421 | inline bool isSub(comb<0> cmb) |
422 | { |
423 | return true; |
424 | } |
425 | |
426 | /*! \brief Set all the elements to zero |
427 | * |
428 | */ |
429 | |
430 | inline void zero() |
431 | { |
432 | } |
433 | |
434 | |
435 | /*! \brief Compare two combination |
436 | * |
437 | * check if they match |
438 | * |
439 | * \param t combination to check |
440 | * \return true if the two combination match, false otherwise |
441 | * |
442 | */ |
443 | inline bool operator!=(const comb<0> & t) const |
444 | { |
445 | // They match |
446 | |
447 | return true; |
448 | } |
449 | |
450 | /*! \brief Compare two combination |
451 | * |
452 | * check if they match |
453 | * |
454 | * \param t combination to check |
455 | * \return true if the two combination match, false otherwise |
456 | * |
457 | */ |
458 | inline bool operator==(const comb<0> & t) const |
459 | { |
460 | return true; |
461 | } |
462 | |
463 | /*! \brief Get the i combination coefficient |
464 | * |
465 | * \param i coefficent |
466 | * \return the coefficent of the combination at position i |
467 | * |
468 | */ |
469 | |
470 | inline char operator[](int i) |
471 | { |
472 | return 0; |
473 | } |
474 | |
475 | /*! \brief get the combination array pointer |
476 | * |
477 | * \return an array of char representing the combination |
478 | * |
479 | */ |
480 | |
481 | inline char * getComb() |
482 | { |
483 | return c; |
484 | } |
485 | |
486 | /*! \brief get the index i of the combination |
487 | * |
488 | * NOTE: used on expression template |
489 | * |
490 | * \param i index |
491 | * |
492 | * \return value of the i index |
493 | * |
494 | */ |
495 | inline char value(int i) const |
496 | { |
497 | return c[i]; |
498 | } |
499 | |
500 | |
501 | /* \brief It return the number of zero in the combination |
502 | * |
503 | * \return number of zero |
504 | * |
505 | */ |
506 | inline int n_zero() |
507 | { |
508 | return 0; |
509 | } |
510 | |
511 | /* \brief produce an unique number from the combination |
512 | * |
513 | * |
514 | * |
515 | */ |
516 | inline size_t lin() |
517 | { |
518 | return 0; |
519 | } |
520 | }; |
521 | |
522 | // create a specialization of std::vector<comb<0>> |
523 | |
524 | namespace std |
525 | { |
526 | /*! \brief Stub vector specialization |
527 | * |
528 | * On compiler previous 4.9.2 the code compile, and provide trivial functionality, |
529 | *(complex operations produce crash at runtime) |
530 | * |
531 | * On 4.9.2 does not even compile |
532 | * So we create a particular case that pass compilation give basic functionality, and |
533 | * crash in case of complex usage |
534 | * |
535 | */ |
536 | |
537 | template<> |
538 | class vector<comb<0>> |
539 | { |
540 | //! Pointer to nothing |
541 | comb<0> * ptr; |
542 | |
543 | public: |
544 | |
545 | /*! \brief Return 0 |
546 | * |
547 | * \return 0 |
548 | * |
549 | */ |
550 | size_t size() |
551 | { |
552 | return 0; |
553 | } |
554 | |
555 | /*! \brief Do nothing |
556 | * |
557 | * \param i ignored |
558 | * |
559 | * \return nothing |
560 | * |
561 | */ |
562 | comb<0> & operator[](size_t i) |
563 | { |
564 | return ptr[i]; |
565 | } |
566 | |
567 | /*! \brief Do nothing |
568 | * |
569 | * \param obj ignored |
570 | * |
571 | */ |
572 | void push_back(comb<0> & obj) |
573 | { |
574 | } |
575 | }; |
576 | } |
577 | |
578 | #endif |
579 | |