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)
@def foreach_cell_root2(root)
{
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;
_push (0, root.i, root.j, root.k, 0);
while (_s >= 0) {
int stage;
_pop();
if (!allocated (0))
continue;
switch (stage) {
case 0: {
POINT_VARIABLES;
/* do something */
@
@def end_foreach_cell_root2()
if (point.level < grid->depth) {
_push (point.level, point.i, point.j, point.k, 1);
_push (point.level + 1, _LEFT, _BOTTOM2, _BACK, 0);
}
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);
_push (point.level + 1, _LEFT, _TOP2, _BACK, 0); break;
case 2: _push (point.level, point.i, point.j, point.k, 3);
_push (point.level + 1, _RIGHT, _BOTTOM2, _BACK, 0); break;
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);
_push (point.level + 1, _LEFT, _BOTTOM2, _FRONT, 0); break;
case 2: _push (point.level, point.i, point.j, point.k, 3);
_push (point.level + 1, _LEFT, _TOP2, _BACK, 0); break;
case 3: _push (point.level, point.i, point.j, point.k, 4);
_push (point.level + 1, _LEFT, _TOP2, _FRONT, 0); break;
case 4: _push (point.level, point.i, point.j, point.k, 5);
_push (point.level + 1, _RIGHT, _BOTTOM2, _BACK, 0); break;
case 5: _push (point.level, point.i, point.j, point.k, 6);
_push (point.level + 1, _RIGHT, _BOTTOM2, _FRONT, 0); break;
case 6: _push (point.level, point.i, point.j, point.k, 7);
_push (point.level + 1, _RIGHT, _TOP2, _BACK, 0); break;
case 7: _push (point.level + 1, _RIGHT, _TOP2, _FRONT, 0); break;
#endif
}
}
}
@
@def foreach_cell2() {
#if dimension == 1
Point root = {GHOSTS,0};
#elif dimension == 2
Point root = {GHOSTS,GHOSTS,0};
#else // dimension == 3
Point root = {GHOSTS,GHOSTS,GHOSTS,0};
#endif
foreach_cell_root2 (root)
@
@define end_foreach_cell2() end_foreach_cell_root2() }
@def foreach_cell_all2() {
Point root = { .level = 0 };
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
foreach_cell_root2 (root)
@
@define end_foreach_cell_all2() end_foreach_cell_root2() }
@def foreach_cell_post_root2(condition, root)
{
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;
_push (0, root.i, root.j, root.k, 0); /* the root cell */
while (_s >= 0) {
int stage;
_pop();
if (!allocated (0))
continue;
switch (stage) {
case 0: {
POINT_VARIABLES;
if (point.level == grid->depth) {
_push (point.level, point.i, point.j, point.k, 8);
}
else {
_push (point.level, point.i, point.j, point.k, 1);
if (condition)
_push (point.level + 1, _LEFT, _BOTTOM, _BACK, 0);
}
break;
}
#if dimension == 1
case 1:
_push (point.level, point.i, point.j, point.k, 2);
if (condition)
_push (point.level + 1, _RIGHT, _BOTTOM, _BACK, 0);
break;
#elif dimension == 2
case 1:
_push (point.level, point.i, point.j, point.k, 2);
if (condition)
_push (point.level + 1, _LEFT, _TOP, _BACK, 0);
break;
case 2:
_push (point.level, point.i, point.j, point.k, 3);
if (condition)
_push (point.level + 1, _RIGHT, _BOTTOM, _BACK, 0);
break;
case 3:
_push (point.level, point.i, point.j, point.k, 4);
if (condition)
_push (point.level + 1, _RIGHT, _TOP, _BACK, 0);
break;
#elif dimension == 3
case 1:
_push (point.level, point.i, point.j, point.k, 2);
if (condition)
_push (point.level + 1, _LEFT, _BOTTOM, _FRONT, 0);
break;
case 2:
_push (point.level, point.i, point.j, point.k, 3);
if (condition)
_push (point.level + 1, _LEFT, _TOP, _BACK, 0);
break;
case 3:
_push (point.level, point.i, point.j, point.k, 4);
if (condition)
_push (point.level + 1, _LEFT, _TOP, _FRONT, 0);
break;
case 4:
_push (point.level, point.i, point.j, point.k, 5);
if (condition)
_push (point.level + 1, _RIGHT, _BOTTOM, _BACK, 0);
break;
case 5:
_push (point.level, point.i, point.j, point.k, 6);
if (condition)
_push (point.level + 1, _RIGHT, _BOTTOM, _FRONT, 0);
break;
case 6:
_push (point.level, point.i, point.j, point.k, 7);
if (condition)
_push (point.level + 1, _RIGHT, _TOP, _BACK, 0);
break;
case 7:
_push (point.level, point.i, point.j, point.k, 8);
if (condition)
_push (point.level + 1, _RIGHT, _TOP, _FRONT, 0);
break;
#endif
default: {
POINT_VARIABLES;
/* do something */
@
@def end_foreach_cell_post_root2()
}
}
}
}
@
@def foreach_cell_post2(condition)
{
#if dimension == 1
Point root = {GHOSTS,0};
#elif dimension == 2
Point root = {GHOSTS,GHOSTS,0};
#else // dimension == 3
Point root = {GHOSTS,GHOSTS,GHOSTS,0};
#endif
foreach_cell_post_root2(condition, root)
@
@define end_foreach_cell_post2() end_foreach_cell_post_root2() }
@def foreach_cell_post_all2(condition) {
Point root = { .level = 0 };
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
foreach_cell_post_root2 (condition, root)
@
@define end_foreach_cell_post_all2() end_foreach_cell_post_root2() }
@def foreach_leaf2() foreach_cell2()
if (is_leaf (cell)) {
if (is_active(cell) && is_local(cell)) {
@
@define end_foreach_leaf2() } continue; } end_foreach_cell2()