freepooma-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

template idiom in the Blitz stencils; TList as a Domain simplification


From: Allan Stokes
Subject: template idiom in the Blitz stencils; TList as a Domain simplification
Date: Thu, 7 Jun 2001 06:31:22 -0700

Yesterday I read through the Blitz stencil implementation.  It's relatively
uncomplicated.   The main trick is the use of #define tricks to make it
convenient to define user stencils.

This is a good example of one of the many dozens of prebuild stencils which
Blitz includes.

BZ_DECLARE_STENCIL_OPERATOR1(Laplacian3D, A)
    return -6.0 * A
      + A.shift(-1,0) + A.shift(1,0)
      + A.shift(-1,1) + A.shift(1,1)
      + A.shift(-1,2) + A.shift(1,2);
BZ_END_STENCIL_OPERATOR

Laplacian3D becomes the name of the stencil.  The array A is the single
argument.  The offsets are applied by shifting the "entire" array.  Blitz
uses a trick internally to figure out what "entire" means.

The first time a stencil is run, it is applied to a psuedo-array which does
nothing but keep track of the range of offsets supplied.  Blitz then
restricts the stencil to the largest interior sub-array such that the
supplied shifts are legal.

I'll write a short note describing the Blitz approach in more detail after
contrasting the Pooma stencils.

What caught my eye was a complaint, presumably by Todd, which is reminiscent
of some ugly template constructs in the Domain module.

/*
 * There are a lot of kludges in this code to work around the fact that
 * you can't have default template parameters with function templates.
 * Ideally, one would implement applyStencil(..) as:
 *
 * template<class T_stencil, class T_numtype1, class T_array2,
 *    class T_array3, class T_array4, class T_array5, class T_array6,
 *    class T_array7, class T_array8, class T_array9, class T_array10,
 *    class T_array11>
 * void applyStencil(const T_stencil& stencil, Array<T_numtype1,3>& A,
 *    T_array2& B = _dummyArray, T_array3& C = _dummyArray, ......)
 *
 * and allow for up to (say) 11 arrays to be passed.  But this doesn't
 * appear to be legal C++.  Instead, 11 versions of applyStencil are
 * provided, each one with a different number of array parameters,
 * and these stubs fill in the _dummyArray parameters and invoke
 * applyStencil_imp().
 */

I'm quite certain that C++ doesn't allow this.  I vaguely recall discussing
the point with John Spicer when I tried to something like this myself.

Lately there's been some discussion of possible extensions to C++ on
comp.std.c++  I often have ideas about how C++ could be fixed, but few which
are practical.  This is a case which could be handled quite easily.

template <class T, class A = Dummy, class B = Dummy>
  void applyStencil (T t, A a = Dummy(), B b = Dummy())

Presently, default types are not allowed for function templates.  Default
types could be allowed in the role of providing a default type when the
argument position is not supplied in the call.  If the type had a default in
this situation, then the default value would have somewhere to go.

This is one mechanism which might help prevent clusters of redundant
function signatures.

One of the ways in which Pooma goes against the grain is the use of domain
arguments in vararg contexts, much like Todd is doing here with stencil
arguments.  Aside from the possibility of salvaging Todd's trick, the C++
language has no reasonable mechanism for supporting vararg parameter lists.

One of the ideas I've been considering is the use of typelists to handle
this construct.  TLists are described in Andrei Alexandrescu's "Modern C++
Design", chapter 3.

A TList is a recursively defined list template.  You can think of them as a
generalization of pair<>.  Andrei's Loki library includes a full set of
compile time TList manipulations: indexing, erasing, replacing, etc.

With the use of Tlists, Todd's function might look like something like this:

template<class T_stencil, class TypeList>
 void applyStencil(const T_stencil& stencil, TypeList& L)

To call this function you need to package the varargs:

  applyStencil (stencil, make_tlist(a1, a2, a3, a4));

Loki has enough #defines on TList to support up to 50 parameters.

I remember noticing somewhere in the Domain/Layout code situations where
seven instances of a member function where defined each with a different
vararg length, and each of the functions just passed the same parameters
through to another Pooma module, which presumably also defines seven member
functions to handle all the ranks.

There might be a case for adopting a TList mechanism to handle vararg
constructs in Pooma.  The TList itself contains all the nasty code
replication.  There would no longer be a need for Pooma components to
replicate member functions on rank.

I don't know to what extend vararg constructs are currently exposed in user
level contexts, or how much of an imposition it would be to require users to
package their varargs.

A possible compromise would be to retain the functions for 1 to 3
dimensions, and only require packaging for extended ranks.  Is having three
versions any better than having seven?

I'm tossing this construct out first, because it's the least "C++ compliant"
of all the conveniences which Domain presently offers.  Allowing integers to
act as a domain type is also a hassle, but at least it's a hassle the
language endorses.

Allan


reply via email to

[Prev in Thread] Current Thread [Next in Thread]