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_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