Skylark (Sketching Library)  0.1
/var/lib/jenkins/jobs/Skylark/workspace/sketch/RFUT_Elemental.hpp
Go to the documentation of this file.
00001 #ifndef SKYLARK_RFUT_ELEMENTAL_HPP
00002 #define SKYLARK_RFUT_ELEMENTAL_HPP
00003 
00004 #include <boost/mpi.hpp>
00005 #include "../utility/randgen.hpp"
00006 
00007 namespace skylark { namespace sketch {
00008 
00012 template < typename ValueType,
00013            typename FUT,
00014            elem::Distribution RowDist,
00015            typename ValueDistributionType>
00016 struct RFUT_t<
00017     elem::DistMatrix<ValueType, elem::STAR, RowDist>,
00018     FUT,
00019     ValueDistributionType> :
00020         public RFUT_data_t<ValueDistributionType> {
00021     // Typedef value, matrix, distribution and transform data types
00022     // so that we can use them regularly and consistently.
00023     typedef ValueType value_type;
00024     typedef elem::Matrix<ValueType> local_type;
00025     typedef elem::DistMatrix<ValueType, elem::STAR, RowDist> matrix_type;
00026     typedef elem::DistMatrix<ValueType,
00027                              elem::STAR, RowDist> output_matrix_type;
00028     typedef ValueDistributionType value_distribution_type;
00029     typedef RFUT_data_t<ValueDistributionType> data_type;
00030 
00034     RFUT_t(int N, base::context_t& context)
00035         : data_type (N, context) {
00036 
00037     }
00038 
00042     RFUT_t (RFUT_t<matrix_type,
00043                    FUT,
00044                    value_distribution_type>& other) :
00045         data_type(other) {}
00046 
00050     RFUT_t(const data_type& other_data) :
00051         data_type(other_data) {}
00052 
00057     template <typename Dimension>
00058     void apply (const matrix_type& A,
00059         output_matrix_type& mixed_A,
00060         Dimension dimension) const {
00061         switch (RowDist) {
00062         case elem::VC:
00063         case elem::VR:
00064             try {
00065                 apply_impl_vdist(A, mixed_A, dimension);
00066             } catch (std::logic_error e) {
00067                 SKYLARK_THROW_EXCEPTION (
00068                     base::elemental_exception()
00069                         << base::error_msg(e.what()) );
00070             } catch(boost::mpi::exception e) {
00071                 SKYLARK_THROW_EXCEPTION (
00072                      base::mpi_exception()
00073                          << base::error_msg(e.what()) );
00074                 }
00075             break;
00076 
00077         default:
00078             SKYLARK_THROW_EXCEPTION (
00079                 base::unsupported_matrix_distribution() );
00080         }
00081     }
00082 
00083 private:
00088     void apply_impl_vdist (const matrix_type& A,
00089                            output_matrix_type& mixed_A,
00090                            skylark::sketch::columnwise_tag) const {
00091         // TODO verify that A has the correct size
00092 
00093         // TODO no need to create FUT everytime...
00094         FUT T(data_type::_N);
00095 
00096         // Scale
00097         const local_type& local_A = A.LockedMatrix();
00098         local_type& local_TA = mixed_A.Matrix();
00099         value_type scale = T.scale();
00100         for (int j = 0; j < local_A.Width(); j++)
00101             for (int i = 0; i < data_type::_N; i++)
00102                 local_TA.Set(i, j,
00103                     scale * data_type::D[i] * local_A.Get(i, j));
00104 
00105         // Apply underlying transform
00106         T.apply(local_TA, skylark::sketch::columnwise_tag());
00107     }
00108 
00109 
00110 };
00111 
00115 template < typename ValueType,
00116            typename FUT,
00117            elem::Distribution RowDist,
00118            typename ValueDistributionType>
00119 struct RFUT_t<
00120     elem::DistMatrix<ValueType, RowDist, elem::STAR>,
00121     FUT,
00122     ValueDistributionType> :
00123         public RFUT_data_t<ValueDistributionType> {
00124     // Typedef value, matrix, distribution and transform data types
00125     // so that we can use them regularly and consistently.
00126     typedef ValueType value_type;
00127     typedef elem::Matrix<ValueType> local_type;
00128     typedef elem::DistMatrix<ValueType, RowDist, elem::STAR> matrix_type;
00129     typedef elem::DistMatrix<ValueType, RowDist, elem::STAR> output_matrix_type;
00130     typedef elem::DistMatrix<ValueType, elem::STAR, RowDist> intermediate_type;
00132     typedef ValueDistributionType value_distribution_type;
00133     typedef RFUT_data_t<ValueDistributionType> data_type;
00134 
00138     RFUT_t(int N, base::context_t& context)
00139         : data_type (N, context) {
00140 
00141     }
00142 
00146     RFUT_t (RFUT_t<matrix_type,
00147                    FUT,
00148                    value_distribution_type>& other) :
00149         data_type(other) {}
00150 
00154     RFUT_t(const data_type& other_data) :
00155            data_type(other_data) {}
00156 
00160     template <typename Dimension>
00161     void apply(const matrix_type& A,
00162                output_matrix_type& mixed_A,
00163                Dimension dimension) const {
00164 
00165         switch (RowDist) {
00166             case elem::VC:
00167             case elem::VR:
00168                 try {
00169                     apply_impl_vdist(A, mixed_A, dimension);
00170                 } catch (std::logic_error e) {
00171                     SKYLARK_THROW_EXCEPTION (
00172                         base::elemental_exception()
00173                             << base::error_msg(e.what()) );
00174                 } catch(boost::mpi::exception e) {
00175                     SKYLARK_THROW_EXCEPTION (
00176                         base::mpi_exception()
00177                             << base::error_msg(e.what()) );
00178                 }
00179 
00180                 break;
00181 
00182             default:
00183                 SKYLARK_THROW_EXCEPTION (
00184                     base::unsupported_matrix_distribution() );
00185 
00186         }
00187     }
00188 
00189     template <typename Dimension>
00190     void apply_inverse(const matrix_type& A,
00191                        output_matrix_type& mixed_A,
00192                        Dimension dimension) const {
00193 
00194         switch (RowDist) {
00195             case elem::VC:
00196             case elem::VR:
00197                 try {
00198                     apply_inverse_impl_vdist(A, mixed_A, dimension);
00199                 } catch (std::logic_error e) {
00200                     SKYLARK_THROW_EXCEPTION (
00201                         base::elemental_exception()
00202                             << base::error_msg(e.what()) );
00203                 } catch(boost::mpi::exception e) {
00204                     SKYLARK_THROW_EXCEPTION (
00205                         base::mpi_exception()
00206                             << base::error_msg(e.what()) );
00207                 }
00208 
00209                 break;
00210 
00211         default:
00212             SKYLARK_THROW_EXCEPTION (
00213                 base::unsupported_matrix_distribution() );
00214 
00215         }
00216     }
00217 
00218 
00219 private:
00224     void apply_impl_vdist (const matrix_type& A,
00225                            output_matrix_type& mixed_A,
00226                            skylark::sketch::rowwise_tag) const {
00227         // TODO verify that A has the correct size
00228 
00229         FUT T(data_type::_N);
00230 
00231         // Scale
00232         const local_type& local_A = A.LockedMatrix();
00233         local_type& local_TA = mixed_A.Matrix();
00234         value_type scale = T.scale(local_A);
00235         for (int j = 0; j < data_type::_N; j++)
00236             for (int i = 0; i < local_A.Height(); i++)
00237                 local_TA.Set(i, j,
00238                     scale * data_type::D[j] * local_A.Get(i, j));
00239 
00240         // Apply underlying transform
00241         T.apply(local_TA, skylark::sketch::rowwise_tag());
00242     }
00243 
00248     void apply_impl_vdist (const matrix_type& A,
00249                            output_matrix_type& mixed_A,
00250                            skylark::sketch::columnwise_tag) const {
00251         // TODO verify that A has the correct size
00252         // TODO A and mixed_A have to match
00253 
00254         FUT T(data_type::_N);
00255 
00256         // Rearrange matrix
00257         intermediate_type inter_A(A.Grid());
00258         inter_A = A;
00259 
00260         // Scale
00261         local_type& local_A = inter_A.Matrix();
00262         value_type scale = T.scale(local_A);
00263         for (int j = 0; j < local_A.Width(); j++)
00264             for (int i = 0; i < data_type::_N; i++)
00265                 local_A.Set(i, j,
00266                     scale * data_type::D[i] * local_A.Get(i, j));
00267 
00268         // Apply underlying transform
00269         T.apply(local_A, skylark::sketch::columnwise_tag());
00270 
00271         // Rearrange back
00272         mixed_A = inter_A;
00273     }
00274 
00279     void apply_inverse_impl_vdist  (const matrix_type& A,
00280                                     output_matrix_type& mixed_A,
00281                                     skylark::sketch::columnwise_tag) const {
00282 
00283         FUT T(data_type::_N);
00284 
00285         // TODO verify that A has the correct size
00286         // TODO A and mixed_A have to match
00287 
00288         // Rearrange matrix
00289         intermediate_type inter_A(A.Grid());
00290         inter_A = A;
00291 
00292         // Apply underlying transform
00293         local_type& local_A = inter_A.Matrix();
00294         T.apply_inverse(local_A, skylark::sketch::columnwise_tag());
00295 
00296         // Scale
00297         value_type scale = T.scale(local_A);
00298         for (int j = 0; j < local_A.Width(); j++)
00299             for (int i = 0; i < data_type::_N; i++)
00300                 local_A.Set(i, j,
00301                     scale * data_type::D[i] * local_A.Get(i, j));
00302 
00303         // Rearrange back
00304         mixed_A = inter_A;
00305     }
00306 
00307 };
00308 
00309 } } 
00311 #endif // SKYLARK_RFUT_HPP