]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
24 | //////////////////////////////////////////////////////////////////////////////////////// | |
25 | /// \file | |
26 | /// \brief Given an object with run-time specified type (denoted as an array of Bits, dynamic index, and a static set of Types) and a generic operation, | |
27 | /// casts the object to its appropriate type and applies the operation | |
28 | /// \author Lubomir Bourdev and Hailin Jin \n | |
29 | /// Adobe Systems Incorporated | |
30 | /// \date 2005-2007 \n Last updated on November 6, 2007 | |
31 | /// | |
32 | //////////////////////////////////////////////////////////////////////////////////////// | |
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 GIL_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 GIL_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> GIL_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> GIL_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 GIL_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 |