1 # /* 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 implements over 2200 functions for 1-dimensional arithmetic 15 # * array manipulation in C. The idea is to use preprocessor data structures, 16 # * lists, and tuples for storing metainformation to be used for generating 17 # * the actual C code. 18 # * 19 # * Who needs templates anyway? :) 20 # * 21 # * Compile with any C compiler with a standards conforming preprocessor. 22 # */ 23 # 24 # include <boost/preprocessor/comparison/less.hpp> 25 # include <boost/preprocessor/control/if.hpp> 26 # include <boost/preprocessor/list/at.hpp> 27 # include <boost/preprocessor/list/cat.hpp> 28 # include <boost/preprocessor/list/for_each_product.hpp> 29 # include <boost/preprocessor/logical/or.hpp> 30 # include <boost/preprocessor/tuple/to_list.hpp> 31 # include <boost/preprocessor/tuple/eat.hpp> 32 # 33 # /* Information about C operators */ 34 # 35 # /* Accessors for the operator datatype. */ 36 # define OP_SYMBOL(O) BOOST_PP_TUPLE_ELEM(5, 0, O) 37 # define OP_NAME(O) BOOST_PP_TUPLE_ELEM(5, 1, O) 38 # define OP_IS_FLOATING(O) BOOST_PP_TUPLE_ELEM(5, 2, O) 39 # define OP_IS_LOGICAL(O) BOOST_PP_TUPLE_ELEM(5, 3, O) 40 # define OP_IS_SHIFT(O) BOOST_PP_TUPLE_ELEM(5, 4, O) 41 # 42 # /* List of applicative unary operators. */ 43 # define APPLICATIVE_UNARY_OPS \ 44 BOOST_PP_TUPLE_TO_LIST( \ 45 3, \ 46 ( \ 47 ( ! , logical_not, 1, 1, 0), \ 48 ( ~ , bitwise_not, 0, 0, 0), \ 49 ( - , neg, 1, 0, 0) \ 50 ) \ 51 ) \ 52 /**/ 53 # 54 # /* List of applicative binary operators. */ 55 # define APPLICATIVE_BINARY_OPS \ 56 BOOST_PP_TUPLE_TO_LIST( \ 57 18, \ 58 ( \ 59 ( * , mul ,1 ,0 ,0), \ 60 ( / , div ,1 ,0 ,0), \ 61 ( % , mod ,0 ,0 ,0), \ 62 ( + , add ,1 ,0 ,0), \ 63 ( - , sub ,1 ,0 ,0), \ 64 ( << , shift_left ,0 ,0 ,1), \ 65 ( >> , shift_right ,0 ,0 ,1), \ 66 ( < , less ,1 ,1 ,0), \ 67 ( <= , less_equal ,1 ,1 ,0), \ 68 ( >= , greater_equal ,1 ,1 ,0), \ 69 ( > , greater ,1 ,1 ,0), \ 70 ( == , equal ,1 ,1 ,0), \ 71 ( != , not_equal ,1 ,1 ,0), \ 72 ( & , bitwise_and ,0 ,0 ,0), \ 73 ( | , bitwise_or ,0 ,0 ,0), \ 74 ( ^ , bitwise_xor ,0 ,0 ,0), \ 75 ( && , logical_and ,1 ,1 ,0), \ 76 ( || , logical_or ,1 ,1 ,0) \ 77 ) \ 78 ) \ 79 /**/ 80 # 81 # /* Information about C built-in types. */ 82 # 83 # /* Accessors for the type datatype. */ 84 # define TYPE_NAME(T) BOOST_PP_TUPLE_ELEM(4, 0, T) 85 # define TYPE_ABBREVIATION(T) BOOST_PP_TUPLE_ELEM(4, 1, T) 86 # define TYPE_IS_FLOATING(T) BOOST_PP_TUPLE_ELEM(4, 2, T) 87 # define TYPE_RANK(T) BOOST_PP_TUPLE_ELEM(4, 3, T) 88 # 89 # /* List of C built-in types. */ 90 # define BUILTIN_TYPES \ 91 BOOST_PP_TUPLE_TO_LIST( \ 92 12, \ 93 ( \ 94 ( signed char ,sc, 0, 1), \ 95 ( char ,ch, 0, 1), \ 96 ( unsigned char ,uc, 0, 1), \ 97 ( short ,ss, 0, 2), \ 98 ( unsigned short ,us, 0, 2), \ 99 TYPE_INT, \ 100 ( unsigned ,ui, 0, 4), \ 101 ( long ,sl, 0, 5), \ 102 ( unsigned long ,ul, 0, 6), \ 103 ( float ,fl, 1, 7), \ 104 ( double ,db, 1, 8), \ 105 ( long double ,ld, 1, 9) \ 106 ) \ 107 ) \ 108 /**/ 109 # 110 # /* Type int is needed in some type computations. */ 111 # define TYPE_INT (int, si, 0, 3) 112 # 113 # /* Type computation macros. */ 114 # define TYPE_OF_INTEGER_PROMOTION(T) \ 115 BOOST_PP_IF( \ 116 BOOST_PP_LESS(TYPE_RANK(T), TYPE_RANK(TYPE_INT)), \ 117 TYPE_INT, T \ 118 ) \ 119 /**/ 120 # define TYPE_OF_USUAL_ARITHMETIC_CONVERSION(L, R) \ 121 TYPE_OF_INTEGER_PROMOTION( \ 122 BOOST_PP_IF( \ 123 BOOST_PP_LESS(TYPE_RANK(L), TYPE_RANK(R)), \ 124 R, L \ 125 ) \ 126 ) \ 127 /**/ 128 # define TYPE_OF_UNARY_OP(O, T) \ 129 BOOST_PP_IF( \ 130 OP_IS_LOGICAL(O), \ 131 TYPE_INT, TYPE_OF_INTEGER_PROMOTION(T) \ 132 ) \ 133 /**/ 134 # define TYPE_OF_BINARY_OP(O, L, R) \ 135 BOOST_PP_IF( \ 136 OP_IS_LOGICAL(O), TYPE_INT, \ 137 BOOST_PP_IF( \ 138 OP_IS_SHIFT(O), \ 139 TYPE_OF_INTEGER_PROMOTION(L), \ 140 TYPE_OF_USUAL_ARITHMETIC_CONVERSION(L,R) \ 141 ) \ 142 ) \ 143 /**/ 144 # define IS_VALID_UNARY_OP_AND_TYPE_COMBINATION(O, T) \ 145 BOOST_PP_IF( \ 146 TYPE_IS_FLOATING(T), \ 147 OP_IS_FLOATING(O), 1 \ 148 ) \ 149 /**/ 150 # define IS_VALID_BINARY_OP_AND_TYPE_COMBINATION(O, L, R) \ 151 BOOST_PP_IF( \ 152 BOOST_PP_OR(TYPE_IS_FLOATING(L), TYPE_IS_FLOATING(R)), \ 153 OP_IS_FLOATING(O), 1 \ 154 ) \ 155 /**/ 156 # 157 # /* Generates code for all unary operators and integral types. */ 158 # define UNARY_ARRAY_OP(_, OT) \ 159 BOOST_PP_IF( \ 160 IS_VALID_UNARY_OP_AND_TYPE_COMBINATION OT, \ 161 UNARY_ARRAY_OP_CODE, BOOST_PP_TUPLE_EAT(2) \ 162 ) OT \ 163 /**/ 164 # define UNARY_ARRAY_OP_CODE(O, T) \ 165 void BOOST_PP_LIST_CAT(BOOST_PP_TUPLE_TO_LIST(4, (array_, OP_NAME(O), _, TYPE_ABBREVIATION(T)))) \ 166 (const TYPE_NAME(T)* in, TYPE_NAME(TYPE_OF_UNARY_OP(O, T))* out, unsigned n) { \ 167 do { \ 168 *out++ = OP_SYMBOL(O) *in++; \ 169 } while (--n); \ 170 } \ 171 /**/ 172 173 BOOST_PP_LIST_FOR_EACH_PRODUCT(UNARY_ARRAY_OP, 2, (APPLICATIVE_UNARY_OPS, BUILTIN_TYPES)) 174 175 # /* Generates code for all binary operators and integral type pairs. */ 176 # define BINARY_ARRAY_OP(_, OLR) \ 177 BOOST_PP_IF( \ 178 IS_VALID_BINARY_OP_AND_TYPE_COMBINATION OLR, \ 179 BINARY_ARRAY_OP_CODE, BOOST_PP_TUPLE_EAT(3) \ 180 ) OLR \ 181 /**/ 182 # define BINARY_ARRAY_OP_CODE(O, L, R) \ 183 void BOOST_PP_LIST_CAT( \ 184 BOOST_PP_TUPLE_TO_LIST( \ 185 6, (array_, OP_NAME(O), _, TYPE_ABBREVIATION(L), _, TYPE_ABBREVIATION(R)) \ 186 ) \ 187 )(const TYPE_NAME(L)* lhs_in, const TYPE_NAME(R)* rhs_in, TYPE_NAME(TYPE_OF_BINARY_OP(O, L, R))* out, unsigned n) { \ 188 do { \ 189 *out++ = *lhs_in OP_SYMBOL(O) *rhs_in; \ 190 ++lhs_in; \ 191 ++rhs_in; \ 192 } while (--n); \ 193 } \ 194 /**/ 195 196 BOOST_PP_LIST_FOR_EACH_PRODUCT(BINARY_ARRAY_OP, 3, (APPLICATIVE_BINARY_OPS, BUILTIN_TYPES, BUILTIN_TYPES)) 197