Boost GIL


apply_operation_base.hpp
Go to the documentation of this file.
1 /*
2  Copyright 2005-2007 Adobe Systems Incorporated
3 
4  Use, modification and distribution are subject to the Boost Software License,
5  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6  http://www.boost.org/LICENSE_1_0.txt).
7 
8  See http://opensource.adobe.com/gil for most recent version including documentation.
9 */
10 
11 /*************************************************************************************************/
12 
13 #ifndef GIL_APPLY_OPERATION_BASE_HPP
14 #define GIL_APPLY_OPERATION_BASE_HPP
15 
16 #include "../../gil_config.hpp"
17 #include "../../utilities.hpp"
18 #include <boost/mpl/begin.hpp>
19 #include <boost/mpl/next.hpp>
20 #include <boost/mpl/deref.hpp>
21 #include <boost/mpl/size.hpp>
22 #include <boost/preprocessor/repeat.hpp>
23 
33 
34 namespace boost { namespace gil {
35 
36 /*
37 GENERATE_APPLY_FWD_OPS generates for every N functions that look like this (for N==2):
38 
39  template <> struct apply_operation_fwd_fn<3> {
40  template <typename Types, typename Bits, typename UnaryOp>
41  typename UnaryOp::result_type apply(Bits& bits, std::size_t index, UnaryOp op) const {
42  typedef typename mpl::begin<Types>::type T0;
43  typedef typename mpl::next<T0>::type T1;
44  typedef typename mpl::next<T1>::type T2;
45  switch (index) {
46  case 0: return op(reinterpret_cast<typename mpl::deref<T0>::type&>(bits));
47  case 1: return op(reinterpret_cast<typename mpl::deref<T1>::type&>(bits));
48  case 2: return op(reinterpret_cast<typename mpl::deref<T2>::type&>(bits));
49  }
50  throw;
51  }
52 
53  template <typename Types, typename Bits, typename UnaryOp>
54  typename UnaryOp::result_type applyc(const Bits& bits, std::size_t index, UnaryOp op) const {
55  typedef typename mpl::begin<Types>::type T0;
56  typedef typename mpl::next<T0>::type T1;
57  typedef typename mpl::next<T1>::type T2;
58  switch (index) {
59  case 0: return op(reinterpret_cast<const typename mpl::deref<T0>::type&>(bits));
60  case 1: return op(reinterpret_cast<const typename mpl::deref<T1>::type&>(bits));
61  case 2: return op(reinterpret_cast<const typename mpl::deref<T2>::type&>(bits));
62  }
63  throw;
64  }
65  };
66 */
67 
68 #define GIL_FWD_TYPEDEFS(z, N, text) T##N; typedef typename mpl::next<T##N>::type
69 #define GIL_FWD_CASE(z, N, SUM) case N: return op(*gil_reinterpret_cast<typename mpl::deref<T##N>::type*>(&bits));
70 #define GIL_FWD_CONST_CASE(z, N, SUM) case N: return op(*gil_reinterpret_cast_c<const typename mpl::deref<T##N>::type*>(&bits));
71 
72 #define GIL_FWD_CASE_WITH_INFO(z, N, SUM) case N: return op(*gil_reinterpret_cast<typename mpl::deref<T##N>::type*>(&bits), info);
73 #define GIL_FWD_CONST_CASE_WITH_INFO(z, N, SUM) case N: return op(*gil_reinterpret_cast_c<const typename mpl::deref<T##N>::type*>(&bits), info);
74 
75 #define GIL_APPLY_FWD_OP(z, N, text) \
76  template <> struct apply_operation_fwd_fn<BOOST_PP_ADD(N,1)> { \
77  template <typename Types, typename Bits, typename UnaryOp> \
78  typename UnaryOp::result_type apply(Bits& bits, std::size_t index, UnaryOp op) const { \
79  typedef typename mpl::begin<Types>::type \
80  BOOST_PP_REPEAT(N, GIL_FWD_TYPEDEFS, BOOST_PP_EMPTY) \
81  T##N; \
82  switch (index) { \
83  BOOST_PP_REPEAT(BOOST_PP_ADD(N,1), GIL_FWD_CASE, BOOST_PP_EMPTY) \
84  } \
85  throw; \
86  } \
87  template <typename Types, typename Bits, typename UnaryOp> \
88  typename UnaryOp::result_type applyc(const Bits& bits, std::size_t index, UnaryOp op) const { \
89  typedef typename mpl::begin<Types>::type \
90  BOOST_PP_REPEAT(N, GIL_FWD_TYPEDEFS, BOOST_PP_EMPTY) \
91  T##N; \
92  switch (index) { \
93  BOOST_PP_REPEAT(BOOST_PP_ADD(N,1), GIL_FWD_CONST_CASE,BOOST_PP_EMPTY) \
94  } \
95  throw; \
96  } \
97  template <typename Types, typename Info, typename Bits, typename UnaryOp> \
98  typename UnaryOp::result_type apply(Bits& bits, std::size_t index, const Info& info, UnaryOp op) const { \
99  typedef typename mpl::begin<Types>::type \
100  BOOST_PP_REPEAT(N, GIL_FWD_TYPEDEFS, BOOST_PP_EMPTY) \
101  T##N; \
102  switch (index) { \
103  BOOST_PP_REPEAT(BOOST_PP_ADD(N,1), GIL_FWD_CASE_WITH_INFO, BOOST_PP_EMPTY) \
104  } \
105  throw; \
106  } \
107  template <typename Types, typename Bits, typename Info, typename UnaryOp> \
108  typename UnaryOp::result_type applyc(const Bits& bits, std::size_t index, const Info& info, UnaryOp op) const { \
109  typedef typename mpl::begin<Types>::type \
110  BOOST_PP_REPEAT(N, GIL_FWD_TYPEDEFS, BOOST_PP_EMPTY) \
111  T##N; \
112  switch (index) { \
113  BOOST_PP_REPEAT(BOOST_PP_ADD(N,1), GIL_FWD_CONST_CASE_WITH_INFO,BOOST_PP_EMPTY) \
114  } \
115  throw; \
116  } \
117  };
118 
119 #define GIL_GENERATE_APPLY_FWD_OPS(N) BOOST_PP_REPEAT(N, GIL_APPLY_FWD_OP, BOOST_PP_EMPTY)
120 
121 namespace detail {
122 template <std::size_t N> struct apply_operation_fwd_fn {};
123 
124 // Create specializations of apply_operation_fn for each N 0..100
125 GIL_GENERATE_APPLY_FWD_OPS(99)
126 } // namespace detail
127 
128 // unary application
129 template <typename Types, typename Bits, typename Op>
130 typename Op::result_type BOOST_FORCEINLINE apply_operation_basec(const Bits& bits, std::size_t index, Op op) {
131  return detail::apply_operation_fwd_fn<mpl::size<Types>::value>().template applyc<Types>(bits,index,op);
132 }
133 
134 // unary application
135 template <typename Types, typename Bits, typename Op>
136 typename Op::result_type BOOST_FORCEINLINE apply_operation_base( Bits& bits, std::size_t index, Op op) {
137  return detail::apply_operation_fwd_fn<mpl::size<Types>::value>().template apply<Types>(bits,index,op);
138 }
139 
140 namespace detail {
141  template <typename T2, typename Op>
142  struct reduce_bind1 {
143  const T2& _t2;
144  Op& _op;
145 
146  typedef typename Op::result_type result_type;
147 
148  reduce_bind1(const T2& t2, Op& op) : _t2(t2), _op(op) {}
149 
150  template <typename T1> BOOST_FORCEINLINE result_type operator()(const T1& t1) { return _op(t1, _t2); }
151  };
152 
153  template <typename Types1, typename Bits1, typename Op>
154  struct reduce_bind2 {
155  const Bits1& _bits1;
156  std::size_t _index1;
157  Op& _op;
158 
159  typedef typename Op::result_type result_type;
160 
161  reduce_bind2(const Bits1& bits1, std::size_t index1, Op& op) : _bits1(bits1), _index1(index1), _op(op) {}
162 
163  template <typename T2> BOOST_FORCEINLINE result_type operator()(const T2& t2) {
164  return apply_operation_basec<Types1>(_bits1, _index1, reduce_bind1<T2,Op>(t2, _op));
165  }
166  };
167 } // namespace detail
168 
169 // Binary application by applying on each dimension separately
170 template <typename Types1, typename Types2, typename Bits1, typename Bits2, typename Op>
171 static typename Op::result_type BOOST_FORCEINLINE apply_operation_base(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) {
172  return apply_operation_basec<Types2>(bits2,index2,detail::reduce_bind2<Types1,Bits1,Op>(bits1,index1,op));
173 }
174 
175 #undef GIL_FWD_TYPEDEFS
176 #undef GIL_FWD_CASE
177 #undef GIL_FWD_CONST_CASE
178 #undef GIL_APPLY_FWD_OP
179 #undef GIL_GENERATE_APPLY_FWD_OPS
180 #undef BHS
181 
182 } } // namespace boost::gil
183 
184 
185 #endif