Skylark (Sketching Library)  0.1
/var/lib/jenkins/jobs/Skylark/workspace/sketch/RFT_Elemental.hpp
Go to the documentation of this file.
00001 #ifndef SKYLARK_RFT_ELEMENTAL_HPP
00002 #define SKYLARK_RFT_ELEMENTAL_HPP
00003 
00004 namespace skylark {
00005 namespace sketch {
00006 
00010 template <typename ValueType,
00011           template <typename> class InputType,
00012           template <typename> class KernelDistribution>
00013 struct RFT_t <
00014     InputType<ValueType>,
00015     elem::Matrix<ValueType>,
00016     KernelDistribution> :
00017         public RFT_data_t<KernelDistribution> {
00018     // Typedef value, matrix, transform, distribution and transform data types
00019     // so that we can use them regularly and consistently.
00020     typedef ValueType value_type;
00021     typedef InputType<value_type> matrix_type;
00022     typedef elem::Matrix<value_type> output_matrix_type;
00023     typedef RFT_data_t<KernelDistribution> data_type;
00024 private:
00025     typedef skylark::sketch::dense_transform_t <matrix_type,
00026                                                 output_matrix_type,
00027                                                 KernelDistribution>
00028     underlying_t;
00029 
00030 
00031 protected:
00035     RFT_t (int N, int S, base::context_t& context)
00036         : data_type (N, S, context) {
00037 
00038     }
00039 
00040 public:
00044     RFT_t(const RFT_t<matrix_type,
00045                       output_matrix_type,
00046                       KernelDistribution>& other)
00047         : data_type(other) {
00048 
00049     }
00050 
00054     RFT_t(const data_type& other_data)
00055         : data_type(other_data) {
00056 
00057     }
00058 
00062     template <typename Dimension>
00063     void apply (const matrix_type& A,
00064                 output_matrix_type& sketch_of_A,
00065                 Dimension dimension) const {
00066         try {
00067             apply_impl(A, sketch_of_A, dimension);
00068         } catch (std::logic_error e) {
00069             SKYLARK_THROW_EXCEPTION (
00070                 base::elemental_exception()
00071                     << base::error_msg(e.what()) );
00072         } catch(boost::mpi::exception e) {
00073             SKYLARK_THROW_EXCEPTION (
00074                 base::mpi_exception()
00075                     << base::error_msg(e.what()) );
00076         }
00077     }
00078 
00079 private:
00084     void apply_impl(const matrix_type& A,
00085         output_matrix_type& sketch_of_A,
00086         skylark::sketch::columnwise_tag tag) const {
00087 
00088         // TODO verify sizes etc.
00089         underlying_t underlying(*data_type::_underlying_data);
00090         underlying.apply(A, sketch_of_A, tag);
00091 
00092 #       if SKYLARK_HAVE_OPENMP
00093 #       pragma omp parallel for collapse(2)
00094 #       endif
00095         for(int j = 0; j < base::Width(A); j++)
00096             for(int i = 0; i < data_type::_S; i++) {
00097                 value_type x = sketch_of_A.Get(i, j);
00098                 x += data_type::_shifts[i];
00099 
00100 #               ifdef SKYLARK_EXACT_COSINE
00101                 x = std::cos(x);
00102 #               else
00103                 // x = std::cos(x) is slow
00104                 // Instead use low-accuracy approximation
00105                 if (x < -3.14159265) x += 6.28318531;
00106                 else if (x >  3.14159265) x -= 6.28318531;
00107                 x += 1.57079632;
00108                 if (x >  3.14159265)
00109                     x -= 6.28318531;
00110                 x = (x < 0) ?
00111                     1.27323954 * x + 0.405284735 * x * x :
00112                     1.27323954 * x - 0.405284735 * x * x;
00113 #               endif
00114 
00115                 x = data_type::_outscale * x;
00116                 sketch_of_A.Set(i, j, x);
00117             }
00118     }
00119 
00124     void apply_impl(const matrix_type& A,
00125         output_matrix_type& sketch_of_A,
00126         skylark::sketch::rowwise_tag tag) const {
00127 
00128         // TODO verify sizes etc.
00129         underlying_t underlying(*data_type::_underlying_data);
00130         underlying.apply(A, sketch_of_A, tag);
00131 
00132 #       if SKYLARK_HAVE_OPENMP
00133 #       pragma omp parallel for collapse(2)
00134 #       endif
00135         for(int j = 0; j < data_type::_S; j++)
00136             for(int i = 0; i < base::Height(A); i++) {
00137                 value_type x = sketch_of_A.Get(i, j);
00138                 x += data_type::_shifts[j];
00139 
00140 #               ifdef SKYLARK_EXACT_COSINE
00141                 x = std::cos(x);
00142 #               else
00143                 // x = std::cos(x) is slow
00144                 // Instead use low-accuracy approximation
00145                 if (x < -3.14159265) x += 6.28318531;
00146                 else if (x >  3.14159265) x -= 6.28318531;
00147                 x += 1.57079632;
00148                 if (x >  3.14159265)
00149                     x -= 6.28318531;
00150                 x = (x < 0) ?
00151                     1.27323954 * x + 0.405284735 * x * x :
00152                     1.27323954 * x - 0.405284735 * x * x;
00153 #               endif
00154 
00155                 x = data_type::_outscale * x;
00156                 sketch_of_A.Set(i, j, x);
00157             }
00158     }
00159 };
00160 
00164 template <typename ValueType,
00165           elem::Distribution ColDist,
00166           template <typename> class KernelDistribution>
00167 struct RFT_t <
00168     elem::DistMatrix<ValueType, ColDist, elem::STAR>,
00169     elem::DistMatrix<ValueType, ColDist, elem::STAR>,
00170     KernelDistribution> :
00171         public RFT_data_t<KernelDistribution> {
00172     // Typedef value, matrix, transform, distribution and transform data types
00173     // so that we can use them regularly and consistently.
00174     typedef ValueType value_type;
00175     typedef elem::DistMatrix<value_type, ColDist, elem::STAR> matrix_type;
00176     typedef elem::DistMatrix<value_type,
00177                              ColDist, elem::STAR> output_matrix_type;
00178     typedef RFT_data_t<KernelDistribution> data_type;
00179 private:
00180     typedef skylark::sketch::dense_transform_t <matrix_type,
00181                                                 output_matrix_type,
00182                                                 KernelDistribution>
00183     underlying_t;
00184 
00185 protected:
00186 
00187     // Allow only creation by subclasses.
00188 
00192     RFT_t (int N, int S, base::context_t& context)
00193         : data_type (N, S, context) {
00194 
00195     }
00196 
00197 public:
00198 
00202     RFT_t(const RFT_t<matrix_type,
00203                       output_matrix_type,
00204                       KernelDistribution>& other)
00205         : data_type(other) {
00206 
00207     }
00208 
00212     RFT_t(const data_type& other_data)
00213         : data_type(other_data) {
00214 
00215     }
00216 
00220     template <typename Dimension>
00221     void apply (const matrix_type& A,
00222                 output_matrix_type& sketch_of_A,
00223                 Dimension dimension) const {
00224 
00225         switch(ColDist) {
00226         case elem::VR:
00227         case elem::VC:
00228             try {
00229             apply_impl_vdist (A, sketch_of_A, dimension);
00230             } catch (std::logic_error e) {
00231                 SKYLARK_THROW_EXCEPTION (
00232                     base::elemental_exception()
00233                         << base::error_msg(e.what()) );
00234             } catch(boost::mpi::exception e) {
00235                 SKYLARK_THROW_EXCEPTION (
00236                     base::mpi_exception()
00237                         << base::error_msg(e.what()) );
00238             }
00239 
00240             break;
00241 
00242         default:
00243             SKYLARK_THROW_EXCEPTION (
00244                 base::unsupported_matrix_distribution() );
00245         }
00246     }
00247 
00248 private:
00253     void apply_impl_vdist (const matrix_type& A,
00254                      output_matrix_type& sketch_of_A,
00255                      skylark::sketch::columnwise_tag tag) const {
00256         underlying_t underlying(*data_type::_underlying_data);
00257         underlying.apply(A, sketch_of_A, tag);
00258         elem::Matrix<value_type> &Al = sketch_of_A.Matrix();
00259         for(int j = 0; j < base::Width(Al); j++)
00260             for(int i = 0; i < data_type::_S; i++) {
00261                 value_type val = Al.Get(i, j);
00262                 value_type trans =
00263                     data_type::_outscale * std::cos(val + data_type::_shifts[i]);
00264                 Al.Set(i, j, trans);
00265             }
00266     }
00267 
00272     void apply_impl_vdist(const matrix_type& A,
00273         output_matrix_type& sketch_of_A,
00274         skylark::sketch::rowwise_tag tag) const {
00275 
00276         // TODO verify sizes etc.
00277         underlying_t underlying(*data_type::_underlying_data);
00278         underlying.apply(A, sketch_of_A, tag);
00279         elem::Matrix<value_type> &Al = sketch_of_A.Matrix();
00280         for(int j = 0; j < data_type::_S; j++)
00281             for(int i = 0; i < base::Height(Al); i++) {
00282                 value_type val = Al.Get(i, j);
00283                 value_type trans =
00284                     data_type::_outscale * std::cos(val + data_type::_shifts[j]);
00285                 Al.Set(i, j, trans);
00286             }
00287     }
00288 
00289 };
00290 
00291 } } 
00293 #endif // SKYLARK_RFT_ELEMENTAL_HPP