ivl 679
|
00001 /* This file is part of the ivl C++ library <http://image.ntua.gr/ivl>. 00002 A C++ template library extending syntax towards mathematical notation. 00003 00004 Copyright (C) 2012 Yannis Avrithis <iavr@image.ntua.gr> 00005 Copyright (C) 2012 Kimon Kontosis <kimonas@image.ntua.gr> 00006 00007 ivl is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU Lesser General Public License 00009 version 3 as published by the Free Software Foundation. 00010 00011 Alternatively, you can redistribute it and/or modify it under the terms 00012 of the GNU General Public License version 2 as published by the Free 00013 Software Foundation. 00014 00015 ivl is distributed in the hope that it will be useful, 00016 but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00018 See the GNU General Public License for more details. 00019 00020 You should have received a copy of the GNU General Public License 00021 and a copy of the GNU Lesser General Public License along 00022 with ivl. If not, see <http://www.gnu.org/licenses/>. */ 00023 00024 #ifndef IVL_ARRAY_DETAILS_ROW_FUNC 00025 #define IVL_ARRAY_DETAILS_ROW_FUNC 00026 00027 namespace ivl { 00028 namespace row_func_details { 00029 00030 00031 template<bool enable_idx = false> 00032 class index_count 00033 { 00034 public: 00035 index_count() { } 00036 00037 inline void next(); 00038 00039 template<class F, class S> 00040 inline 00041 void elem_op(const F& f, const S& val) 00042 { 00043 F.elem_op(val); 00044 } 00045 }; 00046 00047 template<> 00048 class index_count<true> 00049 { 00050 size_t idx; 00051 00052 public: 00053 index_count() { idx = 0; } 00054 00055 inline void next() { idx++; } 00056 00057 template<class F, class S> 00058 inline 00059 void elem_op(const F& f, const S& val) 00060 { 00061 F.elem_op(val, idx); 00062 } 00063 }; 00064 00065 00066 template<bool IDX> 00067 struct first_elem_first 00068 { 00069 template<class F, class S, class N, class K> 00070 static 00071 typename types::get_templ_arg<2, F>::type loop(const array<S, N, K>& a) 00072 { 00073 typename array<S, N, K>::const_iterator cit = a.begin(); 00074 typename array<S, N, K>::const_iterator eit = a.end(); 00075 00076 F func(*cit); 00077 index_count<IDX> idx; 00078 00079 for(++cit; cit != eit; ++cit) { 00080 idx.next(); 00081 idx.elem_op(func, *cit); 00082 } 00083 00084 return func.result(); 00085 } 00086 00087 00088 }; 00089 00090 template<bool IDX> 00091 struct length_first 00092 { 00093 template<class F, class S, class N, class K> 00094 static 00095 typename types::get_templ_arg<2, F>::type loop(const array<S, N, K>& a) 00096 { 00097 typename array<S, N, K>::const_iterator cit = a.begin(); 00098 typename array<S, N, K>::const_iterator eit = a.end(); 00099 00100 F func(a.length()); 00101 index_count<IDX> idx; 00102 00103 for(++cit; cit != eit; ++cit) { 00104 idx.elem_op(func, *cit); 00105 idx.next(); 00106 } 00107 00108 return func.result(); 00109 } 00110 }; 00111 00112 // elem_row_class for max 4 lvalue args 00113 template<template<typename, typename> class F, class S, class O1, 00114 class O2 = types::term, class O3 = types::term, class O4 = types::term> 00115 class elem_row_class 00116 { 00117 public: 00118 typedef O1 elem_type; 00119 00120 template<class D, class P> 00121 static 00122 inline 00123 O1 calculate(const array<S, D, P>& in) 00124 { 00125 typedef F<S, O1> functype; 00126 typedef typename functype::behavior behavior; 00127 return behavior::loop<functype>(in); 00128 } 00129 00130 template<class D, class P> 00131 static 00132 inline 00133 void calculate(const array<S, D, P>& in, O1& o1, O2& o2) 00134 { 00135 typedef F<S, internal::tuple<O1, O2> > functype; 00136 typedef typename functype::behavior behavior; 00137 behavior::loop<functype>(in).get(o1, o2); 00138 } 00139 00140 template<class D, class P> 00141 static 00142 inline 00143 void calculate(const array<S, D, P>& in, O1& o1, O2& o2, O3& o3) 00144 { 00145 typedef F<S, internal::tuple<O1, O2, O3> > functype; 00146 typedef typename functype::behavior behavior; 00147 behavior::loop<functype>(in).get(o1, o2, o3); 00148 } 00149 00150 template<class D, class P> 00151 static 00152 inline 00153 void calculate(const array<S, D, P>& in, O1& o1, O2& o2, O3& o3, O4& o4) 00154 { 00155 typedef F<S, internal::tuple<O1, O2, O3, O4> > functype; 00156 typedef typename functype::behavior behavior; 00157 behavior::loop<functype>(in).get(o1, o2, o3, o4); 00158 } 00159 }; 00160 00161 template<class F, class A> 00162 class row_array_type 00163 { 00164 }; 00165 00166 template<class F, class T, class D, class P> 00167 class row_array_type<F, array<T, D, P> > 00168 //: public types::class_type<typename F::elem_type> 00169 { 00170 public: 00171 typedef typename F::elem_type elem_type; 00172 typedef typename A::elem_type eval_type; 00173 00174 static 00175 inline 00176 elem_type calculate(const array<T, D, P>& a) 00177 { 00178 return F::calculate(a); 00179 } 00180 00181 static 00182 inline 00183 elem_type produce(const array<T, D, P>& a) 00184 { 00185 return calculate(a); 00186 } 00187 00188 }; 00189 00190 00191 template<class F, class T, class D, class P> 00192 class row_array_type<F, array_2d<T, D, P> > 00193 : 00194 public array_2d<typename F::elem_type, 00195 data::row_elem_func_2d_data_id<F, array_2d<T, D, P> >, types::term>, 00196 public rvalue_base<row_array_type<F, array_2d<T, D, P> 00197 { 00198 public: 00199 typedef row_array_type eval_type; 00200 static inline internal::tuple<const array_2d<T, D, P>&, size_t dim> 00201 produce(const array<T, D, P>&a, size_t dim) 00202 { return internal::tpl(a,dim);} 00203 00204 // this class is initialized with set_input, and not with constructor. 00205 // the reason is to simplify (make smaller) the code 00206 // in each row_function specialization [TODO: subject to debate] 00207 row_array_type() { } 00208 00209 template 00210 <class L1, class M1, class N1, 00211 class L2, class M2, class N2> 00212 void output( 00213 const array_2d<L1, M1, N1>& o1, 00214 const array_2d<L2, M2, N2>& o2) 00215 { 00216 size_t len = this->length(); 00217 size_t row = in_dim == 0 ? 1 : len; 00218 size_t col = in_dim == 1 ? 1 : len; 00219 o1.resize(row, col); 00220 o2.resize(row, col); 00221 00222 return loops::row_func_2d_output<F>(in, in_dim, o1, o2); 00223 } 00224 00225 template 00226 <class L1, class M1, class N1, 00227 class L2, class M2, class N2, 00228 class L3, class M3, class N3> 00229 void output( 00230 const array_2d<L1, M1, N1>& o1, 00231 const array_2d<L2, M2, N2>& o2, 00232 const array_2d<L3, M3, N3>& o3) 00233 { 00234 size_t len = this->length(); 00235 size_t row = in_dim == 0 ? 1 : len; 00236 size_t col = in_dim == 1 ? 1 : len; 00237 o1.resize(row, col); 00238 o2.resize(row, col); 00239 o3.resize(row, col); 00240 00241 return loops::row_func_2d_output<F>(in, in_dim, o1, o2, o3); 00242 } 00243 00244 template 00245 <class L1, class M1, class N1, 00246 class L2, class M2, class N2, 00247 class L3, class M3, class N3, 00248 class L4, class M4, class N4> 00249 void output( 00250 const array_2d<L1, M1, N1>& o1, 00251 const array_2d<L2, M2, N2>& o2, 00252 const array_2d<L3, M3, N3>& o3, 00253 const array_2d<L4, M4, N4>& o4) 00254 { 00255 size_t len = this->length(); 00256 size_t row = in_dim == 0 ? 1 : len; 00257 size_t col = in_dim == 1 ? 1 : len; 00258 o1.resize(row, col); 00259 o2.resize(row, col); 00260 o3.resize(row, col); 00261 o4.resize(row, col); 00262 00263 return loops::row_func_2d_output<F>(in, in_dim, o1, o2, o3, o4); 00264 } 00265 00266 }; 00267 00268 00269 00270 template<class F, class T, class D, class P> 00271 class row_array_type<F, array_nd<T, D, P> > 00272 : 00273 public array_nd<typename F::elem_type, 00274 data::row_elem_func_nd_data_id<F, array_nd<T, D, P> >, types::term>, 00275 public rvalue<row_array_type<F, array_nd<T, D, P> 00276 { 00277 public: 00278 typedef row_array_type eval_type; 00279 00280 // this class is initialized with set_input, and not with constructor. 00281 // the reason is to simplify (make smaller) the code 00282 // in each row_function specialization [TODO: subject to debate] 00283 row_array_type() { } 00284 00285 template 00286 <class L1, class M1, class N1, 00287 class L2, class M2, class N2> 00288 void output( 00289 const array_nd<L1, M1, N1>& o1, 00290 const array_nd<L2, M2, N2>& o2) 00291 { 00292 return loops::row_func_nd_output<F>(in, in_dim, 00293 this->in_dims, this->size_nd(), o1, o2); 00294 } 00295 00296 template 00297 <class L1, class M1, class N1, 00298 class L2, class M2, class N2, 00299 class L3, class M3, class N3> 00300 void output( 00301 const array_nd<L1, M1, N1>& o1, 00302 const array_nd<L2, M2, N2>& o2, 00303 const array_nd<L3, M3, N3>& o3) 00304 { 00305 return loops::row_func_nd_output<F>(in, in_dim, 00306 this->in_dims, this->size_nd(), o1, o2, o3); 00307 } 00308 00309 template 00310 <class L1, class M1, class N1, 00311 class L2, class M2, class N2, 00312 class L3, class M3, class N3, 00313 class L4, class M4, class N4> 00314 void output( 00315 const array_nd<L1, M1, N1>& o1, 00316 const array_nd<L2, M2, N2>& o2, 00317 const array_nd<L3, M3, N3>& o3, 00318 const array_nd<L4, M4, N4>& o4) 00319 { 00320 return loops::row_func_nd_output<F>(in, in_dim, 00321 this->in_dims, this->size_nd(), o1, o2, o3, o4); 00322 } 00323 00324 }; 00325 00326 } /* namespace row_func_details */ 00327 } /* namespace ivl */ 00328 00329 #endif // IVL_ARRAY_DETAILS_ROW_FUNC