00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef GIL_APPLY_OPERATION_HPP
00010 #define GIL_APPLY_OPERATION_HPP
00011
00020
00021 #include "apply_operation_base.hpp"
00022 #include "variant.hpp"
00023
00024
00025
00026
00027 #define BINARY_REDUCE_LIMIT 226
00028
00029 #ifndef DO_REDUCE
00030
00031 ADOBE_GIL_NAMESPACE_BEGIN
00032
00033 template <typename TYPES, typename UNARY_OP> GIL_FORCEINLINE
00034 typename UNARY_OP::result_type apply_operation(variant<TYPES>& arg, UNARY_OP op) {
00035 return apply_operation_base<TYPES>(arg._bits, arg._index ,op);
00036 }
00037
00038 template <typename TYPES, typename UNARY_OP> GIL_FORCEINLINE
00039 typename UNARY_OP::result_type apply_operation(const variant<TYPES>& arg, UNARY_OP op) {
00040 return apply_operation_basec<TYPES>(arg._bits, arg._index ,op);
00041 }
00042
00043 template <typename TYPES1, typename TYPES2, typename BINARY_OP> GIL_FORCEINLINE
00044 typename BINARY_OP::result_type apply_operation(const variant<TYPES1>& arg1, const variant<TYPES2>& arg2, BINARY_OP op) {
00045 return apply_operation_base<TYPES1,TYPES2>(arg1._bits, arg1._index, arg2._bits, arg2._index, op);
00046 }
00047
00048 ADOBE_GIL_NAMESPACE_END
00049
00050 #else
00051
00052
00053 #include "type_vector.hpp"
00054 #include "dynamic_at_c.hpp"
00055 #include "reduce.hpp"
00056 #include <boost/mpl/insert.hpp>
00057 #include <boost/mpl/transform.hpp>
00058
00059
00060 ADOBE_GIL_NAMESPACE_BEGIN
00061
00062
00070
00071
00072
00073
00083
00084 template <typename TYPES, typename OP>
00085 struct unary_reduce_impl {
00086 typedef typename boost::mpl::transform<TYPES, detail::reduce<OP, boost::mpl::_1> >::type reduced_t;
00087 typedef typename boost::mpl::copy<reduced_t, boost::mpl::inserter<boost::mpl::set<>, boost::mpl::insert<boost::mpl::_1,boost::mpl::_2> > >::type unique_t;
00088 static const bool is_single=boost::mpl::size<unique_t>::value==1;
00089 };
00090
00091 template <typename TYPES, typename OP, bool SINGLE=unary_reduce_impl<TYPES,OP>::is_single>
00092 struct unary_reduce : public unary_reduce_impl<TYPES,OP> {
00093 typedef typename unary_reduce_impl<TYPES,OP>::reduced_t reduced_t;
00094 typedef typename unary_reduce_impl<TYPES,OP>::unique_t unique_t;
00095
00096 static unsigned short inline map_index(std::size_t index) {
00097 typedef typename boost::mpl::mapping_vector<reduced_t, unique_t> indices_t;
00098 return gil::at_c<indices_t, unsigned short>(index);
00099 }
00100 template <typename BITS> GIL_FORCEINLINE static typename OP::result_type applyc(const BITS& bits, std::size_t index, OP op) {
00101 return apply_operation_basec<unique_t>(bits,map_index(index),op);
00102 }
00103
00104 template <typename BITS> GIL_FORCEINLINE static typename OP::result_type apply(BITS& bits, std::size_t index, OP op) {
00105 return apply_operation_base<unique_t>(bits,map_index(index),op);
00106 }
00107 };
00108
00109 template <typename TYPES, typename OP>
00110 struct unary_reduce<TYPES,OP,true> : public unary_reduce_impl<TYPES,OP> {
00111 typedef typename unary_reduce_impl<TYPES,OP>::unique_t unique_t;
00112 static unsigned short inline map_index(std::size_t index) { return 0; }
00113
00114 template <typename BITS> GIL_FORCEINLINE static typename OP::result_type applyc(const BITS& bits, std::size_t index, OP op) {
00115 return op(reinterpret_cast<const typename boost::mpl::front<unique_t>::type&>(bits));
00116 }
00117
00118 template <typename BITS> GIL_FORCEINLINE static typename OP::result_type apply(BITS& bits, std::size_t index, OP op) {
00119 return op(reinterpret_cast<typename boost::mpl::front<unique_t>::type&>(bits));
00120 }
00121 };
00122
00123
00136
00137 namespace detail {
00138 struct pair_generator {
00139 template <typename VEC2> struct apply {
00140 typedef std::pair<const typename boost::mpl::at_c<VEC2,0>::type*, const typename boost::mpl::at_c<VEC2,1>::type*> type;
00141 };
00142 };
00143
00144
00145 template <typename UNARY_1, typename UNARY_2, typename OP, bool COMPLEX>
00146 struct binary_reduce_impl {
00147
00148 typedef typename boost::mpl::copy_to_vector<typename UNARY_1::unique_t>::type vec1_types;
00149 typedef typename boost::mpl::copy_to_vector<typename UNARY_2::unique_t>::type vec2_types;
00150
00151 typedef boost::mpl::cross_vector<boost::mpl::vector2<vec1_types, vec2_types>, pair_generator> BIN_TYPES;
00152 typedef unary_reduce<BIN_TYPES,OP> bin_reduced_t;
00153
00154 static unsigned short inline map_index(std::size_t index1, std::size_t index2) {
00155 unsigned short r1=UNARY_1::map_index(index1);
00156 unsigned short r2=UNARY_2::map_index(index2);
00157 return bin_reduced_t::map_index(r2*boost::mpl::size<vec1_types>::value + r1);
00158 }
00159 public:
00160 typedef typename bin_reduced_t::unique_t unique_t;
00161
00162 template <typename BITS1, typename BITS2>
00163 static typename OP::result_type inline apply(const BITS1& bits1, std::size_t index1, const BITS2& bits2, std::size_t index2, OP op) {
00164 std::pair<const void*,const void*> pr(&bits1, &bits2);
00165 return apply_operation_basec<unique_t>(pr, map_index(index1,index2),op);
00166 }
00167 };
00168
00169
00170 template <typename UNARY_1, typename UNARY_2, typename OP>
00171 struct binary_reduce_impl<UNARY_1,UNARY_2,OP,true> {
00172 template <typename BITS1, typename BITS2>
00173 static typename OP::result_type inline apply(const BITS1& bits1, std::size_t index1, const BITS2& bits2, std::size_t index2, OP op) {
00174 return apply_operation_base<UNARY_1::unique_t,UNARY_2::unique_t>(bits1, index1, bits2, index2, op);
00175 }
00176 };
00177 }
00178
00179
00180 template <typename TYPES1, typename TYPES2, typename OP>
00181 struct binary_reduce {
00182
00183 typedef unary_reduce<TYPES1,OP> unary1_t;
00184 typedef unary_reduce<TYPES2,OP> unary2_t;
00185
00186 static const std::size_t CROSS_SIZE = boost::mpl::size<typename unary1_t::unique_t>::value *
00187 boost::mpl::size<typename unary2_t::unique_t>::value;
00188
00189 typedef detail::binary_reduce_impl<unary1_t,unary2_t,OP, (CROSS_SIZE>BINARY_REDUCE_LIMIT)> impl;
00190 public:
00191 template <typename BITS1, typename BITS2>
00192 static typename OP::result_type inline apply(const BITS1& bits1, std::size_t index1, const BITS2& bits2, std::size_t index2, OP op) {
00193 return impl::apply(bits1,index1,bits2,index2,op);
00194 }
00195 };
00196
00197 template <typename TYPES, typename UNARY_OP>
00198 GIL_FORCEINLINE typename UNARY_OP::result_type apply_operation(variant<TYPES>& arg, UNARY_OP op) {
00199 return unary_reduce<TYPES,UNARY_OP>::template apply(arg._bits, arg._index ,op);
00200 }
00201
00202 template <typename TYPES, typename UNARY_OP>
00203 GIL_FORCEINLINE typename UNARY_OP::result_type apply_operation(const variant<TYPES>& arg, UNARY_OP op) {
00204 return unary_reduce<TYPES,UNARY_OP>::template applyc(arg._bits, arg._index ,op);
00205 }
00206
00207 template <typename TYPES1, typename TYPES2, typename BINARY_OP>
00208 GIL_FORCEINLINE typename BINARY_OP::result_type apply_operation(const variant<TYPES1>& arg1, const variant<TYPES2>& arg2, BINARY_OP op) {
00209 return binary_reduce<TYPES1,TYPES2,BINARY_OP>::template apply(arg1._bits, arg1._index, arg2._bits, arg2._index, op);
00210 }
00211
00212
00213 ADOBE_GIL_NAMESPACE_END
00214
00215 #endif
00216
00217 #endif