glue_metaprog.hpp

Go to the documentation of this file.
00001 // Copyright (C) 2009 NICTA
00002 // 
00003 // Authors:
00004 // - Conrad Sanderson (conradsand at ieee dot org)
00005 // 
00006 // This file is part of the Armadillo C++ library.
00007 // It is provided without any warranty of fitness
00008 // for any purpose. You can redistribute this file
00009 // and/or modify it under the terms of the GNU
00010 // Lesser General Public License (LGPL) as published
00011 // by the Free Software Foundation, either version 3
00012 // of the License or (at your option) any later version.
00013 // (see http://www.opensource.org/licenses for more info)
00014 
00015 
00016 //! \addtogroup glue_metaprog
00017 //! @{
00018 
00019 
00020 
00021 //! \brief
00022 //! Template metaprogram depth_lhs
00023 //! calculates the number of Glue<Tx,Ty, glue_type> instances on the left hand side argument of Glue<Tx,Ty, glue_type>
00024 //! i.e. it recursively expands each Tx, until the type of Tx is not "Glue<..,.., glue_type>"  (i.e the "glue_type" changes)
00025 
00026 template<typename glue_type, typename T1>
00027 struct depth_lhs
00028   {
00029   static const u32 num = 0;
00030   };
00031 
00032 template<typename glue_type, typename T1, typename T2>
00033 struct depth_lhs< glue_type, Glue<T1,T2,glue_type> >
00034   {
00035   static const u32 num = 1 + depth_lhs<glue_type, T1>::num;
00036   };
00037 
00038 
00039 
00040 //! \brief
00041 //! Template metaprogram mat_ptrs
00042 //! fills a given array with addresses of matrices from a recursive instance of Glue<Tx,Ty, glue_type>.
00043 //! While parsing the recursive instance, if encountered objects are of type Op<..>,
00044 //! they are converted to type 'Mat' first
00045 
00046 template<typename glue_type, typename T1>
00047 struct mat_ptrs
00048   {
00049   typedef typename T1::elem_type elem_type;
00050   
00051   static const u32 num = 0;
00052 
00053   inline
00054   static
00055   void
00056   get_ptrs
00057     (
00058     const Mat<elem_type>** ptrs,
00059     bool* del,
00060     const T1& X
00061     )
00062     {
00063 
00064     ptrs[0] = 
00065       (
00066       is_Mat<T1>::value ?
00067         reinterpret_cast<const Mat<elem_type>*>(&X)
00068       :
00069         new Mat<elem_type>(X)
00070       );
00071 
00072     
00073     del[0] = 
00074       (
00075       is_Mat<T1>::value ?
00076         false
00077       :
00078         true
00079       );
00080 
00081     
00082     }
00083   
00084   };
00085 
00086 
00087 
00088 template<typename glue_type, typename T1, typename T2>
00089 struct mat_ptrs<glue_type, Glue<T1,T2,glue_type> >
00090   {
00091   typedef typename T1::elem_type elem_type;
00092   
00093   static const u32 num = 1 + mat_ptrs<glue_type, T1>::num;
00094   
00095   inline
00096   static
00097   void
00098   get_ptrs
00099     (
00100     const Mat<elem_type>** in_ptrs,
00101     bool* del,
00102     const Glue<T1,T2,glue_type>& X
00103     )
00104     {
00105     isnt_same_type<typename T1::elem_type, typename T2::elem_type>::check();
00106     
00107     mat_ptrs<glue_type, T1>::get_ptrs(in_ptrs, del, X.A);
00108     
00109     in_ptrs[num]  = 
00110       (
00111       is_Mat<T2>::value ?
00112         reinterpret_cast<const Mat<elem_type>*>(&X.B)
00113       :
00114         new Mat<elem_type>(X.B)
00115       );
00116     
00117     del[num] = 
00118       (
00119       is_Mat<T2>::value ?
00120         false
00121       :
00122         true
00123       );
00124     }
00125   
00126   };
00127 
00128 
00129 
00130 //! template metaprogram mat_ptrs_outcheck
00131 //! builds on 'mat_ptrs' by also checking whether any of the input matrices are aliases of the output matrix
00132 
00133 template<typename glue_type, typename T1>
00134 struct mat_ptrs_outcheck
00135   {
00136   typedef typename T1::elem_type elem_type;
00137   
00138   static const u32 num = 0;
00139 
00140   inline
00141   static
00142   void
00143   get_ptrs
00144     (
00145     const Mat<elem_type>** ptrs,
00146     bool* del,
00147     const T1& X,
00148     const Mat<elem_type>* out_ptr
00149     )
00150     {
00151 
00152     const bool same_ptr = 
00153       (
00154       is_Mat<T1>::value ?
00155         (
00156         (out_ptr == reinterpret_cast<const Mat<elem_type>*>(&X)) ?
00157           true
00158         :
00159           false
00160         )
00161       :
00162         false
00163       );
00164 
00165     
00166     ptrs[0] = 
00167       (
00168       same_ptr ?
00169         new Mat<elem_type>(X)
00170       :
00171         (
00172         is_Mat<T1>::value ?
00173           reinterpret_cast<const Mat<elem_type>*>(&X)
00174         :
00175           new Mat<elem_type>(X)
00176         )
00177       );
00178 
00179     
00180     del[0] = 
00181       (
00182       same_ptr ?
00183         true
00184       :
00185         (
00186         is_Mat<T1>::value ?
00187           false
00188         :
00189           true
00190         )
00191       );
00192 
00193     
00194     }
00195   
00196   };
00197 
00198 
00199 
00200 template<typename glue_type, typename T1, typename T2>
00201 struct mat_ptrs_outcheck<glue_type, Glue<T1,T2,glue_type> >
00202   {
00203   typedef typename T1::elem_type elem_type;
00204   
00205   static const u32 num = 1 + mat_ptrs_outcheck<glue_type, T1>::num;
00206   
00207   inline
00208   static
00209   void
00210   get_ptrs
00211     (
00212     const Mat<elem_type>** ptrs,
00213     bool* del,
00214     const Glue<T1,T2,glue_type>& X,
00215     const Mat<elem_type>* out_ptr
00216     )
00217     {
00218     isnt_same_type<typename T1::elem_type, typename T2::elem_type>::check();
00219     
00220     mat_ptrs_outcheck<glue_type, T1>::get_ptrs(ptrs, del, X.A, out_ptr);
00221     
00222     const bool same_ptr =
00223       (
00224       is_Mat<T2>::value ?
00225         (
00226         (out_ptr == reinterpret_cast<const Mat<elem_type>*>(&X.B)) ?
00227           true
00228         :
00229           false
00230         )
00231       :
00232         false
00233       );
00234     
00235     
00236     ptrs[num]  = 
00237       (
00238       same_ptr ?
00239         new Mat<elem_type>(X.B)
00240       :
00241         (
00242         is_Mat<T2>::value ?
00243           reinterpret_cast<const Mat<elem_type>*>(&X.B)
00244         :
00245           new Mat<elem_type>(X.B)
00246         )
00247       );
00248     
00249     
00250     del[num] = 
00251       (
00252       same_ptr ?
00253         true
00254       :
00255         (
00256         is_Mat<T2>::value ?
00257           false
00258         :
00259           true
00260         )
00261       );
00262     }
00263 
00264   };
00265 
00266 
00267 //! @}