00001
00002
00003
00004
00005
00006
00007
00008
00019 #ifndef matrix_unroller_h
00020 #define matrix_unroller_h
00021
00022 #include <cml/et/traits.h>
00023 #include <cml/et/size_checking.h>
00024 #include <cml/et/scalar_ops.h>
00025
00026 #if !defined(CML_2D_UNROLLER) && !defined(CML_NO_2D_UNROLLER)
00027 #error "The matrix unroller has not been defined."
00028 #endif
00029
00030 #if defined(CML_2D_UNROLLER) && !defined(CML_MATRIX_UNROLL_LIMIT)
00031 #error "CML_MATRIX_UNROLL_LIMIT is undefined."
00032 #endif
00033
00034 namespace cml {
00035 namespace et {
00036 namespace detail {
00037
00049 template<class OpT, typename E, class AT, typename BO, typename L, class SrcT>
00050 class MatrixAssignmentUnroller
00051 {
00052 protected:
00053
00054
00055 typedef cml::matrix<E,AT,BO,L> matrix_type;
00056
00057
00058 typedef ExprTraits<matrix_type> dest_traits;
00059 typedef ExprTraits<SrcT> src_traits;
00060
00061 #if defined(CML_2D_UNROLLER)
00062
00063
00064 template<int R, int C, int LastRow, int LastCol, bool can_unroll>
00065 struct Eval;
00066
00067
00068
00070 template<int R, int C, int LastRow, int LastCol>
00071 struct Eval<R,C,LastRow,LastCol,true> {
00072 void operator()(matrix_type& dest, const SrcT& src) const {
00073
00074
00075 OpT().apply(dest(R,C), src_traits().get(src,R,C));
00076
00077
00078 Eval<R,C+1,LastRow,LastCol,true>()(dest,src);
00079 }
00080 };
00081
00083 template<int R, int LastRow, int LastCol>
00084 struct Eval<R,LastCol,LastRow,LastCol,true> {
00085 void operator()(matrix_type& dest, const SrcT& src) const {
00086
00087
00088 OpT().apply(dest(R,LastCol), src_traits().get(src,R,LastCol));
00089
00090
00091
00092
00093 Eval<R+1,0,LastRow,LastCol,true>()(dest,src);
00094 }
00095 };
00096
00098 template<int C, int LastRow, int LastCol>
00099 struct Eval<LastRow,C,LastRow,LastCol,true> {
00100 void operator()(matrix_type& dest, const SrcT& src) const {
00101
00102
00103 OpT().apply(dest(LastRow,C), src_traits().get(src,LastRow,C));
00104
00105
00106 Eval<LastRow,C+1,LastRow,LastCol,true>()(dest,src);
00107 }
00108 };
00109
00111 template<int LastRow, int LastCol>
00112 struct Eval<LastRow,LastCol,LastRow,LastCol,true> {
00113 void operator()(matrix_type& dest, const SrcT& src) const {
00114
00115
00116 OpT().apply(
00117 dest(LastRow,LastCol),
00118 src_traits().get(src,LastRow,LastCol));
00119 }
00120 };
00121
00122
00124 template<int R, int C, int LastRow, int LastCol>
00125 struct Eval<R,C,LastRow,LastCol,false> {
00126 void operator()(matrix_type& dest, const SrcT& src) const {
00127 for(size_t i = 0; i <= LastRow; ++i) {
00128 for(size_t j = 0; j <= LastCol; ++j) {
00129 OpT().apply(dest(i,j), src_traits().get(src,i,j));
00130 }
00131 }
00132 }
00133 };
00134
00135 #endif // CML_2D_UNROLLER
00136
00137 #if defined(CML_NO_2D_UNROLLER)
00138
00140 template<int R, int C, int LastRow, int LastCol> struct Eval {
00141 void operator()(matrix_type& dest, const SrcT& src) const {
00142 for(size_t i = 0; i <= LastRow; ++i) {
00143 for(size_t j = 0; j <= LastCol; ++j) {
00144 OpT().apply(dest(i,j), src_traits().get(src,i,j));
00145 }
00146 }
00147 }
00148 };
00149
00150 #endif // CML_NO_2D_UNROLLER
00151
00152
00153 public:
00154
00156 void operator()(
00157 cml::matrix<E,AT,BO,L>& dest, const SrcT& src, cml::fixed_size_tag)
00158 {
00159 typedef cml::matrix<E,AT,BO,L> matrix_type;
00160 enum {
00161 LastRow = matrix_type::array_rows-1,
00162 LastCol = matrix_type::array_cols-1,
00163 Max = (LastRow+1)*(LastCol+1)
00164 };
00165
00166 #if defined(CML_2D_UNROLLER)
00167 typedef typename MatrixAssignmentUnroller<OpT,E,AT,BO,L,SrcT>
00168 ::template Eval<0, 0, LastRow, LastCol,
00169 (Max <= CML_MATRIX_UNROLL_LIMIT)> Unroller;
00170 #endif
00171
00172 #if defined(CML_NO_2D_UNROLLER)
00173
00174 typedef typename MatrixAssignmentUnroller<OpT,E,AT,BO,L,SrcT>
00175 ::template Eval<0, 0, LastRow, LastCol> Unroller;
00176 #endif
00177
00178
00179 typedef typename ExprTraits<SrcT>::size_tag src_size;
00180 typedef typename select_if<
00181 same_type<src_size,dynamic_size_tag>::is_true,
00182 dynamic_size_tag, fixed_size_tag>::result size_tag;
00183
00184
00185 CheckedSize(dest,src,size_tag());
00186
00187
00188
00189
00190
00191 Unroller()(dest,src);
00192 }
00193
00194
00195 private:
00196
00197 matrix_size hack_actual_size(
00198 matrix_type& dest, const SrcT& , scalar_result_tag
00199 )
00200 {
00201 typedef ExprTraits<matrix_type> dest_traits;
00202 return dest_traits().size(dest);
00203 }
00204
00205 matrix_size hack_actual_size(
00206 matrix_type& , const SrcT& src, matrix_result_tag
00207 )
00208 {
00209 typedef ExprTraits<SrcT> src_traits;
00210 return src_traits().size(src);
00211 }
00212
00213 matrix_size CheckOrResize(
00214 matrix_type& dest, const SrcT& src, cml::resizable_tag)
00215 {
00216 #if defined(CML_AUTOMATIC_MATRIX_RESIZE_ON_ASSIGNMENT)
00217
00218 matrix_size N = hack_actual_size(
00219 dest, src, typename src_traits::result_tag());
00220
00221
00222 dest.resize(N.first,N.second);
00223 #else
00224 matrix_size N = CheckedSize(dest,src,dynamic_size_tag());
00225 #endif
00226 return N;
00227 }
00228
00229 matrix_size CheckOrResize(
00230 matrix_type& dest, const SrcT& src, cml::not_resizable_tag)
00231 {
00232 return CheckedSize(dest,src,dynamic_size_tag());
00233 }
00234
00235
00236 public:
00237
00238
00246 void operator()(matrix_type& dest, const SrcT& src, cml::dynamic_size_tag)
00247 {
00248 typedef ExprTraits<SrcT> src_traits;
00249 matrix_size N = this->CheckOrResize(
00250 dest,src,typename matrix_type::resizing_tag());
00251 for(size_t i = 0; i < N.first; ++i) {
00252 for(size_t j = 0; j < N.second; ++j) {
00253 OpT().apply(dest(i,j), src_traits().get(src,i,j));
00254
00255 }
00256 }
00257 }
00258 };
00259
00260 }
00261
00273 template<class OpT, class SrcT, typename E, class AT, typename BO, typename L>
00274 inline void UnrollAssignment(cml::matrix<E,AT,BO,L>& dest, const SrcT& src)
00275 {
00276
00277 typedef cml::matrix<E,AT,BO,L> matrix_type;
00278
00279
00280 typedef detail::MatrixAssignmentUnroller<OpT,E,AT,BO,L,SrcT> unroller;
00281
00282
00283 unroller()(dest, src, typename matrix_type::size_tag());
00284
00285 }
00286
00287 }
00288 }
00289
00290 #endif
00291
00292
00293