array_arithmetic.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  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. BOOST_PP_LIST_FOR_EACH_PRODUCT(UNARY_ARRAY_OP, 2, (APPLICATIVE_UNARY_OPS, BUILTIN_TYPES))
  173. # /* Generates code for all binary operators and integral type pairs. */
  174. # define BINARY_ARRAY_OP(_, OLR) \
  175. BOOST_PP_IF( \
  176. IS_VALID_BINARY_OP_AND_TYPE_COMBINATION OLR, \
  177. BINARY_ARRAY_OP_CODE, BOOST_PP_TUPLE_EAT(3) \
  178. ) OLR \
  179. /**/
  180. # define BINARY_ARRAY_OP_CODE(O, L, R) \
  181. void BOOST_PP_LIST_CAT( \
  182. BOOST_PP_TUPLE_TO_LIST( \
  183. 6, (array_, OP_NAME(O), _, TYPE_ABBREVIATION(L), _, TYPE_ABBREVIATION(R)) \
  184. ) \
  185. )(const TYPE_NAME(L)* lhs_in, const TYPE_NAME(R)* rhs_in, TYPE_NAME(TYPE_OF_BINARY_OP(O, L, R))* out, unsigned n) { \
  186. do { \
  187. *out++ = *lhs_in OP_SYMBOL(O) *rhs_in; \
  188. ++lhs_in; \
  189. ++rhs_in; \
  190. } while (--n); \
  191. } \
  192. /**/
  193. BOOST_PP_LIST_FOR_EACH_PRODUCT(BINARY_ARRAY_OP, 3, (APPLICATIVE_BINARY_OPS, BUILTIN_TYPES, BUILTIN_TYPES))