Files
preprocessor/example/linear_fib.c
Vesa Karvonen b9f6fe1795 Example on using BOOST_PP_WHILE()
[SVN r12611]
2002-01-31 21:14:39 +00:00

92 lines
2.8 KiB
C

/* Copyright (C) 2002
* Housemarque Oy
* http://www.housemarque.com
*
* Permission to copy, use, modify, sell and distribute this software is
* granted provided this copyright notice appears in all copies. This
* software is provided "as is" without express or implied warranty, and
* with no claim as to its suitability for any purpose.
*
* See http://www.boost.org for most recent version.
*/
/* This example shows how BOOST_PP_WHILE() can be used for implementing
* macros.
*/
#include <boost/preprocessor/while.hpp>
#include <boost/preprocessor/arithmetic/add.hpp>
#include <boost/preprocessor/arithmetic/sub.hpp>
#include <boost/preprocessor/list/adt.hpp>
#include <boost/preprocessor/comparison/less_equal.hpp>
#include <stdio.h>
/* First consider the following C implementation of Fibonacci. */
typedef struct linear_fib_state { int a0, a1, n; } linear_fib_state;
static int linear_fib_c( linear_fib_state p )
{
return p.n;
}
static linear_fib_state linear_fib_f( linear_fib_state p )
{
linear_fib_state r = { p.a1, p.a0 + p.a1, p.n - 1 };
return r;
}
static int linear_fib( int n )
{
linear_fib_state p = { 0, 1, n };
while ( linear_fib_c(p) ) { p = linear_fib_f(p); }
return p.a0;
}
/* Then consider the following preprocessor implementation of Fibonacci. */
#define LINEAR_FIB(N)\
LINEAR_FIB_D(0,N)
/* Since the macro is implemented using BOOST_PP_WHILE, the actual
* implementation takes a depth as a parameter so that it can be called
* inside a BOOST_PP_WHILE. The above easy-to-use version simply uses 0
* as the depth and can not be called inside a BOOST_PP_WHILE.
*/
#define LINEAR_FIB_D(D,N)\
BOOST_PP_TUPLE_ELEM(3,0,BOOST_PP_WHILE##D(LINEAR_FIB_C,LINEAR_FIB_F,(0,1,N)))
/* ^^^ ^^^ ^^ ^^ ^^^^^^^
* #1 #2 #3 #3 #1
*
* #1) The state is a 3-tuple. After the iteration is finished, the first
* element of the tuple is the result.
*
* #2) The WHILE primitive is "invoked" directly. BOOST_PP_WHILE(D,...)
* can't be used because it would not be expanded by the C++ preprocessor.
*
* #3) ???_C is the condition and ???_F is the iteration macro.
*/
#define LINEAR_FIB_C(D,P)\
/* p.n */ BOOST_PP_TUPLE_ELEM(3,2,P)
#define LINEAR_FIB_F(D,P)\
(/* p.a1 */ BOOST_PP_TUPLE_ELEM(3,1,P)\
,/* p.a0+p.a1*/ BOOST_PP_ADD_D(D,BOOST_PP_TUPLE_ELEM(3,0,P),BOOST_PP_TUPLE_ELEM(3,1,P))\
/* ^^ ^ \
* BOOST_PP_ADD() uses BOOST_PP_WHILE(). Therefore we must\
* pass the recursion depth explicitly to BOOST_PP_ADD_D().\
*/\
,/* p.n - 1 */ BOOST_PP_DEC(BOOST_PP_TUPLE_ELEM(3,2,P))\
)
int main()
{
printf("linear_fib(10) = %d\n", linear_fib(10));
printf("LINEAR_FIB(10) = %d\n", LINEAR_FIB(10));
return 0;
}