ivl 679
ivl/details/array/impl/elem_func.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_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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations