ivl 679
ivl/details/array/impl/specialization_details/elem_func/elem_func_tools.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_SPECIALIZATION_DETAILS_ELEM_FUNC_TOOLS_HPP
00025 #define IVL_ARRAY_SPECIALIZATION_DETAILS_ELEM_FUNC_TOOLS_HPP
00026 
00027 namespace ivl {
00028 namespace array_details {
00029 
00030 template<class T, bool HAS_RANDOM_ACCESS = false>
00031 struct elem_func_tools
00032 {
00033 };
00034 
00035 template <class T>
00036 struct elem_func_tools_common
00037 {
00038 
00039         typedef T brackets_ret_type;
00040 
00041         // TODO : these specs are not for binary elem_func.
00042         // the whole class is generic so it can be renamed and placed in
00043         // data/ member control.hpp
00044         typedef const T& const_ref_brackets_type;
00045         typedef T& ref_brackets_type;
00046 };
00047 
00048 template <class T>
00049 struct elem_func_tools <T, false>
00050 : public elem_func_tools_common<T>
00051 {
00052         class not_a_type : public std::complex<int> { }; // for <, >=
00053 
00054         /*typedef int brackets_ret_type;
00055 
00056         // TODO : these specs are not for binary elem_func.
00057         // the whole class is generic so it can be renamed and placed in
00058         // data/ member control.hpp
00059         typedef int const_ref_brackets_type;
00060         typedef int ref_brackets_type;
00061         */
00062         typedef typename elem_func_tools::brackets_ret_type brackets_ret_type;
00063         typedef typename elem_func_tools::ref_brackets_type ref_brackets_type;
00064         typedef typename elem_func_tools::const_ref_brackets_type
00065                 const_ref_brackets_type;
00066 
00067 
00068         typedef not_a_type brackets_arg;
00069 
00070         template <class C>
00071         struct rnd_it
00072         {
00073                 struct foo {
00074                         foo() {}
00075                         template<class T1> foo(T1) {}
00076                         template<class T1, class T2> foo(T1,T2) {}
00077                         template<class T1, class T2, class T3> foo(T1,T2,T3) {}
00078                 };
00079                 typedef foo type;
00080                 //typedef std::complex<int> type; // because it has 0 and (0, 0) constr.
00081         };
00082 
00083         template<class A>
00084         static inline
00085         brackets_ret_type brackets(const A& a, brackets_arg j) { return *a; }
00086 
00087         // TODO : these specs are not for binary elem_func.
00088         // the whole class is generic so it can be renamed and placed in
00089         // data/ member control.hpp
00090         template<class A>
00091         static inline
00092         ref_brackets_type ref_brackets(const A& a, brackets_arg j) { return *a; }
00093 
00094         template<class R>
00095         struct brackets_c
00096         {
00097                 template<class A>
00098                 static inline R f(A& a, brackets_arg j) { return *a; }
00099         };
00100         //
00101 
00102         template<class A>
00103         static inline int add_op(const A& a, brackets_arg j) { return 0; }
00104 
00105         template<class A>
00106         static inline A add_op_void(const A& a, brackets_arg j) { return a; }
00107 
00108         template<class A>
00109         static inline int sub_op(const A& a, brackets_arg j) { return 0; }
00110 
00111         template<class A>
00112         static inline ptrdiff_t dif_op(const A& a, const A& b) { return 0; }
00113 
00114         template<class A>
00115         static inline void add_asgn(const A& a, brackets_arg j) { }
00116 
00117         template<class A>
00118         static inline void sub_asgn(const A& a, brackets_arg j) { }
00119 
00120         // ---------------
00121         // nd usefull tools
00122         template <class A>
00123         struct meta_nd
00124         {
00125                 typedef typename A::stride_type stride_type;
00126                 //      typedef not_a_type stride_type;
00127 
00128         };
00129 
00130 };
00131 
00132 template<class T>
00133 struct elem_func_tools<T, true>
00134 : public elem_func_tools_common<T>
00135 {
00136 
00137         class not_a_type { };
00138 /*
00139         typedef T brackets_ret_type;
00140 
00141         // TODO : these specs are not for binary elem_func.
00142         // the whole class is generic so it can be renamed and placed in
00143         // data/ member control.hpp
00144         typedef const T& const_ref_brackets_type;
00145         typedef T& ref_brackets_type;
00146 */
00147         typedef typename elem_func_tools::brackets_ret_type brackets_ret_type;
00148         typedef typename elem_func_tools::ref_brackets_type ref_brackets_type;
00149         typedef typename elem_func_tools::const_ref_brackets_type
00150                 const_ref_brackets_type;
00151 
00152 
00153         typedef size_t brackets_arg;
00154 
00155         template <class C>
00156         struct rnd_it
00157         {
00158                 typedef C type;
00159         };
00160 
00161         template<class A>
00162         static inline
00163         brackets_ret_type brackets(const A& a, brackets_arg j) { return a[j]; }
00164 
00165         // TODO : these specs are not for binary elem_func.
00166         // the whole class is generic so it can be renamed and placed in
00167         // data/ member control.hpp
00168         template<class A>
00169         static inline
00170         const_ref_brackets_type ref_brackets(const A& a,
00171                 brackets_arg j) { return a[j]; }
00172 
00173         template<class A>
00174         static inline
00175         ref_brackets_type ref_brackets(A& a, brackets_arg j) { return a[j]; }
00176 
00177         template<class R>
00178         struct brackets_c
00179         {
00180                 template<class A>
00181                 static inline R f(A& a, brackets_arg j) { return a[j]; }
00182         };
00183         //
00184 
00185         template<class A>
00186         static inline A add_op(const A& a, brackets_arg j) { return a + j; }
00187 
00188         template<class A>
00189         static inline A add_op_void(const A& a, brackets_arg j) { return a + j; }
00190 
00191         template<class A>
00192         static inline A sub_op(const A& a, brackets_arg j) { return a - j; }
00193 
00194         template<class A>
00195         static inline ptrdiff_t dif_op(const A& a0, const A& a1)
00196         {
00197                 return a0 - a1;
00198         }
00199 
00200         template<class A>
00201         static inline void add_asgn(A& a, brackets_arg j) { a += j; }
00202 
00203         template<class A>
00204         static inline void sub_asgn(A& a, brackets_arg j) { a -= j; }
00205 
00206         // ---------------
00207         // nd usefull tools
00208         template <class A>
00209         struct meta_nd
00210         {
00211                 typedef typename A::stride_type stride_type;
00212 
00213         };
00214 
00215 };
00216 
00217 
00218 // ----------------------
00219 // is_elem_array
00220 
00221 template <class D>
00222 struct is_elem_data_type : public types::t_false { };
00223 
00224 template <template <typename, typename, typename> class F,
00225                         class A1, class A2, bool SWAP_ARGS >
00226 struct is_elem_data_type<data::binary_elem_func<F, A1, A2, SWAP_ARGS> >
00227 : public types::t_true { };
00228 
00229 template <template <typename, typename> class F, class A>
00230 struct is_elem_data_type<data::unary_elem_func<F, A> >
00231 : public types::t_true { };
00232 
00233 template <class A, class IS_IVL_ARRAY>
00234 struct is_elem_array_tool : public types::t_false { };
00235 
00236 template <class A>
00237 struct is_elem_array_tool<A, types::t_true> : public
00238         is_elem_data_type<typename A::data_type>
00239 { };
00240 
00241 template <class A>
00242 struct is_elem_array
00243 : public is_elem_array_tool<A, typename types::is_ivl_array<A>::type> { };
00244 
00245 // ----------------------
00246 
00247 
00248 template <bool SWAP_ARGS, class T, class F>
00249 struct elem_func_swap_op_val
00250 {
00251         template<class J, class K>
00252         static inline T from(const J& j, const K& k) { return F::elem_op(j, k); }
00253         // TODO: for _ptr
00254         template<class J, class K, class L>
00255         static inline T from(const L& l, const J& j, const K& k) { return F::elem_op(l, j, k); }
00256 };
00257 
00258 template <class T, class F>
00259 struct elem_func_swap_op_val<true, T, F>
00260 {
00261         template<class J, class K>
00262         static inline T from(const J& j, const K& k) { return F::elem_op(k, j); }
00263         // TODO: for _ptr
00264         template<class J, class K, class L>
00265         static inline T from(const L& l, const J& j, const K& k) { return F::elem_op(l, k, j); }
00266 };
00267 
00268 template <bool SWAP_ARGS, class T, class F, class A1_SCALAR, class A2_SCALAR>
00269 struct elem_func_swap_op_arr { };
00270 /*
00271 template <class T, class F>
00272 struct elem_func_swap_op_arr<false, T, F, types::term, types::term>
00273 {
00274         template<class J, class K>
00275         static inline T from(const J& j, const K& k)
00276                 { T x; x.setref(j, k); return x; }
00277 };
00278 
00279 template <class T, class F>
00280 struct elem_func_swap_op_arr<true, T, F, types::term, types::term>
00281 {
00282         template<class J, class K>
00283         static inline T from(const J& j, const K& k)
00284                 { T x; x.setref(k, j); return x; }
00285 };
00286 */
00287 template <bool SWAP_ARGS, class T, class F>
00288 struct elem_func_swap_op_arr<SWAP_ARGS, T, F, types::term, types::term>
00289 {
00290         template<class J, class K>
00291         static inline T from(const J& j, const K& k)
00292                 { T x; x.setref(j, k); return x; }
00293 };
00294 
00295 template <bool SWAP_ARGS, class T, class F, class SCALAR1>
00296 struct elem_func_swap_op_arr<SWAP_ARGS, T, F, SCALAR1, types::term>
00297 {
00298         template<class J, class K>
00299         static inline T from(const J& j, const K& k)
00300         {
00301                 SCALAR1 j_s(k.derived().size());
00302                 j_s.setval(j);
00303                 T x; x.setref(j_s, k); return x;
00304         }
00305 };
00306 
00307 template <bool SWAP_ARGS, class T, class F, class SCALAR2>
00308 struct elem_func_swap_op_arr<SWAP_ARGS, T, F, types::term, SCALAR2>
00309 {
00310         template<class J, class K>
00311         static inline T from(const J& j, const K& k)
00312         {
00313                 SCALAR2 k_s(j.derived().size());
00314                 k_s.setval(k);
00315                 T x; x.setref(j, k_s); return x;
00316         }
00317 };
00318 
00319 template <bool SWAP_ARGS, class T, class F, class A1_SCALAR, class A2_SCALAR>
00320 struct elem_func_swap_op
00321 : public
00322 types::t_if<is_elem_array<T>,
00323         elem_func_swap_op_arr<SWAP_ARGS, T, F, A1_SCALAR, A2_SCALAR>,
00324         elem_func_swap_op_val<SWAP_ARGS, T, F> >::type
00325 {
00326 };
00327 
00328 template <class T, class F, class IS_ELEM_ARRAY>
00329 struct elem_func_unary_op_tool { };
00330 
00331 template <class T, class F>
00332 struct elem_func_unary_op_tool<T, F, types::t_false>
00333 {
00334         template <class J>
00335         static inline T from(const J& j) { return F::elem_op(j); }
00336 };
00337 
00338 template <class T, class F>
00339 struct elem_func_unary_op_tool<T, F, types::t_true>
00340 {
00341         template <class J>
00342         static inline T from(const J& j) {
00343                 // TODO: this needs some focus: the implementation below
00344                 // is like this provided that the used class (T) is an ivl::array.
00345                 // however, if T is the elem_func class that is derived from that
00346                 // ??? array then the code below is changed, that's why i comment out:
00347                 T x; x.setref(j); return x;
00348                         //TODO:REMOVE:std::cout << "dbg: " << T(j) << std::endl;
00349                 //return T(j); // (T constructed from j).
00350         }
00351 };
00352 
00353 template <class T, class F>
00354 struct elem_func_unary_op
00355 : public
00356         elem_func_unary_op_tool<T, F, typename is_elem_array<T>::type>
00357 {
00358 };
00359 
00360 //-------------------------------------------------------------
00361 // tools useful for higher elem_func classes
00362 
00363 
00364 template <
00365         class T,
00366         class A1,
00367         class A2,
00368         class D1,
00369         class D2
00370 >
00371 struct binary_operator_result
00372 {
00373         typedef typename A1::derived_type a1;
00374         typedef typename A2::derived_type a2;
00375 
00376         typedef typename types::change_data_class_set<D1, a1>::type n_a1;
00377 
00378         typedef typename types::change_data_class_set<D1, a2>::type n_a2;
00379 
00380         typedef typename types::to_type<T, n_a1>::type n1;
00381         typedef typename types::to_type<T, n_a2>::type n2;
00382 
00383         typedef typename types::change_data_class_set<data::normal, n1>::type nn1;
00384         typedef typename types::change_data_class_set<data::normal, n2>::type nn2;
00385 
00386         typedef typename types::highest_common<n1, n2>::type_a hc;
00387 
00388         typedef typename types::t_and<
00389                         types::is_base_eq<ivl::array_nd<T, data::normal>, nn1>,
00390                         types::t_not<
00391                                 types::is_base_eq<ivl::array_nd<T, data::normal>, nn2> >
00392                 >::type a1_nd;
00393 
00394         typedef typename types::t_and<
00395                         types::is_base_eq<ivl::array_nd<T, data::normal>, nn2>,
00396                         types::t_not<
00397                                 types::is_base_eq<ivl::array_nd<T, data::normal>, nn1> >
00398                 >::type a2_nd;
00399 
00400         typedef a2_nd swap;
00401 
00402         typedef typename types::t_if<a1_nd, n1,
00403                 typename types::t_if<a2_nd,
00404                         typename types::change_data_class_set<D2, n2>::type, hc>
00405                         ::type>::type type_elem;
00406 
00407         typedef typename types::change_elem_type<T, type_elem>::type type;
00408 
00409         typedef typename types::t_if<swap, const a2&, const a1&>::type in1_t;
00410         typedef typename types::t_if<swap, const a1&, const a2&>::type in2_t;
00411 
00412 };
00413 
00417 template <class T, class A>
00418 class scalar_to_array
00419 {
00420         // TODO: I would rather this would make an array of the provided level
00421         // type and not derived. However this would probably mean to revise
00422         // the whole ivl. and also I would need a tool to keep the class
00423         // template, without derived info (leaving term), or is there one ?! :)
00424         typedef typename types::normal_type<A>::type a_t;
00425 
00426         // this determines the storage type used for elem_func scalar types.
00427         // @@@@ typedef ref_val_repeat data_type; <-was like that
00428 
00429         //typedef val_repeat data_type;
00430 
00431         //TODO: Why scalars!?
00432         typedef typename types::t_if<
00433                 types::t_or<
00434                         types::is_base<types::copyscalar_identifier, T>,
00435                         types::is_base<types::scalar_identifier, T>
00436                 >, val_repeat, ref_val_repeat>::type data_type;
00437 
00438 public:
00439         typedef typename types::change_elem_type<T, typename
00440                 types::change_data_class_set<data_type, a_t>::type>::type type;
00441 
00442 };
00443 
00444 
00445 } /* namespace array_details */
00446 } /* namespace ivl */
00447 
00448 #endif // IVL_ARRAY_SPECIALIZATION_DETAILS_ELEM_FUNC_TOOLS_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations