00001
00002
00003
00004
00005
00006
00007
00008
00022 #ifndef vector_unroller_h
00023 #define vector_unroller_h
00024
00025 #include <cml/et/traits.h>
00026 #include <cml/et/size_checking.h>
00027 #include <cml/et/scalar_ops.h>
00028
00029 #if !defined(CML_VECTOR_UNROLL_LIMIT)
00030 #error "CML_VECTOR_UNROLL_LIMIT is undefined."
00031 #endif
00032
00033 namespace cml {
00034 namespace et {
00035 namespace detail {
00036
00046 template<class OpT, typename E, class AT, class SrcT>
00047 class VectorAssignmentUnroller
00048 {
00049 protected:
00050
00051
00052 template<int N, int Last, bool can_unroll> struct Eval;
00053
00054
00055 typedef cml::vector<E,AT> vector_type;
00056
00057
00058 typedef ExprTraits<vector_type> dest_traits;
00059 typedef ExprTraits<SrcT> src_traits;
00060
00062 template<int N, int Last> struct Eval<N,Last,true> {
00063 void operator()(vector_type& dest, const SrcT& src) const {
00064
00065
00066 OpT().apply(dest[N], src_traits().get(src,N));
00067
00068
00069
00070 Eval<N+1,Last,true>()(dest, src);
00071 }
00072 };
00073
00075 template<int Last> struct Eval<Last,Last,true> {
00076 void operator()(vector_type& dest, const SrcT& src) const {
00077
00078
00079 OpT().apply(dest[Last], src_traits().get(src,Last));
00080
00081 }
00082 };
00083
00084
00090 template<int N, int Last> struct Eval<N,Last,false> {
00091 void operator()(vector_type& dest, const SrcT& src) const {
00092 for(size_t i = 0; i <= Last; ++i) {
00093 OpT().apply(dest[i], src_traits().get(src,i));
00094
00095 }
00096 }
00097 };
00098
00099
00100 public:
00101
00103 void operator()(vector_type& dest, const SrcT& src, cml::fixed_size_tag)
00104 {
00105 typedef cml::vector<E,AT> vector_type;
00106 enum { Len = vector_type::array_size };
00107 typedef typename VectorAssignmentUnroller<OpT,E,AT,SrcT>::template
00108 Eval<0, Len-1, (Len <= CML_VECTOR_UNROLL_LIMIT)> Unroller;
00109
00110
00111
00112 typedef typename ExprTraits<SrcT>::size_tag src_size;
00113 typedef typename select_if<
00114 same_type<src_size,dynamic_size_tag>::is_true,
00115 dynamic_size_tag, fixed_size_tag>::result size_tag;
00116
00117
00118 CheckedSize(dest,src,size_tag());
00119
00120
00121
00122
00123
00124
00125 Unroller()(dest,src);
00126 }
00127
00128
00129 private:
00130
00131 size_t CheckOrResize(
00132 vector_type& dest, const SrcT& src, cml::resizable_tag)
00133 {
00134 #if defined(CML_AUTOMATIC_VECTOR_RESIZE_ON_ASSIGNMENT)
00135
00136 size_t N = std::max(dest.size(),src_traits().size(src));
00137
00138
00139 cml::et::detail::Resize(dest,N);
00140 #else
00141 size_t N = CheckedSize(dest,src,dynamic_size_tag());
00142 #endif
00143
00144 return N;
00145 }
00146
00147 size_t CheckOrResize(
00148 vector_type& dest, const SrcT& src, cml::not_resizable_tag)
00149 {
00150 return CheckedSize(dest,src,dynamic_size_tag());
00151 }
00152
00153 public:
00154
00155
00157 void operator()(vector_type& dest, const SrcT& src, cml::dynamic_size_tag)
00158 {
00159
00160 typedef ExprTraits<SrcT> src_traits;
00161 size_t N = this->CheckOrResize(
00162 dest,src,typename vector_type::resizing_tag());
00163 for(size_t i = 0; i < N; ++i) {
00164 OpT().apply(dest[i], src_traits().get(src,i));
00165
00166 }
00167 }
00168
00169 };
00170
00175 template<class AccumT, class OpT, class LeftT, class RightT>
00176 struct VectorAccumulateUnroller
00177 {
00178
00179 template<int N, int Last, bool can_unroll> struct Eval;
00180
00181
00182 typedef ExprTraits<LeftT> left_traits;
00183 typedef ExprTraits<RightT> right_traits;
00184
00185
00186 typedef typename AccumT::value_type result_type;
00187
00189 template<int N, int Last> struct Eval<N,Last,true> {
00190 result_type operator()(
00191 const LeftT& left, const RightT& right) const
00192 {
00193
00194 return AccumT().apply(
00195 OpT().apply(left[N], right_traits().get(right,N)),
00196 Eval<N+1,Last,true>()(left, right));
00197
00198 }
00199 };
00200
00202 template<int Last> struct Eval<Last,Last,true> {
00203 result_type operator()(
00204 const LeftT& left, const RightT& right) const
00205 {
00206 return OpT().apply(left[Last],right_traits().get(right,Last));
00207
00208 }
00209 };
00210
00212 template<int N, int Last> struct Eval<N,Last,false> {
00213 result_type operator()(
00214 const LeftT& left, const RightT& right) const
00215 {
00216 result_type accum = OpT().apply(left[0],right[0]);
00217 for(size_t i = 1; i <= Last; ++i) {
00218
00219
00220
00221
00222 accum = AccumT().apply(accum, OpT().apply(
00223 left[i],right_traits().get(right,i)));
00224
00225 }
00226 }
00227 };
00228 };
00229
00230 }
00231
00239 template<class OpT, class SrcT, typename E, class AT> inline
00240 void UnrollAssignment(cml::vector<E,AT>& dest, const SrcT& src)
00241 {
00242
00243 typedef cml::vector<E,AT> vector_type;
00244
00245
00246 typedef detail::VectorAssignmentUnroller<OpT,E,AT,SrcT> unroller;
00247
00248
00249 unroller()(dest, src, typename vector_type::size_tag());
00250
00251 }
00252
00253 }
00254 }
00255
00256 #endif
00257
00258
00259