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 */
33template<unsigned int dim>
34struct 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
396template<>
397struct 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
524namespace 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