Factoring out looping structure

Denis Koroskin 2korden at gmail.com
Mon Apr 6 13:48:28 PDT 2009


On Tue, 07 Apr 2009 00:33:04 +0400, Doctor J <nobody at nowhere.com> 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)



More information about the Digitalmars-d-learn mailing list