Modules | Alphabetical List | Class List | Directories | File List | GIL Home Page # apply_operation_base.hpp Go to the documentation of this file.
    00001 /*
    00002     Copyright 2005-2007 Adobe Systems Incorporated
    00003
    00004     Use, modification and distribution are subject to the Boost Software License,
    00005     Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
    00006     http://www.boost.org/LICENSE_1_0.txt).
    00007
    00008     See http://opensource.adobe.com/gil for most recent version including documentation.
    00009 */
    00010
    00011 /*************************************************************************************************/
    00012
    00013 #ifndef GIL_APPLY_OPERATION_BASE_HPP
    00014 #define GIL_APPLY_OPERATION_BASE_HPP
    00015
    00016 #include "../../gil_config.hpp"
    00017 #include "../../utilities.hpp"
    00018 #include <boost/mpl/begin.hpp>
    00019 #include <boost/mpl/next.hpp>
    00020 #include <boost/mpl/deref.hpp>
    00021 #include <boost/mpl/size.hpp>
    00022 #include <boost/preprocessor/repeat.hpp>
    00023
    00033
    00034 namespace boost { namespace gil {
    00035
    00036 /*
    00037 GENERATE_APPLY_FWD_OPS generates for every N functions that look like this (for N==2):
    00038
    00039     template <> struct apply_operation_fwd_fn<3> {
    00040         template <typename Types, typename Bits, typename UnaryOp>
    00041         typename UnaryOp::result_type apply(Bits& bits, std::size_t index, UnaryOp op) const {
    00042             typedef typename mpl::begin<Types>::type T0;
    00043             typedef typename mpl::next<T0>::type T1;
    00044             typedef typename mpl::next<T1>::type T2;
    00045             switch (index) {
    00046                 case 0: return op(reinterpret_cast<typename mpl::deref<T0>::type&>(bits));
    00047                 case 1: return op(reinterpret_cast<typename mpl::deref<T1>::type&>(bits));
    00048                 case 2: return op(reinterpret_cast<typename mpl::deref<T2>::type&>(bits));
    00049             }
    00050             throw;
    00051         }
    00052
    00053         template <typename Types, typename Bits, typename UnaryOp>
    00054         typename UnaryOp::result_type applyc(const Bits& bits, std::size_t index, UnaryOp op) const {
    00055             typedef typename mpl::begin<Types>::type T0;
    00056             typedef typename mpl::next<T0>::type T1;
    00057             typedef typename mpl::next<T1>::type T2;
    00058             switch (index) {
    00059                 case 0: return op(reinterpret_cast<const typename mpl::deref<T0>::type&>(bits));
    00060                 case 1: return op(reinterpret_cast<const typename mpl::deref<T1>::type&>(bits));
    00061                 case 2: return op(reinterpret_cast<const typename mpl::deref<T2>::type&>(bits));
    00062             }
    00063             throw;
    00064         }
    00065     };
    00066 */
    00067
    00068 #define GIL_FWD_TYPEDEFS(z, N, text)   T##N; typedef typename mpl::next<T##N>::type
    00069 #define GIL_FWD_CASE(z, N, SUM)       case N: return op(*gil_reinterpret_cast<typename mpl::deref<T##N>::type*>(&bits));
    00070 #define GIL_FWD_CONST_CASE(z, N, SUM) case N: return op(*gil_reinterpret_cast_c<const typename mpl::deref<T##N>::type*>(&bits));
    00071
    00072 #define GIL_APPLY_FWD_OP(z, N, text)                                                                        \
    00073     template <> struct apply_operation_fwd_fn<BOOST_PP_ADD(N,1)> {                                      \
    00074         template <typename Types, typename Bits, typename UnaryOp>                                     \
    00075         typename UnaryOp::result_type apply(Bits& bits, std::size_t index, UnaryOp op) const {        \
    00076             typedef typename mpl::begin<Types>::type                                             \
    00077             BOOST_PP_REPEAT(N, GIL_FWD_TYPEDEFS, BOOST_PP_EMPTY)                                            \
    00078             T##N;                                                                                       \
    00079             switch (index) {                                                                            \
    00080                 BOOST_PP_REPEAT(BOOST_PP_ADD(N,1), GIL_FWD_CASE, BOOST_PP_EMPTY)                            \
    00081             }                                                                                           \
    00082             throw;                                                                                      \
    00083         }                                                                                               \
    00084         template <typename Types, typename Bits, typename UnaryOp>                                     \
    00085         typename UnaryOp::result_type applyc(const Bits& bits, std::size_t index, UnaryOp op) const { \
    00086             typedef typename mpl::begin<Types>::type                                             \
    00087             BOOST_PP_REPEAT(N, GIL_FWD_TYPEDEFS, BOOST_PP_EMPTY)                                            \
    00088             T##N;                                                                                       \
    00089             switch (index) {                                                                            \
    00090                 BOOST_PP_REPEAT(BOOST_PP_ADD(N,1), GIL_FWD_CONST_CASE,BOOST_PP_EMPTY)                       \
    00091             }                                                                                           \
    00092             throw;                                                                                      \
    00093         }                                                                                               \
    00094     };
    00095
    00096 #define GIL_GENERATE_APPLY_FWD_OPS(N) BOOST_PP_REPEAT(N, GIL_APPLY_FWD_OP, BOOST_PP_EMPTY)
    00097
    00098 namespace detail {
    00099 template <std::size_t N> struct apply_operation_fwd_fn {};
    00100
    00101 // Create specializations of apply_operation_fn for each N 0..100
    00102 GIL_GENERATE_APPLY_FWD_OPS(99)
    00103 } // namespace detail
    00104
    00105 // unary application
    00106 template <typename Types, typename Bits, typename Op>
    00107 typename Op::result_type GIL_FORCEINLINE apply_operation_basec(const Bits& bits, std::size_t index, Op op) {
    00108     return detail::apply_operation_fwd_fn<mpl::size<Types>::value>().template applyc<Types>(bits,index,op);
    00109 }
    00110
    00111 // unary application
    00112 template <typename Types, typename Bits, typename Op>
    00113 typename Op::result_type GIL_FORCEINLINE apply_operation_base(      Bits& bits, std::size_t index, Op op) {
    00114     return detail::apply_operation_fwd_fn<mpl::size<Types>::value>().template apply<Types>(bits,index,op);
    00115 }
    00116
    00117 namespace detail {
    00118     template <typename T2, typename Op>
    00119     struct reduce_bind1 {
    00120         const T2& _t2;
    00121         mutable Op&  _op;
    00122
    00123         typedef typename Op::result_type result_type;
    00124
    00125         reduce_bind1(const T2& t2, Op& op) : _t2(t2), _op(op) {}
    00126
    00127         template <typename T1> GIL_FORCEINLINE result_type operator()(const T1& t1) { return _op(t1, _t2); }
    00128     };
    00129
    00130     template <typename Types1, typename Bits1, typename Op>
    00131     struct reduce_bind2 {
    00132         const Bits1& _bits1;
    00133         std::size_t _index1;
    00134         mutable Op&  _op;
    00135
    00136         typedef typename Op::result_type result_type;
    00137
    00138         reduce_bind2(const Bits1& bits1, std::size_t index1, Op& op) : _bits1(bits1), _index1(index1), _op(op) {}
    00139
    00140         template <typename T2> GIL_FORCEINLINE result_type operator()(const T2& t2) {
    00141             return apply_operation_basec<Types1>(_bits1, _index1, reduce_bind1<T2,Op>(t2, _op));
    00142         }
    00143     };
    00144 } // namespace detail
    00145
    00146 // Binary application by applying on each dimension separately
    00147 template <typename Types1, typename Types2, typename Bits1, typename Bits2, typename Op>
    00148 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) {
    00149     return apply_operation_basec<Types2>(bits2,index2,detail::reduce_bind2<Types1,Bits1,Op>(bits1,index1,op));
    00150 }
    00151
    00152 #undef GIL_FWD_TYPEDEFS
    00153 #undef GIL_FWD_CASE
    00154 #undef GIL_FWD_CONST_CASE
    00155 #undef GIL_APPLY_FWD_OP
    00156 #undef GIL_GENERATE_APPLY_FWD_OPS
    00157 #undef BHS
    00158
    00159 } }  // namespace boost::gil
    00160
    00161
    00162 #endif