ivl 679
ivl/details/core/keyword_operators/elem.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_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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations