blob: 2778003f9742acbe4a8d2646f145d17819a603a0 [file] [log] [blame]
Brian Silvermanf27e0852018-08-04 23:56:45 -07001# /* Copyright (C) 2002
2# * Housemarque Oy
3# * http://www.housemarque.com
4# *
5# * Distributed under the Boost Software License, Version 1.0. (See
6# * accompanying file LICENSE_1_0.txt or copy at
7# * http://www.boost.org/LICENSE_1_0.txt)
8# */
9#
10# /* Revised by Paul Mensonides (2002) */
11#
12# /* See http://www.boost.org for most recent version. */
13#
14# /* This example shows how BOOST_PP_WHILE() can be used for implementing macros. */
15#
16# include <stdio.h>
17#
18# include <boost/preprocessor/arithmetic/add.hpp>
19# include <boost/preprocessor/arithmetic/sub.hpp>
20# include <boost/preprocessor/comparison/less_equal.hpp>
21# include <boost/preprocessor/control/while.hpp>
22# include <boost/preprocessor/list/adt.hpp>
23# include <boost/preprocessor/tuple/elem.hpp>
24#
25# /* First consider the following C implementation of Fibonacci. */
26
27typedef struct linear_fib_state {
28 int a0, a1, n;
29} linear_fib_state;
30
31static int linear_fib_c(linear_fib_state p) {
32 return p.n;
33}
34
35static linear_fib_state linear_fib_f(linear_fib_state p) {
36 linear_fib_state r = { p.a1, p.a0 + p.a1, p.n - 1 };
37 return r;
38}
39
40static int linear_fib(int n) {
41 linear_fib_state p = { 0, 1, n };
42 while (linear_fib_c(p)) {
43 p = linear_fib_f(p);
44 }
45 return p.a0;
46}
47
48# /* Then consider the following preprocessor implementation of Fibonacci. */
49#
50# define LINEAR_FIB(n) LINEAR_FIB_D(1, n)
51# /* Since the macro is implemented using BOOST_PP_WHILE, the actual
52# * implementation takes a depth as a parameters so that it can be called
53# * inside a BOOST_PP_WHILE. The above easy-to-use version simply uses 1
54# * as the depth and cannot be called inside a BOOST_PP_WHILE.
55# */
56#
57# define LINEAR_FIB_D(d, n) \
58 BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_WHILE_ ## d(LINEAR_FIB_C, LINEAR_FIB_F, (0, 1, n)))
59# /* ^^^^ ^^^^^ ^^ ^^ ^^^^^^^
60# * #1 #2 #3 #3 #4
61# *
62# * 1) The state is a 3-element tuple. After the iteration is finished, the first
63# * element of the tuple is the result.
64# *
65# * 2) The WHILE primitive is "invoked" directly. BOOST_PP_WHILE(D, ...)
66# * can't be used because it would not be expanded by the preprocessor.
67# *
68# * 3) ???_C is the condition and ???_F is the iteration macro.
69# */
70#
71# define LINEAR_FIB_C(d, p) \
72 /* p.n */ BOOST_PP_TUPLE_ELEM(3, 2, p) \
73 /**/
74#
75# define LINEAR_FIB_F(d, p) \
76 ( \
77 /* p.a1 */ BOOST_PP_TUPLE_ELEM(3, 1, p), \
78 /* p.a0 + p.a1 */ BOOST_PP_ADD_D(d, BOOST_PP_TUPLE_ELEM(3, 0, p), BOOST_PP_TUPLE_ELEM(3, 1, p)), \
79 /* ^^ ^ \
80 * BOOST_PP_ADD() uses BOOST_PP_WHILE(). Therefore we \
81 * pass the recursion depth explicitly to BOOST_PP_ADD_D(). \
82 */ \
83 /* p.n - 1 */ BOOST_PP_DEC(BOOST_PP_TUPLE_ELEM(3, 2, p)) \
84 ) \
85 /**/
86
87int main() {
88 printf("linear_fib(10) = %d\n", linear_fib(10));
89 printf("LINEAR_FIB(10) = %d\n", LINEAR_FIB(10));
90 return 0;
91}