On Tue, 07 Apr 2009 00:33:04 +0400, Doctor J <[email protected]> wrote:
I'm new to template programming and I have a problem for which I think
it would be a good match, but I'd like to get some advice on how to go
about it.
I have a family of algorithms with the same looping structure, but
different particulars:
------------------------
state_t state ;
for (int i = 0 ; i < imax ; ++i)
{
compute_i(state, i);
for (int j = 0 ; j < jmax ; ++j)
{
compute_j(state,i,j);
for (int k = 0 ; k < kmax ; ++k)
{
compute_k(state,i,j,k);
for (int m = 0 ; m < mmax ; ++m)
{
compute_m(state,i,j,k,m);
}
finish_k(state,i,j,k);
}
finish_j(state,i,j);
}
}
--------------------------
I'd like to factor out the particulars from the looping structure, so I
can write the loops once and then implement a bunch of variants with
different particulars (the looping structure is in fact more complicated
than the abstract example given). Obviously I could do this by passing
in an object implementing an interface with all my functions; however,
the whole point of this exercise is to avoid the overhead of function
calls. The code needs to be efficient, and (especially the inner loop)
functions need to be inlined.
So: what are my options in D? Templates, delegates, mixins...? I'd
like to avoid string mixins if possible because they're a bit ugly.
Thanks!
An obvious way is to do a straight convertion:
template (alias compute_i, alias compute_j, alias compute_k, alias compute_m,
alias finish_k, alias finish_j, int imax, int jmax, int kmax, int mmax)
{
void compure(State)(ref State state)
{
for (int i = 0; i < imax; ++i)
{
compute_i(state, i);
for (int j = 0; j < jmax; ++j)
{
compute_j(state,i,j);
for (int k = 0; k < kmax; ++k)
{
compute_k(state,i,j,k);
for (int m = 0; m < mmax; ++m)
{
compute_m(state,i,j,k,m);
}
finish_k(state,i,j,k);
}
finish_j(state,i,j);
}
}
}
}
Usage:
void foo(ref State state, int i) { ... }
void bar(ref State state, int i, int j) { ... }
void baz(ref State state, int i, int j, int k) { ... }
void qux(ref State state, int i, int j, int k, int m) { ... }
void corge(ref State state, int i, int j, int k) { ... }
void grault(ref State state, int i, int j) { ... }
void garply(ref State state, int i) { ... }
struct State
{
// ...
}
State state;
compute!(foo,bar,baz,quz,corge,grault,garply)(state); // state is modified and
stores a result (pass nothing if it's not needed)