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