Brian Silverman | f27e085 | 2018-08-04 23:56:45 -0700 | [diff] [blame^] | 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)) |