1 | /* |
2 | * grid_key_dx_iterator_sub.hpp |
3 | * |
4 | * Created on: Dec 15, 2015 |
5 | * Author: i-bird |
6 | */ |
7 | |
8 | #ifndef OPENFPM_DATA_SRC_GRID_ITERATORS_GRID_KEY_DX_ITERATOR_SUB_HPP_ |
9 | #define OPENFPM_DATA_SRC_GRID_ITERATORS_GRID_KEY_DX_ITERATOR_SUB_HPP_ |
10 | |
11 | #include "grid_key_dx_iterator.hpp" |
12 | #include "Grid/grid_key.hpp" |
13 | |
14 | /* \brief grid_key_dx_iterator_sub can adjust the domain if the border go out-of-side |
15 | * in this case a warning is produced |
16 | * |
17 | * \tparam dim dimensionality |
18 | * |
19 | */ |
20 | template <unsigned int dim, typename linearizer> |
21 | class print_warning_on_adjustment |
22 | { |
23 | public: |
24 | |
25 | /*! \brief print warning type1 |
26 | * |
27 | * \param gk_start start point |
28 | * |
29 | */ |
30 | inline static void pw1(size_t i, const grid_key_dx<dim> & gk_start) {std::cerr << "Warning: " << __FILE__ << ":" << __LINE__ << " start with index smaller than zero x[" << i << "]=" << gk_start.get(i) << "\n" ;} |
31 | |
32 | /*! \brief print warning type2 |
33 | * |
34 | * \param i component |
35 | * \param gk_start start point |
36 | * |
37 | */ |
38 | inline static void pw2(size_t i, const grid_key_dx<dim> & gk_start) {std::cerr << "Warning: " << __FILE__ << ":" << __LINE__ << " Cropping start point x[" << i << "]=" << gk_start.get(i) << " to x[" << i << "]=0 \n" ;} |
39 | |
40 | |
41 | /*! \brief print warning type3 |
42 | * |
43 | * |
44 | */ |
45 | inline static void pw3() {std::cerr << "Warning: " << __FILE__ << ":" << __LINE__ << " stop with smaller index than start \n" ;} |
46 | |
47 | |
48 | /*! \brief print warning type4 |
49 | * |
50 | * \param i component |
51 | * \param gk_stop stop point |
52 | * \param grid_base grid information |
53 | * |
54 | */ |
55 | inline static void pw4(size_t i, const grid_key_dx<dim> & gk_stop, const linearizer & grid_base) {std::cerr << "Warning: " << __FILE__ << ":" << __LINE__ << " stop index bigger than cell domain x[" << i << "]=" << gk_stop.get(i) << " > " << grid_base.size(i) << "\n" ;} |
56 | |
57 | /*! \brief print warning type5 |
58 | * |
59 | * |
60 | */ |
61 | inline static void pw5() {std::cerr << "Warning grid_key_dx_iterator_sub: " << __FILE__ << ":" << __LINE__ << " the starting point is not smaller or equal than than the stop point in all the coordinates" << "\n" ;} |
62 | }; |
63 | |
64 | /* \brief grid_key_dx_iterator_sub can adjust the domain if the border go out-of-side |
65 | * in this case a warning is produced |
66 | * |
67 | * \tparam dim dimensionality |
68 | * \tparam gb type of grid |
69 | * |
70 | */ |
71 | template <unsigned int dim, typename linearizer> |
72 | class do_not_print_warning_on_adjustment |
73 | { |
74 | public: |
75 | |
76 | /*! \brief print warning type1 |
77 | * |
78 | * \param i component |
79 | * \param gk_start start point |
80 | * |
81 | */ |
82 | inline static void pw1(size_t i, const grid_key_dx<dim> & gk_start) {} |
83 | |
84 | /*! \brief print warning type2 |
85 | * |
86 | * \param i component |
87 | * \param gk_start start point |
88 | * |
89 | */ |
90 | inline static void pw2(size_t i, const grid_key_dx<dim> & gk_start) {} |
91 | |
92 | /*! \brief print warning type3 |
93 | * |
94 | * |
95 | */ |
96 | inline static void pw3() {} |
97 | |
98 | /*! \brief print warning type4 |
99 | * |
100 | * \param i component |
101 | * \param gk_stop stop point |
102 | * \param grid_base grid information |
103 | * |
104 | */ |
105 | inline static void pw4(size_t i, const grid_key_dx<dim> & gk_stop, const linearizer & grid_base) {} |
106 | |
107 | /*! \brief print warning type5 |
108 | * |
109 | * |
110 | */ |
111 | inline static void pw5() {} |
112 | }; |
113 | |
114 | template<unsigned int dim, typename stl_type, typename linearizer> |
115 | struct post_increment_sub_impl |
116 | { |
117 | static inline void inc(grid_key_dx<dim> & gk, |
118 | grid_key_dx<dim> & gk_start, |
119 | grid_key_dx<dim> & gk_stop, |
120 | stl_type & stl_code, |
121 | linearizer & grid_base) |
122 | { |
123 | long int i = 0; |
124 | for ( ; i < dim-1 ; i++) |
125 | { |
126 | /* coverity[dead_error_begin] */ |
127 | size_t id = gk.get(i); |
128 | if ((long int)id > gk_stop.get(i)) |
129 | { |
130 | // ! overflow, increment the next index |
131 | |
132 | size_t idr = gk.get(i) - gk_start.get(i); |
133 | gk.set_d(i,gk_start.get(i)); |
134 | id = gk.get(i+1); |
135 | gk.set_d(i+1,id+1); |
136 | |
137 | stl_code.adjust_offset(i,idr,grid_base); |
138 | } |
139 | else |
140 | { |
141 | break; |
142 | } |
143 | } |
144 | } |
145 | }; |
146 | |
147 | |
148 | /** |
149 | * |
150 | * Grid key class iterator, iterate through a sub-grid defined by an hyper-cube |
151 | * |
152 | * \param dim dimensionality of the grid |
153 | * |
154 | * \note if you have a grid you can get this object from getIteratorSub() |
155 | * |
156 | * ### Sub grid iterator declaration and usage |
157 | * \snippet grid_unit_tests.hpp Sub-grid iterator test usage |
158 | * |
159 | */ |
160 | |
161 | template<unsigned int dim, typename stencil, typename linearizer, typename warn> |
162 | class grid_key_dx_iterator_sub : public grid_key_dx_iterator<dim,stencil,linearizer> |
163 | { |
164 | #ifdef SE_CLASS1 |
165 | bool initialized = false; |
166 | #endif |
167 | |
168 | //! grid base where we are iterating |
169 | linearizer grid_base; |
170 | |
171 | //! start point |
172 | grid_key_dx<dim> gk_start; |
173 | |
174 | //! stop point |
175 | grid_key_dx<dim> gk_stop; |
176 | |
177 | /*! \brief Initialize gk |
178 | * |
179 | */ |
180 | void Initialize() |
181 | { |
182 | // Check that start and stop are inside the domain otherwise crop them |
183 | |
184 | for (size_t i = 0 ; i < dim ; i++) |
185 | { |
186 | // if start smaller than 0 |
187 | if (gk_start.get(i) < 0) |
188 | { |
189 | #ifdef SE_CLASS1 |
190 | warn::pw1(i,gk_start); |
191 | #endif |
192 | if (gk_start.get(i) < gk_stop.get(i)) |
193 | { |
194 | #ifdef SE_CLASS1 |
195 | warn::pw2(i,gk_start); |
196 | #endif |
197 | gk_start.set_d(i,0); |
198 | } |
199 | else |
200 | { |
201 | #ifdef SE_CLASS1 |
202 | warn::pw3(); |
203 | #endif |
204 | // No points are available |
205 | gk_start.set_d(dim-1,gk_stop.get(dim-1)+1); |
206 | break; |
207 | } |
208 | } |
209 | |
210 | // if stop bigger than the domain |
211 | if (gk_stop.get(i) >= (long int)grid_base.size(i)) |
212 | { |
213 | #ifdef SE_CLASS1 |
214 | warn::pw4(i,gk_stop,grid_base); |
215 | #endif |
216 | |
217 | if (gk_start.get(i) < (long int)grid_base.size(i)) |
218 | gk_stop.set_d(i,grid_base.size(i)-1); |
219 | else |
220 | { |
221 | // No point are available |
222 | gk_start.set_d(dim-1,gk_stop.get(dim-1)+1); |
223 | break; |
224 | } |
225 | } |
226 | } |
227 | |
228 | //! Initialize gk |
229 | for (unsigned int i = 0 ; i < dim ; i++) |
230 | { |
231 | this->gk.set_d(i,gk_start.get(i)); |
232 | } |
233 | |
234 | #ifdef SE_CLASS1 |
235 | initialized = true; |
236 | #endif |
237 | } |
238 | |
239 | /*! \brief After incremented we have to check we did not overflo |
240 | * any dimension and in case adjust the dimensions |
241 | * |
242 | */ |
243 | void post_increment() |
244 | { |
245 | //! check the overflow of all the index with exception of the last dimensionality |
246 | |
247 | // post_increment_sub_impl<dim,stencil>::inc(this->gk,gk_start,gk_stop,this->stl_code,grid_base); |
248 | |
249 | long int i = 0; |
250 | for ( ; i < dim-1 ; i++) |
251 | { |
252 | /* coverity[dead_error_begin] */ |
253 | size_t id = this->gk.get(i); |
254 | if ((long int)id > gk_stop.get(i)) |
255 | { |
256 | // ! overflow, increment the next index |
257 | |
258 | size_t idr = this->gk.get(i) - gk_start.get(i); |
259 | this->gk.set_d(i,gk_start.get(i)); |
260 | id = this->gk.get(i+1); |
261 | this->gk.set_d(i+1,id+1); |
262 | |
263 | this->stl_code.adjust_offset(i,idr,grid_base); |
264 | } |
265 | else |
266 | { |
267 | break; |
268 | } |
269 | } |
270 | } |
271 | |
272 | public: |
273 | |
274 | /*! \brief Default constructor |
275 | * |
276 | * \warning extremely unsafe |
277 | * If you use this constructor before use the iterator you should call reinitialize first |
278 | * |
279 | */ |
280 | grid_key_dx_iterator_sub() |
281 | {} |
282 | |
283 | /*! \brief Constructor from another grid_key_dx_iterator_sub |
284 | * |
285 | * |
286 | * \param g_s_it grid_key_dx_iterator_sub |
287 | * |
288 | */ |
289 | grid_key_dx_iterator_sub(const grid_key_dx_iterator_sub<dim,stencil,linearizer> & g_s_it) |
290 | :grid_key_dx_iterator<dim,stencil>(g_s_it),grid_base(g_s_it.grid_base),gk_start(g_s_it.gk_start), gk_stop(g_s_it.gk_stop) |
291 | { |
292 | #ifdef SE_CLASS1 |
293 | //! If we are on debug check that the stop grid_key id bigger than the start |
294 | //! grid_key |
295 | |
296 | for (unsigned int i = 0 ; i < dim ; i++) |
297 | { |
298 | if (gk_start.get(i) > gk_stop.get(i)) |
299 | { |
300 | warn::pw5(); |
301 | } |
302 | } |
303 | #endif |
304 | |
305 | Initialize(); |
306 | } |
307 | |
308 | |
309 | /*! \brief Constructor require a grid grid<dim,T> |
310 | * |
311 | * It construct an iterator over an hyper-cube defined by start and stop, |
312 | * \warning if start and stop are outside the domain defined by g the intersection |
313 | * will be considered |
314 | * |
315 | * \tparam T type of object that the grid store |
316 | * |
317 | * \param g Grid on which iterate |
318 | * \param start starting point |
319 | * \param stop end point |
320 | * |
321 | */ |
322 | grid_key_dx_iterator_sub(const linearizer & g, |
323 | const grid_key_dx<dim> & start, |
324 | const grid_key_dx<dim> & stop) |
325 | : grid_key_dx_iterator<dim,stencil,linearizer>(g),grid_base(g),gk_start(start), gk_stop(stop) |
326 | { |
327 | #ifdef SE_CLASS1 |
328 | //! If we are on debug check that the stop grid_key id bigger than the start |
329 | //! grid_key |
330 | |
331 | for (unsigned int i = 0 ; i < dim ; i++) |
332 | { |
333 | if (gk_start.get(i) > gk_stop.get(i)) |
334 | { |
335 | warn::pw5(); |
336 | } |
337 | } |
338 | #endif |
339 | |
340 | Initialize(); |
341 | } |
342 | |
343 | |
344 | /*! \brief Constructor require a grid grid<dim,T> |
345 | * |
346 | * It construct an iterator over an hyper-cube defined by start and stop, |
347 | * \warning if start and stop are outside the domain defined by g the intersection |
348 | * will be considered |
349 | * |
350 | * \tparam T type of object that the grid store |
351 | * |
352 | * \param g Grid on which iterate |
353 | * \param start starting point |
354 | * \param stop end point |
355 | * \param stencil_pnt stencil points |
356 | * |
357 | */ |
358 | grid_key_dx_iterator_sub(const linearizer & g, |
359 | const grid_key_dx<dim> & start, |
360 | const grid_key_dx<dim> & stop, |
361 | const grid_key_dx<dim> (& stencil_pnt)[stencil::nsp]) |
362 | :grid_key_dx_iterator<dim,stencil,linearizer>(g,stencil_pnt),grid_base(g),gk_start(start), gk_stop(stop) |
363 | { |
364 | #ifdef SE_CLASS1 |
365 | //! If we are on debug check that the stop grid_key id bigger than the start |
366 | //! grid_key |
367 | |
368 | for (unsigned int i = 0 ; i < dim ; i++) |
369 | { |
370 | if (gk_start.get(i) > gk_stop.get(i)) |
371 | { |
372 | warn::pw5(); |
373 | } |
374 | } |
375 | #endif |
376 | |
377 | Initialize(); |
378 | grid_key_dx_iterator<dim,stencil>::calc_stencil_offset(this->gk); |
379 | } |
380 | |
381 | /*! \brief Constructor |
382 | * |
383 | * It construct an iterator setting only the stencil point. |
384 | * Require reinitialize to make it work |
385 | * |
386 | * |
387 | * \param stencil_pnt stencil points |
388 | * |
389 | */ |
390 | grid_key_dx_iterator_sub(const grid_key_dx<dim> (& stencil_pnt)[stencil::nsp]) |
391 | :grid_key_dx_iterator<dim,stencil>(stencil_pnt) |
392 | { |
393 | } |
394 | |
395 | /*! \brief Constructor require a grid grid<dim,T> |
396 | * |
397 | * It construct an iterator over an hyper-cube defined by start and stop, |
398 | * \warning if start and stop are outside the domain defined by g the intersection |
399 | * will be considered |
400 | * |
401 | * \tparam T type of object that the grid store |
402 | * |
403 | * \param g info of the grid where we are iterating |
404 | * \param m Margin of the domain |
405 | * |
406 | */ |
407 | grid_key_dx_iterator_sub(const linearizer & g, const size_t m) |
408 | :grid_key_dx_iterator<dim>(g),grid_base(g) |
409 | { |
410 | // Initialize the start and stop point |
411 | for (unsigned int i = 0 ; i < dim ; i++) |
412 | { |
413 | gk_start.set_d(i,m); |
414 | gk_stop.set_d(i,g.size(i)-m-1); |
415 | } |
416 | |
417 | // |
418 | Initialize(); |
419 | } |
420 | |
421 | /*! \brief Constructor require a grid grid<dim,T> |
422 | * |
423 | * It construct an iterator over an hyper-cube defined by start and stop, |
424 | * |
425 | * |
426 | * \param g Grid on which iterate |
427 | * \param start starting point |
428 | * \param stop end point |
429 | * |
430 | */ |
431 | grid_key_dx_iterator_sub(const linearizer & g, |
432 | const size_t (& start)[dim], |
433 | const size_t (& stop)[dim]) |
434 | :grid_key_dx_iterator<dim>(g),grid_base(g),gk_start(start), gk_stop(stop) |
435 | { |
436 | #ifdef SE_CLASS1 |
437 | //! If we are on debug check that the stop grid_key id bigger than the start |
438 | //! grid_key |
439 | |
440 | for (unsigned int i = 0 ; i < dim ; i++) |
441 | { |
442 | if (start[i] > stop[i]) |
443 | { |
444 | warn::pw5(); |
445 | } |
446 | } |
447 | #endif |
448 | |
449 | Initialize(); |
450 | } |
451 | |
452 | /*! \brief Get the next element |
453 | * |
454 | * Get the next element |
455 | * |
456 | * \return the next grid_key |
457 | * |
458 | */ |
459 | grid_key_dx_iterator_sub<dim,stencil,linearizer,warn> & operator++() |
460 | { |
461 | #ifdef SE_CLASS1 |
462 | if (initialized == false) |
463 | {std::cerr << "Error: " << __FILE__ << __LINE__ << " using unitialized iterator" << "\n" ;} |
464 | #endif |
465 | |
466 | //! increment the first index |
467 | |
468 | size_t id = this->gk.get(0); |
469 | this->gk.set_d(0,id+1); |
470 | |
471 | this->stl_code.increment(); |
472 | |
473 | //! check the overflow of all the index with exception of the last dimensionality |
474 | |
475 | post_increment(); |
476 | |
477 | return *this; |
478 | } |
479 | |
480 | /*! \brief increment the operator by more than one |
481 | * |
482 | * \return the next grid_key |
483 | * |
484 | */ |
485 | grid_key_dx_iterator_sub<dim,stencil,warn> & operator+=(int nsteps) |
486 | { |
487 | #ifdef SE_CLASS1 |
488 | if (initialized == false) |
489 | {std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " using unitialized iterator" << "\n" ;} |
490 | #endif |
491 | |
492 | for (size_t i = 0 ; i < nsteps ; i++) |
493 | { |
494 | this->operator ++(); |
495 | } |
496 | |
497 | return *this; |
498 | } |
499 | |
500 | /*! \brief Check if there is the next element |
501 | * |
502 | * Check if there is the next element |
503 | * |
504 | * \return true if there is the next, false otherwise |
505 | * |
506 | */ |
507 | inline bool isNext() |
508 | { |
509 | #ifdef SE_CLASS1 |
510 | if (initialized == false) |
511 | {std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " using unitialized iterator" << "\n" ;} |
512 | #endif |
513 | |
514 | if (this->gk.get(dim-1) <= gk_stop.get(dim-1)) |
515 | { |
516 | //! we did not reach the end of the grid |
517 | |
518 | return true; |
519 | } |
520 | |
521 | //! we reach the end of the grid |
522 | return false; |
523 | } |
524 | |
525 | /*! \brief Return the actual grid key iterator |
526 | * |
527 | * \return the actual key |
528 | * |
529 | */ |
530 | inline grid_key_dx<dim> get() const |
531 | { |
532 | #ifdef SE_CLASS1 |
533 | if (initialized == false) |
534 | {std::cerr << "Error: " << __FILE__ << __LINE__ << " using unitialized iterator" << "\n" ;} |
535 | #endif |
536 | |
537 | return grid_key_dx_iterator<dim,stencil,linearizer>::get(); |
538 | } |
539 | |
540 | /*! \brief Reinitialize the iterator |
541 | * |
542 | * it re-initialize the iterator with the passed grid_key_dx_iterator_sub |
543 | * the actual position of the grid_key_dx_iterator_sub is ignored |
544 | * |
545 | * \param g_s_it grid_key_dx_iterator_sub |
546 | * |
547 | */ |
548 | inline void reinitialize(const grid_key_dx_iterator_sub<dim> & g_s_it) |
549 | { |
550 | // Reinitialize the iterator |
551 | |
552 | grid_key_dx_iterator<dim,stencil>::reinitialize(g_s_it); |
553 | grid_base = g_s_it.getGridInfo(); |
554 | gk_start = g_s_it.getStart(); |
555 | gk_stop = g_s_it.getStop(); |
556 | |
557 | |
558 | #ifdef SE_CLASS1 |
559 | //! If we are on debug check that the stop grid_key id bigger than the start |
560 | //! grid_key |
561 | |
562 | for (unsigned int i = 0 ; i < dim ; i++) |
563 | { |
564 | if (gk_start.get(i) > gk_stop.get(i)) |
565 | { |
566 | warn::pw5(); |
567 | } |
568 | } |
569 | |
570 | initialized = true; |
571 | #endif |
572 | |
573 | Initialize(); |
574 | grid_key_dx_iterator<dim,stencil>::calc_stencil_offset(this->gk); |
575 | } |
576 | |
577 | /*! \brief Get the volume spanned by this sub-grid iterator |
578 | * |
579 | * \return the volume |
580 | * |
581 | */ |
582 | inline size_t getVolume() |
583 | { |
584 | return Box<dim,long int>::getVolumeKey(gk_start.get_k(), gk_stop.get_k()); |
585 | } |
586 | |
587 | /*! \brief Reset the iterator (it restart from the beginning) |
588 | * |
589 | */ |
590 | inline void reset() |
591 | { |
592 | //! Initialize to 0 the index |
593 | |
594 | for (size_t i = 0 ; i < dim ; i++) |
595 | {this->gk.set_d(i,gk_start.get(i));} |
596 | } |
597 | |
598 | /*! \brief Return the grid information related to this grid |
599 | * |
600 | * |
601 | * |
602 | */ |
603 | inline const linearizer & getGridInfo() const |
604 | { |
605 | return grid_base; |
606 | } |
607 | |
608 | /*! \brief Starting point |
609 | * |
610 | * \return starting point |
611 | * |
612 | */ |
613 | const grid_key_dx<dim> & getStart() const |
614 | { |
615 | return gk_start; |
616 | } |
617 | |
618 | /*! \brief Stop point |
619 | * |
620 | * \return stop point |
621 | * |
622 | */ |
623 | const grid_key_dx<dim> & getStop() const |
624 | { |
625 | return gk_stop; |
626 | } |
627 | |
628 | /*! \brief Sum a template constant |
629 | * |
630 | * \tparam compile-time offset |
631 | * |
632 | */ |
633 | template<unsigned int tot_add> |
634 | inline void private_sum() |
635 | { |
636 | this->stl_code.template private_sum<tot_add>(); |
637 | } |
638 | |
639 | /*! \brief Sum a template constant |
640 | * |
641 | * \param tot_add Add an offset to all the pointer |
642 | * |
643 | */ |
644 | inline void private_adjust(size_t tot_add) |
645 | { |
646 | this->stl_code.private_adjust(tot_add); |
647 | } |
648 | |
649 | /* \brief Set the iterator in a way that isNext return false |
650 | * |
651 | */ |
652 | void invalidate() |
653 | { |
654 | this->gk.set_d(dim-1,1); |
655 | this->gk_stop.set_d(dim-1,0); |
656 | |
657 | #ifdef SE_CLASS1 |
658 | this->initialized = true; |
659 | #endif |
660 | } |
661 | }; |
662 | |
663 | |
664 | //// Specialization for dimension 0 |
665 | |
666 | /** |
667 | * |
668 | * Grid key class iterator, iterate through a sub-grid defined by an hyper-cube |
669 | * |
670 | * \param dim dimensionality of the grid |
671 | * |
672 | * \note if you have a grid you can get this object from getIteratorSub() |
673 | * |
674 | * ### Sub grid iterator declaration and usage |
675 | * \snippet grid_unit_tests.hpp Sub-grid iterator test usage |
676 | * |
677 | */ |
678 | |
679 | template<typename warn> |
680 | class grid_key_dx_iterator_sub<0,warn> |
681 | { |
682 | |
683 | public: |
684 | |
685 | grid_key_dx_iterator_sub() |
686 | {} |
687 | |
688 | /*! \brief Next point |
689 | * |
690 | * stub version do nothing |
691 | * |
692 | * \return itself |
693 | * |
694 | */ |
695 | grid_key_dx_iterator<0> & operator++() |
696 | {return *this;} |
697 | |
698 | /*! \brief Is there a next point |
699 | * |
700 | * stub version |
701 | * |
702 | * \return always false |
703 | * |
704 | */ |
705 | inline bool isNext() |
706 | {return false;} |
707 | |
708 | /*! \brief return the volume |
709 | * |
710 | * stub version |
711 | * |
712 | * \return always 0 |
713 | * |
714 | */ |
715 | inline size_t getVolume() |
716 | {return 0;} |
717 | |
718 | /*! \brief Reset the iterator |
719 | * |
720 | * stub version, do nothing |
721 | * |
722 | * |
723 | */ |
724 | inline void reset() |
725 | {} |
726 | }; |
727 | |
728 | #endif /* OPENFPM_DATA_SRC_GRID_ITERATORS_GRID_KEY_DX_ITERATOR_SUB_HPP_ */ |
729 | |