Boost GIL


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