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_PTR_HPP 00025 #define IVL_DETAILS_ARRAY_BASE_ELEM_FUNC_PTR_HPP 00026 00027 // NOTE 00028 // TODO: remove this 00029 // Elem func ptr is a temporary class, before tup elem func is created 00030 // to support pointer to functions elem func 00031 00032 namespace ivl { 00033 00034 00035 00036 // --------------------------------------------------------------- 00037 // binary elem func result definition 00038 00039 namespace array_details { 00040 00041 struct bin_elem_func_ptr {}; 00042 struct bin_scalar_r_ptr {}; 00043 struct bin_scalar_l_ptr {}; 00044 struct bin_val_func_ptr {}; 00045 00046 template < 00047 class T, 00048 template <typename, typename, typename> class F, 00049 class A1, 00050 class A2, 00051 class MATCH 00052 > 00053 struct bin_elem_func_result_ptr {}; 00054 00055 } /* namespace array_details */ 00056 00057 template < 00058 class T, 00059 template <typename, typename, typename> class F, 00060 class A1, 00061 class A2 00062 > 00063 class binary_elem_func_result_ptr 00064 { 00065 typedef typename types::t_if< 00066 types::t_and<types::is_ivl_array<A1>, types::is_ivl_array<A2> >, 00067 array_details::bin_elem_func_ptr, 00068 typename types::t_if<types::is_ivl_array<A1>, 00069 array_details::bin_scalar_r_ptr, 00070 typename types::t_if<types::is_ivl_array<A2>, 00071 array_details::bin_scalar_l_ptr, 00072 array_details::bin_val_func_ptr>::type>::type>::type 00073 match_type; 00074 public: 00075 typedef typename 00076 array_details::bin_elem_func_result_ptr<T, F, A1, A2, match_type> 00077 ::type type; 00078 typedef typename 00079 array_details::bin_elem_func_result_ptr<T, F, A1, A2, match_type> 00080 ::wrapper_type wrapper_type; 00081 typedef typename F<types::term, types::term, types::term>::ptr_t ptr_t; 00082 00083 static inline 00084 typename array_details::bin_elem_func_result_ptr<T, F, A1, A2, match_type> 00085 ::type from(ptr_t p1, const A1& a1, const A2& a2) 00086 { 00087 return array_details::bin_elem_func_result_ptr<T, F, A1, A2, match_type> 00088 ::from(p1, a1, a2); 00089 } 00090 }; 00091 00092 // --------------------------------------------------------------- 00093 // unary elem func result definition 00094 00095 // -------------------------------------------------------------------- 00096 // elem func classes 00097 00098 00099 template < 00100 class T, 00101 template <typename, typename, typename> class F, 00102 class A1, 00103 class A2 00104 > 00105 class elem_func_binary_ptr : public 00106 00107 // types::change_data_class_set< 00108 // typename data::binary_elem_func_traits<F, A1, A2, false>:: 00109 // type, typename A1::derived_type>::type 00110 00111 array_details::binary_operator_result< 00112 typename binary_elem_func_result_ptr<T, F, 00113 typename A1::elem_type, typename A2::elem_type>::type, 00114 A1, A2, 00115 data::binary_elem_func_ptr<F, 00116 typename A1::derived_type, typename A2::derived_type, false>, 00117 data::binary_elem_func_ptr<F, 00118 typename A2::derived_type, typename A1::derived_type, true> >::type 00119 00120 { 00121 public: 00122 //typedef typename types::change_data_class_set< 00123 // typename data::binary_elem_func_traits<F, A1, A2, false>:: 00124 // type, typename A1::derived_type>::type base_class; 00125 typedef typename array_details::binary_operator_result< 00126 typename binary_elem_func_result_ptr<T, F, 00127 typename A1::elem_type, typename A2::elem_type>::type, 00128 A1, A2, 00129 data::binary_elem_func_ptr<F, 00130 typename A1::derived_type, typename A2::derived_type, false>, 00131 data::binary_elem_func_ptr<F, 00132 typename A2::derived_type, typename A1::derived_type, true> >:: 00133 type base_class; 00134 00135 base_class& base() 00136 { return static_cast<base_class&>(*this); } 00137 const base_class& base() const 00138 { return static_cast<const base_class&>(*this); } 00139 00140 typedef typename F<types::term, types::term, types::term>::ptr_t ptr_t; 00141 00142 elem_func_binary_ptr(ptr_t p1, const A1& a1, const A2& a2) 00143 { 00144 // sets the underlying array references, switching them if SWAP 00145 this->setref(p1, ref1(a1.derived(), a2.derived()), 00146 ref2(a1.derived(), a2.derived())); 00147 00148 this->validate(); 00149 } 00150 00151 elem_func_binary_ptr(const elem_func_binary_ptr& a) : base_class(a) { } 00152 00153 elem_func_binary_ptr& operator=(const elem_func_binary_ptr& o) 00154 { base_class::operator=(o); return *this; } 00155 00156 }; 00157 00158 template < 00159 class T, 00160 template <typename, typename, typename> class F, 00161 class A1, 00162 class T2 00163 > 00164 class elem_func_scalar_r_ptr : public 00165 types::change_elem_type<typename 00166 binary_elem_func_result_ptr<T, F, 00167 typename A1::elem_type, T2>::type, 00168 typename types::change_data_class_set< 00169 data::binary_elem_func_ptr<F, typename A1::derived_type, 00170 typename array_details::scalar_to_array<T2, 00171 typename A1::derived_type>::type, false>, 00172 typename A1::derived_type>::type>::type 00173 { 00174 public: 00175 typedef typename types::change_elem_type<typename 00176 binary_elem_func_result_ptr<T, F, 00177 typename A1::elem_type, T2>::type, 00178 typename types::change_data_class_set< 00179 data::binary_elem_func_ptr<F, typename A1::derived_type, 00180 typename array_details::scalar_to_array<T2, 00181 typename A1::derived_type>::type, false>, 00182 typename A1::derived_type>::type>::type base_class; 00183 00184 typedef typename F<types::term, types::term, types::term>::ptr_t ptr_t; 00185 base_class& base() 00186 { return static_cast<base_class&>(*this); } 00187 const base_class& base() const 00188 { return static_cast<const base_class&>(*this); } 00189 00190 elem_func_scalar_r_ptr(ptr_t p1, const A1& a1, const T2& t2) 00191 { 00192 this->setref(p1, a1.derived(), 00193 typename array_details::scalar_to_array<T2, 00194 typename A1::derived_type> 00195 ::type(a1.derived().size())); 00196 this->in2->setval(t2); 00197 } 00198 00199 elem_func_scalar_r_ptr(const elem_func_scalar_r_ptr& a) : base_class(a) { } 00200 00201 elem_func_scalar_r_ptr& operator=(const elem_func_scalar_r_ptr& o) 00202 { base_class::operator=(o); return *this; } 00203 00204 }; 00205 00206 template < 00207 class T, 00208 template <typename, typename, typename> class F, 00209 class T1, 00210 class A2 00211 > 00212 class elem_func_scalar_l_ptr : public 00213 types::change_elem_type<typename 00214 binary_elem_func_result_ptr<T, F, 00215 T1, typename A2::elem_type>::type, 00216 typename types::change_data_class_set< 00217 data::binary_elem_func_ptr<F, typename A2::derived_type, 00218 typename array_details::scalar_to_array<T1, 00219 typename A2::derived_type>::type, true>, 00220 typename A2::derived_type>::type>::type 00221 { 00222 public: 00223 typedef typename types::change_elem_type<typename 00224 binary_elem_func_result_ptr<T, F, 00225 T1, typename A2::elem_type>::type, 00226 typename types::change_data_class_set< 00227 data::binary_elem_func_ptr<F, typename A2::derived_type, 00228 typename array_details::scalar_to_array<T1, 00229 typename A2::derived_type>::type, true>, 00230 typename A2::derived_type>::type>::type base_class; 00231 typedef typename F<types::term, types::term, types::term>::ptr_t ptr_t; 00232 00233 base_class& base() 00234 { return static_cast<base_class&>(*this); } 00235 const base_class& base() const 00236 { return static_cast<const base_class&>(*this); } 00237 00238 elem_func_scalar_l_ptr(ptr_t p1, const T1& t1, const A2& a2) 00239 { 00240 this->setref(p1, a2.derived(), 00241 typename array_details::scalar_to_array<T1, 00242 typename A2::derived_type> 00243 ::type(a2.derived().size())); 00244 this->in2->setval(t1); 00245 } 00246 00247 elem_func_scalar_l_ptr(const elem_func_scalar_l_ptr& a) : base_class(a) { } 00248 00249 elem_func_scalar_l_ptr& operator=(const elem_func_scalar_l_ptr& o) 00250 { base_class::operator=(o); return *this; } 00251 00252 }; 00253 00254 00255 namespace array_details { 00256 00257 // --------------------------------------------------------------- 00258 // binary elem func result implementation 00259 00260 template < 00261 class T, 00262 template <typename, typename, typename> class F, 00263 class A1, 00264 class A2 00265 > 00266 struct bin_elem_func_result_ptr<T, F, A1, A2, bin_elem_func_ptr> 00267 { 00268 typedef typename elem_func_binary_ptr<T, F, A1, A2>::base_class type; 00269 typedef elem_func_binary_ptr<T, F, A1, A2> wrapper_type; 00270 typedef typename F<types::term, types::term, types::term>::ptr_t ptr_t; 00271 00272 static inline type from(ptr_t p1, const A1& a1, const A2& a2) 00273 { 00274 return elem_func_binary_ptr<T, F, A1, A2>(p1, a1, a2).base(); 00275 } 00276 }; 00277 00278 template < 00279 class T, 00280 template <typename, typename, typename> class F, 00281 class A1, 00282 class T2 00283 > 00284 struct bin_elem_func_result_ptr<T, F, A1, T2, bin_scalar_r_ptr> 00285 { 00286 typedef typename elem_func_scalar_r_ptr<T, F, A1, T2>::base_class type; 00287 typedef elem_func_scalar_r_ptr<T, F, A1, T2> wrapper_type; 00288 typedef typename F<types::term, types::term, types::term>::ptr_t ptr_t; 00289 00290 static inline type from(ptr_t p1, const A1& a1, const T2& a2) 00291 { 00292 return elem_func_scalar_r_ptr<T, F, A1, T2>(p1, a1, a2).base(); 00293 } 00294 }; 00295 00296 template < 00297 class T, 00298 template <typename, typename, typename> class F, 00299 class T1, 00300 class A2 00301 > 00302 struct bin_elem_func_result_ptr<T, F, T1, A2, bin_scalar_l_ptr> 00303 { 00304 typedef typename elem_func_scalar_l_ptr<T, F, T1, A2>::base_class type; 00305 typedef elem_func_scalar_l_ptr<T, F, T1, A2> wrapper_type; 00306 typedef typename F<types::term, types::term, types::term>::ptr_t ptr_t; 00307 00308 static inline type from(ptr_t p1, const T1& a1, const A2& a2) 00309 { 00310 return elem_func_scalar_l_ptr<T, F, T1, A2>(p1, a1, a2).base(); 00311 } 00312 }; 00313 00314 template < 00315 class T, 00316 template <typename, typename, typename> class F, 00317 class T1, 00318 class T2 00319 > 00320 struct bin_elem_func_result_ptr<T, F, T1, T2, bin_val_func_ptr> 00321 { 00322 typedef T type; 00323 typedef T wrapper_type; 00324 typedef typename F<types::term, types::term, types::term>::ptr_t ptr_t; 00325 00326 static inline T from(ptr_t p1, const T1& v1, const T2& v2) 00327 { 00328 return F<T, T1, T2>::elem_op(p1, v1, v2); 00329 } 00330 }; 00331 00332 } /* namespace array_details */ 00333 00334 // classes that can be used directly to get an element function from one 00335 // (unary) or two (binary) classes and an element operation functor. 00336 // these two classes are wrappers for an according elem_func_binary or 00337 // elem_func_scalar_l or elem_func_scalar_r or elem_func_unary class which 00338 // is direct wrapper to an according array<.> or array_nd<.> or any 00339 // ivl container class with an elem_class data type. 00340 00341 template< 00342 template <typename, typename, typename> class F, 00343 class A1, class A2 00344 > 00345 struct binary_elem_func_ptr : public binary_elem_func_result_ptr< 00346 typename F<types::term, 00347 typename types::get_value<A1>::type, 00348 typename types::get_value<A2>::type>::default_ret_type, 00349 F, A1, A2>::wrapper_type 00350 { 00351 private: 00352 typedef typename binary_elem_func_result_ptr< 00353 typename F<types::term, 00354 typename types::get_value<A1>::type, 00355 typename types::get_value<A2>::type>::default_ret_type, 00356 F, A1, A2>::wrapper_type prv_base; 00357 typedef typename F<types::term, types::term, types::term>::ptr_t ptr_t; 00358 public: 00359 template<class A, class B> 00360 binary_elem_func_ptr(ptr_t p1, const A& a1, const B& a2) : prv_base(p1, a1, a2) { } 00361 00362 template<class T1, class T2> 00363 binary_elem_func_ptr(ivl::internal::tuple<T1, T2> a) 00364 : prv_base(a.val(types::number<1>()), a.val(types::number<2>()), a.val(types::number<3>())) { } 00365 00366 binary_elem_func_ptr(const binary_elem_func_ptr& a) : prv_base(a) { } 00367 00368 binary_elem_func_ptr& operator=(const binary_elem_func_ptr& o) 00369 { prv_base::operator=(o); return *this; } 00370 }; 00371 00372 00373 } /* namespace ivl */ 00374 00375 #endif // IVL_DETAILS_ARRAY_BASE_ELEM_FUNC_HPP