ivl 679
ivl/details/array/impl/row_func.hpp
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations