sandbox/Antoonvh/foreach_cell_usd.h
/* ===============================================================
* Tree traversal
* recursive() below is for reference only. The macro
* foreach_cell() is a stack-based implementation of
* recursive(). It is about 12% slower than the recursive
* version and 60% slower than simple array traversal.
*7/span>
* This article was useful:
* http://www.codeproject.com/Articles/418776/How-to-replace-recursive-functions-using-stack-and
*10/span>
* =============================================================== */
We switch the definitions for the _TOP and _BOTTOM children:
Also every function and definition gets a new name:
#include "grid/foreach_cell.h"
#define _TOP2 (2*point.j-GHOSTS)
#define _BOTTOM2 (_TOP2 + 1)
(root)
@def foreach_cell_root2{
int ig = 0, jg = 0; NOT_UNUSED(ig); NOT_UNUSED(jg);
;
Point point#if dimension == 1
struct { int l, i, stage; } stack[STACKSIZE];
#elif dimension == 2
struct { int l, i, j, stage; } stack[STACKSIZE];
#else // dimension == 3
int kg = 0; NOT_UNUSED(kg);
struct { int l, i, j, k, stage; } stack[STACKSIZE];
#endif
int _s = -1;
(0, root.i, root.j, root.k, 0);
_push while (_s >= 0) {
int stage;
();
_popif (!allocated (0))
continue;
switch (stage) {
case 0: {
POINT_VARIABLES;
/* do something */
@()
@def end_foreach_cell_root2if (point.level < grid->depth) {
(point.level, point.i, point.j, point.k, 1);
_push (point.level + 1, _LEFT, _BOTTOM2, _BACK, 0);
_push }
break;
}
#if dimension == 1
case 1: _push (point.level + 1, _RIGHT, _BOTTOM2, _BACK, 0); break;
#elif dimension == 2
case 1: _push (point.level, point.i, point.j, point.k, 2);
(point.level + 1, _LEFT, _TOP2, _BACK, 0); break;
_push case 2: _push (point.level, point.i, point.j, point.k, 3);
(point.level + 1, _RIGHT, _BOTTOM2, _BACK, 0); break;
_push case 3: _push (point.level + 1, _RIGHT, _TOP2, _BACK, 0); break;
#elif dimension == 3
case 1: _push (point.level, point.i, point.j, point.k, 2);
(point.level + 1, _LEFT, _BOTTOM2, _FRONT, 0); break;
_push case 2: _push (point.level, point.i, point.j, point.k, 3);
(point.level + 1, _LEFT, _TOP2, _BACK, 0); break;
_push case 3: _push (point.level, point.i, point.j, point.k, 4);
(point.level + 1, _LEFT, _TOP2, _FRONT, 0); break;
_push case 4: _push (point.level, point.i, point.j, point.k, 5);
(point.level + 1, _RIGHT, _BOTTOM2, _BACK, 0); break;
_push case 5: _push (point.level, point.i, point.j, point.k, 6);
(point.level + 1, _RIGHT, _BOTTOM2, _FRONT, 0); break;
_push case 6: _push (point.level, point.i, point.j, point.k, 7);
(point.level + 1, _RIGHT, _TOP2, _BACK, 0); break;
_push case 7: _push (point.level + 1, _RIGHT, _TOP2, _FRONT, 0); break;
#endif
}
}
}
@
() {
@def foreach_cell2#if dimension == 1
= {GHOSTS,0};
Point root #elif dimension == 2
= {GHOSTS,GHOSTS,0};
Point root #else // dimension == 3
= {GHOSTS,GHOSTS,GHOSTS,0};
Point root #endif
(root)
foreach_cell_root2
@() end_foreach_cell_root2() }
@define end_foreach_cell2
() {
@def foreach_cell_all2= { .level = 0 };
Point root for (root.i = GHOSTS*Period.x; root.i <= GHOSTS*(2 - Period.x); root.i++)
#if dimension >= 2
for (root.j = GHOSTS*Period.y; root.j <= GHOSTS*(2 - Period.y); root.j++)
#endif
#if dimension >= 3
for (root.k = GHOSTS*Period.z; root.k <= GHOSTS*(2 - Period.z); root.k++)
#endif
(root)
foreach_cell_root2
@() end_foreach_cell_root2() }
@define end_foreach_cell_all2
(condition, root)
@def foreach_cell_post_root2{
int ig = 0, jg = 0; NOT_UNUSED(ig); NOT_UNUSED(jg);
;
Point point#if dimension == 1
struct { int l, i, stage; } stack[STACKSIZE];
#elif dimension == 2
struct { int l, i, j, stage; } stack[STACKSIZE];
#else // dimension == 3
int kg = 0; NOT_UNUSED(kg);
struct { int l, i, j, k, stage; } stack[STACKSIZE];
#endif
int _s = -1;
(0, root.i, root.j, root.k, 0); /* the root cell */
_push while (_s >= 0) {
int stage;
();
_popif (!allocated (0))
continue;
switch (stage) {
case 0: {
POINT_VARIABLES;
if (point.level == grid->depth) {
(point.level, point.i, point.j, point.k, 8);
_push }
else {
(point.level, point.i, point.j, point.k, 1);
_push if (condition)
(point.level + 1, _LEFT, _BOTTOM, _BACK, 0);
_push }
break;
}
#if dimension == 1
case 1:
(point.level, point.i, point.j, point.k, 2);
_push if (condition)
(point.level + 1, _RIGHT, _BOTTOM, _BACK, 0);
_push break;
#elif dimension == 2
case 1:
(point.level, point.i, point.j, point.k, 2);
_push if (condition)
(point.level + 1, _LEFT, _TOP, _BACK, 0);
_push break;
case 2:
(point.level, point.i, point.j, point.k, 3);
_push if (condition)
(point.level + 1, _RIGHT, _BOTTOM, _BACK, 0);
_push break;
case 3:
(point.level, point.i, point.j, point.k, 4);
_push if (condition)
(point.level + 1, _RIGHT, _TOP, _BACK, 0);
_push break;
#elif dimension == 3
case 1:
(point.level, point.i, point.j, point.k, 2);
_push if (condition)
(point.level + 1, _LEFT, _BOTTOM, _FRONT, 0);
_push break;
case 2:
(point.level, point.i, point.j, point.k, 3);
_push if (condition)
(point.level + 1, _LEFT, _TOP, _BACK, 0);
_push break;
case 3:
(point.level, point.i, point.j, point.k, 4);
_push if (condition)
(point.level + 1, _LEFT, _TOP, _FRONT, 0);
_push break;
case 4:
(point.level, point.i, point.j, point.k, 5);
_push if (condition)
(point.level + 1, _RIGHT, _BOTTOM, _BACK, 0);
_push break;
case 5:
(point.level, point.i, point.j, point.k, 6);
_push if (condition)
(point.level + 1, _RIGHT, _BOTTOM, _FRONT, 0);
_push break;
case 6:
(point.level, point.i, point.j, point.k, 7);
_push if (condition)
(point.level + 1, _RIGHT, _TOP, _BACK, 0);
_push break;
case 7:
(point.level, point.i, point.j, point.k, 8);
_push if (condition)
(point.level + 1, _RIGHT, _TOP, _FRONT, 0);
_push break;
#endif
default: {
POINT_VARIABLES;
/* do something */
@()
@def end_foreach_cell_post_root2}
}
}
}
@
(condition)
@def foreach_cell_post2{
#if dimension == 1
= {GHOSTS,0};
Point root #elif dimension == 2
= {GHOSTS,GHOSTS,0};
Point root #else // dimension == 3
= {GHOSTS,GHOSTS,GHOSTS,0};
Point root #endif
(condition, root)
foreach_cell_post_root2
@() end_foreach_cell_post_root2() }
@define end_foreach_cell_post2
(condition) {
@def foreach_cell_post_all2= { .level = 0 };
Point root for (root.i = 0; root.i <= 2*GHOSTS; root.i++)
#if dimension >= 2
for (root.j = 0; root.j <= 2*GHOSTS; root.j++)
#endif
#if dimension >= 3
for (root.k = 0; root.k <= 2*GHOSTS; root.k++)
#endif
(condition, root)
foreach_cell_post_root2
@() end_foreach_cell_post_root2() }
@define end_foreach_cell_post_all2
() foreach_cell2()
@def foreach_leaf2if (is_leaf (cell)) {
if (is_active(cell) && is_local(cell)) {
@() } continue; } end_foreach_cell2() @define end_foreach_leaf2