Boost logo

Boost Users :

From: Jeff Flinn (midnight2silverlake_at_[hidden])
Date: 2002-12-10 07:53:46


Paul,

Awesome! Thanks for the extensive description and all your efforts. It seems
like I run into this situation quite often. I'll be studying up on all of
these primitives.

Thanks again, Jeff

----- Original Message -----
From: "Paul Mensonides" <yg-boost-users_at_[hidden]>
Newsgroups: gmane.comp.lib.boost.user
Sent: Monday, December 09, 2002 6:09 PM
Subject: Re: Boost Preprocessor - Nested repeat?

> "Jeff Flinn" <midnight2silverlake_at_[hidden]> wrote in message
> news:000c01c29f84$ae37b0e0$ea02a8c0_at_adi.com...
> > ----- Original Message -----
> > From: "Paul Mensonides" <yg-boost-users_at_[hidden]>
> >
> > > "midnight2silverlake" <midnight2silverlake_at_[hidden]> wrote in message
> > > news:asq7h1+r192_at_eGroups.com...
> > > > I have what looks like a perfect application for Boost/Preprocessor.
> > > > I have 192 entries in a Factory Map a portion of which are show
> > > > below. I'd like to generate the permutations of the three macro
> > > > inputs, but can't figure out where to start. Any help would be
> > > > appreciated.
> > > >
> > > > #define MAP_ENTRY_MCR( aLang, aType, aAcc ) \
> > > > \
> > > > mMap[ CKey( aLang, aType, aAcc ) ] \
> > > > = CVarX< aLang, aType, aAcc >::Make;
> > > >
> > > > MAP_ENTRY_MCR( DCTlanguageC, DCT_DOUBLE , DCT_NONE );
> > > > MAP_ENTRY_MCR( DCTlanguageC, DCT_DOUBLE , DCT_INIT );
> > > > MAP_ENTRY_MCR( DCTlanguageC, DCT_DOUBLE , DCT_ANYTIME );
> > > >
> > > > MAP_ENTRY_MCR( DCTlanguageC, DCT_FLOAT , DCT_NONE );
> > > > ...
> > > >
> > > > Thanks, Jeff Flinn
> > >
> > > Hi Jeff,
> > >
> > > I want to make certain that I'm clear about what you're trying to do.
> You
> > > have 192 consecutive "MAP_ENTRY_MCR( ... )" with different permutions
> each
> > > time, right? How many different elements for each "field" do you
have?
> > > (i.e. how many DCT_DOUBLE, DCT_FLOAT, etc. and how many DCT_NONE,
> > DCT_INIT,
> > > etc.)
> >
> > aLang(4) => DCTlanguageAda, DCTlanguageAdsim, DCTlanguageC
> > , DCTlanguageFortran
> > aType(8)=> DCT_DOUBLE, DCT_FLOAT
> > , DCT_INT_16, DCT_INT_32, DCT_INT_8
> > , DCT_UINT_16, DCT_UINT_32, DCT_UINT_8
> > aAcc(3)=> DCT_INIT, DCT_ANYTIME, DCT_NONE
> >
> > This accounts for 96 MAP_ENTRY_MCR's. There will actually be a 4th macro
> > argument:
> >
> > aDim(2)=> DCT_Vector, DCT_Scalar
> >
> > Which accounts for the 192 entries.
>
> Okay, so what we have here is a full-scale permutation of these four
groups
> of values. It doesn't matter if they are sequential or not, because we'll
> deal with them by name rather than by value. (To address the topic of
this
> thread, you _could_ use BOOST_PP_REPEAT, but only for three dimensions,
and
> it wouldn't be a good idea for other reasons.)
>
> Generally speaking, there are three good options. Only one of them is a
> good option if you plan to use an EDG front-end (such as Comeau or Intel)
> because the sheer size of such a cartesian product will take a while to
> generate.
>
> option #1: lists --------------->
>
> #include <boost/preprocessor/list/for_each_product.hpp>
>
> #define A_LANG \
> (DCTlanguageAda, (DCTlanguageAdsim, (DCTlanguageC, \
> (DCTlanguageFortran, BOOST_PP_NIL)))) \
> /**/
>
> #define A_TYPE \
> (DCT_DOUBLE, (DCT_FLOAT, (DCT_INT_16, (DCT_INT_32, \
> (DCT_INT_8, (DCT_UINT_16, (DCT_UINT_32, \
> (DCT_UINT_8, BOOST_PP_NIL)))))))) \
> /**/
>
> #define A_ACC \
> (DCT_INIT, (DCT_ANYTIME, (DCT_NONE, BOOST_PP_NIL))) \
> /**/
>
> #define A_DIM (DCT_Vector, (DCT_Scalar, BOOST_PP_NIL))
>
> #define PRODUCT(r, product) MAP_ENTRY_MCR product
>
> #define MAP_ENTRY_MCR( aLang, aType, aAcc, aDim ) \
> mMap[ CKey( aLang, aType, aAcc ) ] \
> = CVarX< aLang, aType, aAcc >::Make; \
> /* aDim? */
>
> BOOST_PP_LIST_FOR_EACH_PRODUCT(
> PRODUCT, 4, ( A_LANG, A_TYPE, A_ACC, A_DIM )
> )
>
> #undef A_LANG
> #undef A_TYPE
> #undef A_ACC
> #undef A_DIM
> #undef PRODUCT
> #undef MAP_ENTRY_MCR
>
> -------------------------
>
> The second option requires the latest CVS sources of the PP Lib (i.e.
> post-1.29 release). It is a variant of the above, but with a preprocessor
> data type called a "sequence" that is a little simpler and more efficient
> that a "list."
>
> option #2: sequences --------------->
>
> #include <boost/preprocessor/seq/elem.hpp>
> #include <boost/preprocessor/seq/for_each_product.hpp>
>
> #define A_LANG \
> (DCTlanguageAda)(DCTlanguageAdsim) \
> (DCTlanguageC)(DCTlanguageFortran) \
> /**/
>
> #define A_TYPE \
> (DCT_DOUBLE)(DCT_FLOAT)(DCT_INT_16)(DCT_INT_32) \
> (DCT_INT_8)(DCT_UINT_16)(DCT_UINT_32)(DCT_UINT_8) \
> /**/
>
> #define A_ACC \
> (DCT_INIT)(DCT_ANYTIME)(DCT_NONE) \
> /**/
>
> #define A_DIM \
> (DCT_Vector)(DCT_Scalar) \
> /**/
>
> #define PRODUCT(r, seq) \
> MAP_ENTRY_MCR( \
> BOOST_PP_SEQ_ELEM(0, seq), BOOST_PP_SEQ_ELEM(1, seq), \
> BOOST_PP_SEQ_ELEM(2, seq), BOOST_PP_SEQ_ELEM(3, seq) \
> ) \
> /**/
>
> #define MAP_ENTRY_MCR( aLang, aType, aAcc, aDim ) \
> mMap[ CKey( aLang, aType, aAcc ) ] \
> = CVarX< aLang, aType, aAcc >::Make; \
> /* aDim? */
>
> BOOST_PP_SEQ_FOR_EACH_PRODUCT(
> PRODUCT,
> (A_LANG)(A_TYPE)(A_ACC)(A_DIM)
> )
>
> #undef A_LANG
> #undef A_TYPE
> #undef A_ACC
> #undef A_DIM
> #undef PRODUCT
> #undef MAP_ENTRY_MCR
>
> -------------------------
>
> Both of the two options above use library primitives that are built for
> cartesian products such as this. However, they don't scale to this size
> well on slow preprocessors (e.g. EDG and maybe GCC). Luckily, we have a
> third alternative. However, this alternative is much more "invasive." It
> is a technique which I call "file iteration." In effect, it iterates over
a
> file (or portion of a file) repeatedly with a different macro state each
> iteration. Furthermore, file iteration is supported up to five
> dimensions--we only have four here. I'll presume this stuff is in a
header
> file called "map_entry_mcr.h". This psuedo-code roughly describes the
> implementation:
>
> for (int i = 0; i < aLang.size(); ++i) {
> for (int j = 0; j < aType.size(); ++j) {
> for (int k = 0; k < aAcc.size(); ++k) {
> for (int l = 0; l < aDim.size(); ++l) {
> MAP_ENTRY_MCR(i, j, k, l);
> }
> }
> }
> }
>
> option #3: file iteration --------------->
>
> #if !BOOST_PP_IS_ITERATING
>
> #ifndef MAP_ENTRY_MCR_H // normal include guard
> #define MAP_ENTRY_MCR_H
>
> #include <boost/preprocessor/array/elem.hpp>
> #include <boost/preprocessor/array/size.hpp>
> #include <boost/preprocessor/iteration/iterate.hpp>
>
> // ----- normal file contents go here ----- //
>
> #define A_LANG \
> (4, (DCTlanguageAda, DCTlanguageAdsim, \
> DCTlanguageC, DCTlanguageFortran))
>
> #define A_TYPE \
> (8, ( \
> DCT_DOUBLE, DCT_FLOAT, DCT_INT_16, DCT_INT_32, \
> DCT_INT_8, DCT_UINT_16, DCT_UINT_32, DCT_UINT_8 \
> ))
>
> #define A_ACC \
> (3, (DCT_INIT, DCT_ANYTIME, DCT_NONE))
>
> #define A_DIM \
> (2, (DCT_Vector, DCT_Scalar))
>
> #define ACCESS(array, frame) \
> BOOST_PP_ARRAY_ELEM( \
> BOOST_PP_FRAME_ITERATION(frame), \
> array \
> ) \
> /**/
>
> #define aLang ACCESS(A_LANG, 1)
> #define aType ACCESS(A_TYPE, 2)
> #define aAcc ACCESS(A_ACC, 3)
> #define aDim ACCESS(A_DIM, 4)
>
> // iterate over elements in "A_LANG"
> #define BOOST_PP_ITERATION_PARAMS_1 \
> (3, (0, BOOST_PP_ARRAY_SIZE(A_LANG) - 1, "map_entry_mcr.h"))
> #include BOOST_PP_ITERATE()
>
> #undef A_LANG
> #undef A_TYPE
> #undef A_ACC
> #undef A_DIM
> #undef ACCESS
>
> #undef aLang
> #undef aType
> #undef aAcc
> #undef aDim
>
> // ----- other normal file contents go here ----- //
>
> #endif // EOF
>
> #elif BOOST_PP_ITERATION_DEPTH() == 1
>
> // iterate over elements in "A_TYPE"
> #define BOOST_PP_ITERATION_PARAMS_2 \
> (3, (0, BOOST_PP_ARRAY_SIZE(A_TYPE) - 1, "map_entry_mcr.h"))
> #include BOOST_PP_ITERATE()
>
> #elif BOOST_PP_ITERATION_DEPTH() == 2
>
> // iterate over elements in "A_ACC"
> #define BOOST_PP_ITERATION_PARAMS_3 \
> (3, (0, BOOST_PP_ARRAY_SIZE(A_ACC) - 1, "map_entry_mcr.h"))
> #include BOOST_PP_ITERATE()
>
> #elif BOOST_PP_ITERATION_DEPTH() == 3
>
> // iterate over elements in "A_DIM"
> #define BOOST_PP_ITERATION_PARAMS_4 \
> (3, (0, BOOST_PP_ARRAY_SIZE(A_DIM) - 1, "map_entry_mcr.h"))
> #include BOOST_PP_ITERATE()
>
> #else
>
> mMap[ CKey( aLang, aType, aAcc ) ]
> = CVarX< aLang, aType, aAcc >::Make;
>
> ? aDim
>
> #endif
>
> -------------------------
>
> As you can see, this method is much more elaborate. The mechanism is
> primarily intended for repeating large swathes of code rather than
cartesian
> products. Nevertheless, it works and is fairly fast--even on EDG. Make
> sure that you understand what is happening if you use this last example
> (maybe read the docs on file-iteration). Also, note that you can put all
> this iteration stuff in a separate file and merely include it where you
> want. The file iteration mechanism is a powerhouse, and this usage barely
> touches on its potential (which is partially why the implementation above
is
> as obtuse as it is).
>
> The strengths of option #1 and option #2 is the locality of code. Option
#3
> is a lot more involved. The weaknesses of option #1 and option #2 is that
> it is really slow on EDG preprocessors and that all the code gets expanded
> on a single line and is completely undebuggable. Option #3 excels in this
> area--though in this case, the debuggability aspect is negligible for such
a
> small snippet of source code.
>
> In any case, I urge you to read the documentation on each library
primitive
> used and also the topic on file iteration. If you find anything unclear,
> then you can tell me, and I can improve the docs.
>
> > The DCT_ constants are a combination of enums and integer defines. aLang
> and
> > aDim are enum entries, with sequential values starting with 1. aType
and
> > aAcc are integer defines. aType is non-sequential, aAcc is sequential
> > starting with 1. It is possible for any of these to become
non-sequential
> in
> >
> > the future.
> >
> > >
> > > There are several ways to do this, so let me know if I'm clear on what
> > > you're doing, and I'll help you.
> > >
> > > Paul Mensonides
> >
> > Thanks for the help Paul
> >
> > Jeff Flinn
> > Applied Dynamics, International
>
> Regards,
> Paul Mensonides
>
>
>
>
>
>
>
>
> Info: <http://www.boost.org>
> Wiki: <http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl>
> Unsubscribe: <mailto:boost-users-unsubscribe_at_[hidden]>
>
>
> Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
>
>
>


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net