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_CORE_DETAILS_ELEM_HPP 00025 #define IVL_CORE_DETAILS_ELEM_HPP 00026 00027 namespace ivl { 00028 00029 namespace core_details { 00030 00031 struct elem_details 00032 { 00033 template<class J, class X> 00034 struct check 00035 { 00036 typedef typename types::t_and<types::is_ivl_array<J>, 00037 types::is_base_eq<typename types::bare_type<X>::type,J> >::type is_ch; 00038 typedef typename types::t_if<is_ch, 00039 scalar<J>, J>::type type; 00040 typedef typename types::t_if<is_ch, 00041 data::ices_wrap_array_attr, data::ice_wrap_array_attr>::type attr; 00042 }; 00043 00044 template<class X, class A, class IS_ARRAY> 00045 struct check_2_0 00046 { 00047 typedef A type; 00048 }; 00049 template<class X, class A> 00050 struct check_2_0<X, A, types::t_true> 00051 { 00052 typedef typename types::change_data_class_set< 00053 data::wrap_array<A, 00054 typename check<typename types::get_value<A>::type, X>::attr> 00055 , 00056 typename types::change_elem_type< 00057 typename check<typename types::get_value<A>::type, X>::type 00058 , 00059 typename A::create_new 00060 >::type 00061 >::type 00062 type; 00063 }; 00064 00065 template<class A ,class X> 00066 struct check_2 00067 { 00068 /* 00069 typedef typename types::t_if<types::is_ivl_array<A>, 00070 array<typename check<typename types::get_value<A>::type, X>::type, 00071 data::wrap_array<A, 00072 typename check<typename types::get_value<A>::type, X>::attr> >, 00073 A 00074 >::type type_1; 00075 */ 00076 typedef typename check_2_0<X, A, typename types::is_ivl_array<A>::type>::type type_1; 00077 00078 typedef typename types::t_if<types::t_and_3<types::is_ivl_array<A>, 00079 types::t_not<typename check<typename types::get_value<A>::type, X>::is_ch>, 00080 typename check<A, X>::is_ch>, 00081 scalar<A>, 00082 type_1>::type type; 00083 // mysterious warning of twice scalar 00084 00085 //typedef type_1 type; 00086 }; 00087 }; 00088 00089 } /* namespace core_details */ 00090 00091 template <class RT, class X1, RT F(X1), int COST=0 > 00092 struct unary_elem 00093 { 00094 typedef typename types::bare_type<RT>::type T; 00095 typedef core_details::elem_details et; 00096 00097 template <class J, class J1> 00098 struct functor 00099 { 00100 typedef types::number<COST> cost; 00101 static inline RT elem_op(X1 x) 00102 { 00103 return F(x); 00104 } 00105 }; 00106 template <class A1> 00107 typename unary_elem_func_result<T, functor, 00108 typename et::check_2<A1, X1>::type> 00109 ::type operator()(const A1& a1) 00110 { 00111 return unary_elem_func_result<T, functor, 00112 typename et::check_2<A1, X1>::type 00113 >::from(a1); 00114 } 00115 00116 // tuple 00117 template <class TPL> 00118 typename unary_elem_func_result<T, functor, typename TPL::t1> 00119 ::type operator[](const internal::tuple_base<1, TPL>& tpl) 00120 { 00121 return unary_elem_func_result<T, functor, typename TPL::t1> 00122 ::from(tpl.derived().v1); 00123 } 00124 /* 00125 // suppose array of tuples 00126 template <class J, class S> 00127 typename unary_elem_func_result<J, functor, 00128 member_array<array<J, S>, typename J::t1> > 00129 ::type operator[](const array<J, S>& a) 00130 { 00131 return unary_elem_func_result<J, functor, 00132 member_array<array<J, S>, typename J::t1> > 00133 ::from(a.in(&J::v1)); 00134 } 00135 */ 00136 // suppose array of tuples 00137 template <class A> 00138 typename unary_elem_func_result< 00139 typename types::get_value<A>::type, functor, 00140 member_array<A, typename types::get_value<A>::type::t1> > 00141 ::type operator[](const A& a) 00142 { 00143 typedef typename types::get_value<A>::type J; 00144 return unary_elem_func_result<J, functor, 00145 member_array<A, typename J::t1> > 00146 ::from(a.in(&J::v1)); 00147 } 00148 00149 }; 00150 00151 template <class RT, class X1, class X2, RT F(X1, X2), int COST=0 > 00152 struct binary_elem 00153 { 00154 typedef typename types::bare_type<RT>::type T; 00155 typedef core_details::elem_details et; 00156 00157 template <class J, class J1, class J2> 00158 struct functor 00159 { 00160 typedef types::number<COST> cost; 00161 static inline RT elem_op(X1 x1, X2 x2) 00162 { 00163 return F(x1, x2); 00164 } 00165 }; 00166 /* 00167 template <class A1, class A2> 00168 typename binary_elem_func_result<T, functor, A1, A2> 00169 ::type operator()(const A1& a1, const A2& a2) 00170 { 00171 return binary_elem_func_result<T, functor, A1, A2> 00172 ::from(a1, a2); 00173 } 00174 */ 00175 00176 // tuple 00177 template <class TPL> 00178 typename binary_elem_func_result<T, functor, 00179 typename TPL::t1, typename TPL::t2> 00180 ::type operator[](const internal::tuple_base<2, TPL>& tpl) 00181 { 00182 return binary_elem_func_result<T, functor, 00183 typename TPL::t1, typename TPL::t2> 00184 ::from(tpl.derived().v1, tpl.derived().v2); 00185 } 00186 // suppose array of tuples 00187 00188 //TODO: do something more correct like a combination 00189 // of ice2 and an elem function doing a 00190 // replacer_cast<X1, scalar<X1> 00191 // this will reach inner_type of an array as well. 00192 00193 template <class J, class S> 00194 typename binary_elem_func_result<T, functor, 00195 00196 array<typename et::check<typename J::t1, X1>::type, 00197 data::wrap_array< 00198 member_array<const array<J, S>, typename J::t1>, 00199 typename et::check<typename J::t1, X1>::attr> >, 00200 00201 array<typename et::check<typename J::t2, X2>::type, 00202 data::wrap_array< 00203 member_array<const array<J, S>, typename J::t2>, 00204 typename et::check<typename J::t2, X2>::attr> > 00205 00206 > 00207 00208 ::type operator[](const array<J, S>& a) 00209 { 00210 00211 return binary_elem_func_result<T, functor, 00212 00213 array<typename et::check<typename J::t1, X1>::type, 00214 data::wrap_array< 00215 member_array<const array<J, S>, typename J::t1>, 00216 typename et::check<typename J::t1, X1>::attr> >, 00217 00218 array<typename et::check<typename J::t2, X2>::type, 00219 data::wrap_array< 00220 member_array<const array<J, S>, typename J::t2>, 00221 typename et::check<typename J::t2, X2>::attr> > 00222 00223 >::from( 00224 member_array<const array<J, S>, typename J::t1>(a.in(&J::v1)), 00225 member_array<const array<J, S>, typename J::t2>(a.in(&J::v2))); 00226 } 00227 00228 template <class A1, class A2> 00229 typename binary_elem_func_result<T, functor, 00230 typename et::check_2<A1, X1>::type, 00231 typename et::check_2<A2, X2>::type 00232 > 00233 ::type operator()(const A1& a1, const A2& a2) 00234 { 00235 return 00236 binary_elem_func_result<T, functor, 00237 typename et::check_2<A1, X1>::type, 00238 typename et::check_2<A2, X2>::type 00239 > 00240 ::from(a1, a2); 00241 } 00242 00243 }; 00244 00245 00246 // same but with given functor 00247 template <class RT, class X1, class X2, template<typename, typename, typename> class F > 00248 struct binary_elem_base 00249 { 00250 typedef typename types::bare_type<RT>::type T; 00251 typedef core_details::elem_details et; 00252 00253 00254 00255 // tuple 00256 template <class TPL> 00257 typename binary_elem_func_result<T, F, 00258 typename TPL::t1, typename TPL::t2> 00259 ::type operator[](const internal::tuple_base<2, TPL>& tpl) 00260 { 00261 return binary_elem_func_result<T, F, 00262 typename TPL::t1, typename TPL::t2> 00263 ::from(tpl.derived().v1, tpl.derived().v2); 00264 } 00265 // suppose array of tuples 00266 00267 //TODO: do something more correct like a combination 00268 // of ice2 and an elem function doing a 00269 // replacer_cast<X1, scalar<X1> 00270 // this will reach inner_type of an array as well. 00271 00272 template <class J, class S> 00273 typename binary_elem_func_result<T, F, 00274 00275 array<typename et::check<typename J::t1, X1>::type, 00276 data::wrap_array< 00277 member_array<const array<J, S>, typename J::t1>, 00278 typename et::check<typename J::t1, X1>::attr> >, 00279 00280 array<typename et::check<typename J::t2, X2>::type, 00281 data::wrap_array< 00282 member_array<const array<J, S>, typename J::t2>, 00283 typename et::check<typename J::t2, X2>::attr> > 00284 00285 > 00286 00287 ::type operator[](const array<J, S>& a) 00288 { 00289 00290 return binary_elem_func_result<T, F, 00291 00292 array<typename et::check<typename J::t1, X1>::type, 00293 data::wrap_array< 00294 member_array<const array<J, S>, typename J::t1>, 00295 typename et::check<typename J::t1, X1>::attr> >, 00296 00297 array<typename et::check<typename J::t2, X2>::type, 00298 data::wrap_array< 00299 member_array<const array<J, S>, typename J::t2>, 00300 typename et::check<typename J::t2, X2>::attr> > 00301 00302 >::from( 00303 member_array<const array<J, S>, typename J::t1>(a.in(&J::v1)), 00304 member_array<const array<J, S>, typename J::t2>(a.in(&J::v2))); 00305 } 00306 00307 template <class A1, class A2> 00308 typename binary_elem_func_result<T, F, 00309 typename et::check_2<A1, X1>::type, 00310 typename et::check_2<A2, X2>::type 00311 > 00312 ::type operator()(const A1& a1, const A2& a2) 00313 { 00314 return 00315 binary_elem_func_result<T, F, 00316 typename et::check_2<A1, X1>::type, 00317 typename et::check_2<A2, X2>::type 00318 > 00319 ::from(a1, a2); 00320 } 00321 00322 }; 00323 00324 /* 00325 template <class T, class X1, T F(X1), class A1 > 00326 typename unary_elem_func_result<T, 00327 unary_elem<T, X1, F>::template functor, 00328 typename core_details::elem_details::check_2<A1, X1>::type 00329 > 00330 ::type 00331 elem_run(T (*f)(X1), const A1& a1) 00332 { 00333 return 00334 unary_elem_func_result<T, 00335 unary_elem<T, X1, F>::template functor, 00336 typename core_details::elem_details::check_2<A1, X1>::type 00337 > 00338 ::from(a1); 00339 } 00340 00341 //template<class T, class X1, class X2> 00342 //struct binary_elem_f 00343 template <class T, class X1, class X2, class F0, class A1, class A2 > 00344 struct elem_func_res 00345 00346 00347 template <class T, class X1, class X2, T F(X1, X2), class A1, class A2 > 00348 typename binary_elem_func_result<T, 00349 binary_elem<T, X1, X2, F>::template functor, 00350 typename core_details::elem_details::check_2<A1, X1>::type, 00351 typename core_details::elem_details::check_2<A2, X2>::type 00352 > 00353 ::type 00354 elem_run((*F), const A1& a1, const A2& a2) 00355 { 00356 return 00357 binary_elem_func_result<T, 00358 binary_elem<T, X1, X2, f>::template functor, 00359 typename core_details::elem_details::check_2<A1, X1>::type, 00360 typename core_details::elem_details::check_2<A2, X2>::type 00361 > 00362 ::from(a1, a2); 00363 } 00364 */ 00365 00366 // -------------------------------------------------- 00367 00368 template<class A, class TP> 00369 struct memberfunc_constructor 00370 { 00371 }; 00372 00373 00374 template<class C, class RT, int COST = 0> 00375 struct void_memberfunc 00376 { 00377 typedef typename types::bare_type<RT>::type R; 00378 00379 template <class J, class J1> 00380 struct functor 00381 { 00382 typedef types::number<COST> cost; 00383 static inline RT elem_op(const tuple<C*, RT (C::*)()>& x1) 00384 { 00385 return (x1.v1->*x1.v2()); 00386 } 00387 }; 00388 00389 }; 00390 00391 00392 template<class A, class RT, class C> 00393 struct memberfunc_constructor<A, internal::tuple<C, RT> > 00394 { 00395 typedef typename types::bare_type<RT>::type R; 00396 00397 A* a; 00398 RT (C::*m)(); 00399 template<class T> 00400 memberfunc_constructor(const T& t) 00401 { 00402 a = &t.v1; 00403 m = t.v2; 00404 } 00405 }; 00406 00407 template<class C, class R, class X1, int COST = 0> 00408 struct unary_memberfunc 00409 { 00410 00411 00412 00413 }; 00414 00415 00416 template<class A, class RT, class C, class X1> 00417 struct memberfunc_constructor<A, internal::tuple<C, RT, X1> > 00418 { 00419 struct nac { }; 00420 typedef typename types::t_if<types::t_eq<RT, void>, nac, RT>::type R0; 00421 typedef typename types::t_if<types::t_eq<RT, void>, nac, int>::type ncall_arg; 00422 typedef typename types::bare_type<R0>::type R; 00423 typedef typename types::remove_const<C>::type Z; 00424 typedef RT (Z::*mm)(X1); 00425 typedef RT (Z::*mmc)(X1) const; 00426 00427 typedef typename types::t_if<types::is_const<C>, 00428 mmc, mm>::type ptr_type; 00429 // todo: const C 00430 typedef core_details::elem_details et; 00431 00432 A* a; 00433 ptr_type m; 00434 template<class T> 00435 memberfunc_constructor(const T& t) 00436 { 00437 a = &t.v1; 00438 m = t.v2; 00439 } 00440 template <class J, class J1, class J2> 00441 struct extender 00442 { 00443 typedef types::number<10> cost; 00444 static inline tuple<Z*, copyscalar<ptr_type> > elem_op(const Z& x1, const copyscalar<ptr_type>& x2) 00445 { 00446 return internal::tuple<Z*, copyscalar<ptr_type> >( 00447 &const_cast<Z&>(x1), // unacceptable!!!!!!!! TODO: fix ASAP @@@ 00448 x2); 00449 } 00450 // alternative for pointer-arrays 00451 static inline tuple<Z*, copyscalar<ptr_type> > elem_op(const Z* x1, const copyscalar<ptr_type>& x2) 00452 { 00453 return internal::tuple<Z*, copyscalar<ptr_type> >( 00454 const_cast<Z*>(x1), // unacceptable!!!!!!!! TODO: fix ASAP @@@, 00455 x2); 00456 } 00457 }; 00458 template <class J, class J1, class J2> 00459 struct functor 00460 { 00461 typedef types::number<10> cost; 00462 template<typename L> 00463 static inline R0 elem_op_imp(Z& cr, ptr_type m, X1 x2, L) 00464 { 00465 return (cr.*m)(x2); 00466 } 00467 // void specialization 00468 static inline R0 elem_op_imp(Z& cr, ptr_type m, X1 x2, nac) 00469 { 00470 (cr.*m)(x2); 00471 return nac(); 00472 } 00473 00474 static inline R0 elem_op(const tuple<Z*, copyscalar<ptr_type> >& x1, X1 x2) 00475 { 00476 Z& cr = *x1.v1; 00477 ptr_type m = x1.v2.t; 00478 00479 return elem_op_imp(cr, m, x2, ncall_arg() ); 00480 } 00481 }; 00482 00483 template<class J, class T, class K> 00484 static inline T ncall(T x, K) { return x; } 00485 template<class J, class T> 00486 static inline T ncall(T x, nac) { ++(J(x)); return x; } 00487 00488 00489 template <class A1> 00490 typename binary_elem_func_result<R, functor, 00491 typename types::t_if<types::is_ivl_array<A>, 00492 array<tuple<Z*, copyscalar<ptr_type> >, wrap_array< 00493 typename 00494 binary_elem_func_result<tuple<Z*, copyscalar<ptr_type> >, extender, A, copyscalar<ptr_type> > 00495 ::type, 00496 data::ice_wrap_array_attr 00497 > >, 00498 scalar<tuple<Z*, copyscalar<ptr_type> > > 00499 >::type, 00500 typename et::check_2<A1, X1>::type 00501 > 00502 ::type operator()(const A1& a1) const 00503 { 00504 return 00505 ncall<typename binary_elem_func_result<R, functor, 00506 typename types::t_if<types::is_ivl_array<A>, 00507 array<tuple<Z*, copyscalar<ptr_type> >, wrap_array< 00508 typename 00509 binary_elem_func_result<tuple<Z*, copyscalar<ptr_type> >, extender, A, copyscalar<ptr_type> > 00510 ::type, 00511 data::ice_wrap_array_attr 00512 > >, 00513 scalar<tuple<Z*, copyscalar<ptr_type> > > 00514 >::type, 00515 typename et::check_2<A1, X1>::type 00516 >::type> 00517 (binary_elem_func_result<R, functor, 00518 typename types::t_if<types::is_ivl_array<A>, 00519 array<tuple<Z*, copyscalar<ptr_type> >, wrap_array< 00520 typename 00521 binary_elem_func_result<tuple<Z*, copyscalar<ptr_type> >, extender, A, copyscalar<ptr_type> > 00522 ::type, 00523 data::ice_wrap_array_attr 00524 > >, 00525 scalar<tuple<Z*, copyscalar<ptr_type> > > 00526 >::type, 00527 typename et::check_2<A1, X1>::type 00528 > 00529 ::from( 00530 binary_elem_func_result<tuple<Z*, copyscalar<ptr_type> >, extender, A, copyscalar<ptr_type> > 00531 ::from(*a, copyscalar<ptr_type>(m)), 00532 a1), ncall_arg()); 00533 00534 00535 /* 00536 typedef array<tuple<Z&, copyscalar<ptr_type> >, wrap_array< 00537 typename 00538 binary_elem_func_result<tuple<Z&, copyscalar<ptr_type> >, extender, A, copyscalar<ptr_type> > 00539 ::type, 00540 data::ice_wrap_array_attr 00541 > > warp; 00542 00543 typedef binary_elem_func_result<tuple<Z&, copyscalar<ptr_type> >, extender, A, copyscalar<ptr_type> > 00544 bint; 00545 00546 return 00547 binary_elem_func_result<R, functor, 00548 warp, 00549 typename et::check_2<A1, X1>::type 00550 > 00551 ::from( 00552 bint::from(*a, copyscalar<ptr_type>(m)) 00553 , a1); 00554 */ 00555 } 00556 00557 }; 00558 00559 } /*namespace ivl*/ 00560 00561 #endif // IVL_CORE_DETAILS_ELEM_HPP