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_DETAILS_ARRAY_BASE_ELEM_FUNC_HPP 00025 #define IVL_DETAILS_ARRAY_BASE_ELEM_FUNC_HPP 00026 00027 namespace ivl { 00028 00029 00030 00031 // --------------------------------------------------------------- 00032 // binary elem func result definition 00033 00034 namespace array_details { 00035 00036 struct bin_elem_func {}; 00037 struct bin_scalar_r {}; 00038 struct bin_scalar_l {}; 00039 struct bin_val_func {}; 00040 00041 template < 00042 class T, 00043 template <typename, typename, typename> class F, 00044 class A1, 00045 class A2, 00046 class MATCH 00047 > 00048 struct bin_elem_func_result {}; 00049 00050 } /* namespace array_details */ 00051 00052 template < 00053 class T, 00054 template <typename, typename, typename> class F, 00055 class A1, 00056 class A2 00057 > 00058 class binary_elem_func_result 00059 { 00060 typedef typename types::t_if< 00061 types::t_and<types::is_ivl_array<A1>, types::is_ivl_array<A2> >, 00062 array_details::bin_elem_func, 00063 typename types::t_if<types::is_ivl_array<A1>, 00064 array_details::bin_scalar_r, 00065 typename types::t_if<types::is_ivl_array<A2>, 00066 array_details::bin_scalar_l, 00067 array_details::bin_val_func>::type>::type>::type 00068 match_type; 00069 public: 00070 typedef typename 00071 array_details::bin_elem_func_result<T, F, A1, A2, match_type> 00072 ::type type; 00073 typedef typename 00074 array_details::bin_elem_func_result<T, F, A1, A2, match_type> 00075 ::wrapper_type wrapper_type; 00076 00077 static inline 00078 typename array_details::bin_elem_func_result<T, F, A1, A2, match_type> 00079 ::type from(const A1& a1, const A2& a2) 00080 { 00081 return array_details::bin_elem_func_result<T, F, A1, A2, match_type> 00082 ::from(a1, a2); 00083 } 00084 }; 00085 00086 // --------------------------------------------------------------- 00087 // unary elem func result definition 00088 00089 namespace array_details { 00090 00091 struct un_elem_func {}; 00092 struct un_val_func {}; 00093 00094 template < 00095 class T, 00096 template <typename, typename> class F, 00097 class A, 00098 class MATCH 00099 > 00100 struct un_elem_func_result {}; 00101 00102 } /* namespace array_details */ 00103 00104 00105 template < 00106 class T, 00107 template <typename, typename> class F, 00108 class A 00109 > 00110 class unary_elem_func_result 00111 { 00112 typedef typename types::t_if<types::is_ivl_array<A>, 00113 array_details::un_elem_func, array_details::un_val_func> 00114 ::type match_type; 00115 public: 00116 typedef typename 00117 array_details::un_elem_func_result<T, F, A, match_type> 00118 ::type type; 00119 typedef typename 00120 array_details::un_elem_func_result<T, F, A, match_type> 00121 ::wrapper_type wrapper_type; 00122 00123 static inline 00124 type from(const A& a1) 00125 { 00126 return array_details::un_elem_func_result<T, F, A, match_type> 00127 ::from(a1); 00128 } 00129 }; 00130 00131 00132 // -------------------------------------------------------------------- 00133 // elem func classes 00134 00135 00136 template < 00137 class T, 00138 template <typename, typename, typename> class F, 00139 class A1, 00140 class A2 00141 > 00142 class elem_func_binary : public 00143 00144 // types::change_data_class_set< 00145 // typename data::binary_elem_func_traits<F, A1, A2, false>:: 00146 // type, typename A1::derived_type>::type 00147 00148 array_details::binary_operator_result< 00149 typename binary_elem_func_result<T, F, 00150 typename A1::elem_type, typename A2::elem_type>::type, 00151 A1, A2, 00152 data::binary_elem_func<F, 00153 typename A1::derived_type, typename A2::derived_type, false>, 00154 data::binary_elem_func<F, 00155 typename A2::derived_type, typename A1::derived_type, true> >::type 00156 00157 { 00158 public: 00159 //typedef typename types::change_data_class_set< 00160 // typename data::binary_elem_func_traits<F, A1, A2, false>:: 00161 // type, typename A1::derived_type>::type base_class; 00162 typedef typename array_details::binary_operator_result< 00163 typename binary_elem_func_result<T, F, 00164 typename A1::elem_type, typename A2::elem_type>::type, 00165 A1, A2, 00166 data::binary_elem_func<F, 00167 typename A1::derived_type, typename A2::derived_type, false>, 00168 data::binary_elem_func<F, 00169 typename A2::derived_type, typename A1::derived_type, true> >:: 00170 type base_class; 00171 00172 base_class& base() 00173 { return static_cast<base_class&>(*this); } 00174 const base_class& base() const 00175 { return static_cast<const base_class&>(*this); } 00176 00177 00178 elem_func_binary(const A1& a1, const A2& a2) 00179 { 00180 // sets the underlying array references, switching them if SWAP 00181 this->setref(ref1(a1.derived(), a2.derived()), 00182 ref2(a1.derived(), a2.derived())); 00183 00184 this->validate(); 00185 } 00186 00187 elem_func_binary(const elem_func_binary& a) : base_class(a) { } 00188 00189 elem_func_binary& operator=(const elem_func_binary& o) 00190 { base_class::operator=(o); return *this; } 00191 00192 }; 00193 00194 template < 00195 class T, 00196 template <typename, typename, typename> class F, 00197 class A1, 00198 class T2 00199 > 00200 class elem_func_scalar_r : public 00201 types::change_elem_type<typename 00202 binary_elem_func_result<T, F, 00203 typename A1::elem_type, T2>::type, 00204 typename types::change_data_class_set< 00205 data::binary_elem_func<F, typename A1::derived_type, 00206 typename array_details::scalar_to_array<T2, 00207 typename A1::derived_type>::type, false>, 00208 typename A1::derived_type>::type>::type 00209 { 00210 public: 00211 typedef typename types::change_elem_type<typename 00212 binary_elem_func_result<T, F, 00213 typename A1::elem_type, T2>::type, 00214 typename types::change_data_class_set< 00215 data::binary_elem_func<F, typename A1::derived_type, 00216 typename array_details::scalar_to_array<T2, 00217 typename A1::derived_type>::type, false>, 00218 typename A1::derived_type>::type>::type base_class; 00219 00220 base_class& base() 00221 { return static_cast<base_class&>(*this); } 00222 const base_class& base() const 00223 { return static_cast<const base_class&>(*this); } 00224 00225 elem_func_scalar_r(const A1& a1, const T2& t2) 00226 { 00227 this->setref(a1.derived(), 00228 typename array_details::scalar_to_array<T2, 00229 typename A1::derived_type> 00230 ::type(a1.derived().size())); 00231 this->in2->setval(t2); 00232 } 00233 00234 elem_func_scalar_r(const elem_func_scalar_r& a) : base_class(a) { } 00235 00236 elem_func_scalar_r& operator=(const elem_func_scalar_r& o) 00237 { base_class::operator=(o); return *this; } 00238 00239 }; 00240 00241 template < 00242 class T, 00243 template <typename, typename, typename> class F, 00244 class T1, 00245 class A2 00246 > 00247 class elem_func_scalar_l : public 00248 types::change_elem_type<typename 00249 binary_elem_func_result<T, F, 00250 T1, typename A2::elem_type>::type, 00251 typename types::change_data_class_set< 00252 data::binary_elem_func<F, typename A2::derived_type, 00253 typename array_details::scalar_to_array<T1, 00254 typename A2::derived_type>::type, true>, 00255 typename A2::derived_type>::type>::type 00256 { 00257 public: 00258 typedef typename types::change_elem_type<typename 00259 binary_elem_func_result<T, F, 00260 T1, typename A2::elem_type>::type, 00261 typename types::change_data_class_set< 00262 data::binary_elem_func<F, typename A2::derived_type, 00263 typename array_details::scalar_to_array<T1, 00264 typename A2::derived_type>::type, true>, 00265 typename A2::derived_type>::type>::type base_class; 00266 00267 base_class& base() 00268 { return static_cast<base_class&>(*this); } 00269 const base_class& base() const 00270 { return static_cast<const base_class&>(*this); } 00271 00272 elem_func_scalar_l(const T1& t1, const A2& a2) 00273 { 00274 this->setref(a2.derived(), 00275 typename array_details::scalar_to_array<T1, 00276 typename A2::derived_type> 00277 ::type(a2.derived().size())); 00278 this->in2->setval(t1); 00279 } 00280 00281 elem_func_scalar_l(const elem_func_scalar_l& a) : base_class(a) { } 00282 00283 elem_func_scalar_l& operator=(const elem_func_scalar_l& o) 00284 { base_class::operator=(o); return *this; } 00285 00286 }; 00287 00288 template < 00289 class T, 00290 template <typename, typename> class F, 00291 class A 00292 > 00293 class elem_func_unary : public 00294 types::change_elem_type<typename 00295 unary_elem_func_result<T, F, typename A::elem_type>::type, 00296 typename types::change_data_class_set<data:: 00297 unary_elem_func<F, typename A::derived_type>, 00298 typename A::derived_type>::type>::type 00299 { 00300 public: 00301 typedef typename types::change_elem_type<typename 00302 unary_elem_func_result<T, F, typename A::elem_type>::type, 00303 typename types::change_data_class_set<data:: 00304 unary_elem_func<F, typename A::derived_type>, 00305 typename A::derived_type>::type> 00306 ::type base_class; 00307 00308 base_class& base() 00309 { return static_cast<base_class&>(*this); } 00310 const base_class& base() const 00311 { return static_cast<const base_class&>(*this); } 00312 00313 elem_func_unary(const A& a1) { this->setref(a1.derived()); } 00314 00315 elem_func_unary(const elem_func_unary& a) : base_class(a) { } 00316 00317 elem_func_unary& operator=(const elem_func_unary& o) 00318 { base_class::operator=(o); return *this; } 00319 00320 ~elem_func_unary() { } 00321 00322 }; 00323 00324 00325 namespace array_details { 00326 00327 // --------------------------------------------------------------- 00328 // binary elem func result implementation 00329 00330 template < 00331 class T, 00332 template <typename, typename, typename> class F, 00333 class A1, 00334 class A2 00335 > 00336 struct bin_elem_func_result<T, F, A1, A2, bin_elem_func> 00337 { 00338 typedef typename elem_func_binary<T, F, A1, A2>::base_class type; 00339 typedef elem_func_binary<T, F, A1, A2> wrapper_type; 00340 00341 static inline type from(const A1& a1, const A2& a2) 00342 { 00343 return elem_func_binary<T, F, A1, A2>(a1, a2).base(); 00344 } 00345 }; 00346 00347 template < 00348 class T, 00349 template <typename, typename, typename> class F, 00350 class A1, 00351 class T2 00352 > 00353 struct bin_elem_func_result<T, F, A1, T2, bin_scalar_r> 00354 { 00355 typedef typename elem_func_scalar_r<T, F, A1, T2>::base_class type; 00356 typedef elem_func_scalar_r<T, F, A1, T2> wrapper_type; 00357 00358 static inline type from(const A1& a1, const T2& a2) 00359 { 00360 return elem_func_scalar_r<T, F, A1, T2>(a1, a2).base(); 00361 } 00362 }; 00363 00364 template < 00365 class T, 00366 template <typename, typename, typename> class F, 00367 class T1, 00368 class A2 00369 > 00370 struct bin_elem_func_result<T, F, T1, A2, bin_scalar_l> 00371 { 00372 typedef typename elem_func_scalar_l<T, F, T1, A2>::base_class type; 00373 typedef elem_func_scalar_l<T, F, T1, A2> wrapper_type; 00374 00375 static inline type from(const T1& a1, const A2& a2) 00376 { 00377 return elem_func_scalar_l<T, F, T1, A2>(a1, a2).base(); 00378 } 00379 }; 00380 00381 template < 00382 class T, 00383 template <typename, typename, typename> class F, 00384 class T1, 00385 class T2 00386 > 00387 struct bin_elem_func_result<T, F, T1, T2, bin_val_func> 00388 { 00389 typedef T type; 00390 typedef T wrapper_type; 00391 00392 static inline T from(const T1& v1, const T2& v2) 00393 { 00394 return F<T, T1, T2>::elem_op(v1, v2); 00395 } 00396 }; 00397 00398 // --------------------------------------------------------------- 00399 // unary elem func result implementation 00400 00401 template < 00402 class T, 00403 template <typename, typename> class F, 00404 class A 00405 > 00406 struct un_elem_func_result<T, F, A, un_elem_func> 00407 { 00408 typedef typename elem_func_unary<T, F, A>::base_class type; 00409 typedef elem_func_unary<T, F, A> wrapper_type; 00410 00411 static inline type from(const A& a1) 00412 { 00413 return elem_func_unary<T, F, A>(a1).base(); 00414 } 00415 }; 00416 00417 template < 00418 class T, 00419 template <typename, typename> class F, 00420 class T1 00421 > 00422 struct un_elem_func_result<T, F, T1, un_val_func> 00423 { 00424 typedef T type; 00425 typedef T wrapper_type; 00426 00427 static inline T from(const T1& v1) 00428 { 00429 return F<T, T1>::elem_op(v1); 00430 } 00431 }; 00432 00433 } /* namespace array_details */ 00434 00435 // classes that can be used directly to get an element function from one 00436 // (unary) or two (binary) classes and an element operation functor. 00437 // these two classes are wrappers for an according elem_func_binary or 00438 // elem_func_scalar_l or elem_func_scalar_r or elem_func_unary class which 00439 // is direct wrapper to an according array<.> or array_nd<.> or any 00440 // ivl container class with an elem_class data type. 00441 00442 template< 00443 template <typename, typename, typename> class F, 00444 class A1, class A2 00445 > 00446 struct binary_elem_func : public binary_elem_func_result< 00447 typename F<types::term, 00448 typename types::get_value<A1>::type, 00449 typename types::get_value<A2>::type>::default_ret_type, 00450 F, A1, A2>::wrapper_type 00451 { 00452 private: 00453 typedef typename binary_elem_func_result< 00454 typename F<types::term, 00455 typename types::get_value<A1>::type, 00456 typename types::get_value<A2>::type>::default_ret_type, 00457 F, A1, A2>::wrapper_type prv_base; 00458 public: 00459 template<class A, class B> 00460 binary_elem_func(const A& a1, const B& a2) : prv_base(a1, a2) { } 00461 00462 template<class T1, class T2> 00463 binary_elem_func(ivl::internal::tuple<T1, T2> a) 00464 : prv_base(a.val(types::number<1>()), a.val(types::number<2>())) { } 00465 00466 binary_elem_func(const binary_elem_func& a) : prv_base(a) { } 00467 00468 binary_elem_func& operator=(const binary_elem_func& o) 00469 { prv_base::operator=(o); return *this; } 00470 }; 00471 00472 template< 00473 template <typename, typename> class F, 00474 class A1 00475 > 00476 struct unary_elem_func : public unary_elem_func_result< 00477 typename F<types::term, 00478 typename types::get_value<A1>::type>::default_ret_type, 00479 F, A1>::wrapper_type 00480 { 00481 private: 00482 typedef typename unary_elem_func_result< 00483 typename F<types::term, 00484 typename types::get_value<A1>::type>::default_ret_type, 00485 F, A1>::wrapper_type prv_base; 00486 public: 00487 template<class A> 00488 unary_elem_func(const A& a1) : prv_base(a1) { } 00489 00490 unary_elem_func(const unary_elem_func& a) : prv_base(a) { } 00491 00492 unary_elem_func& operator=(const unary_elem_func& o) 00493 { prv_base::operator=(o); return *this; } 00494 }; 00495 00496 } /* namespace ivl */ 00497 00498 #endif // IVL_DETAILS_ARRAY_BASE_ELEM_FUNC_HPP