ViennaCL - The Vienna Computing Library  1.5.1
viennacl/linalg/row_scaling.hpp
Go to the documentation of this file.
00001 #ifndef VIENNACL_LINALG_ROW_SCALING_HPP_
00002 #define VIENNACL_LINALG_ROW_SCALING_HPP_
00003 
00004 /* =========================================================================
00005    Copyright (c) 2010-2014, Institute for Microelectronics,
00006                             Institute for Analysis and Scientific Computing,
00007                             TU Wien.
00008    Portions of this software are copyright by UChicago Argonne, LLC.
00009 
00010                             -----------------
00011                   ViennaCL - The Vienna Computing Library
00012                             -----------------
00013 
00014    Project Head:    Karl Rupp                   rupp@iue.tuwien.ac.at
00015 
00016    (A list of authors and contributors can be found in the PDF manual)
00017 
00018    License:         MIT (X11), see file LICENSE in the base directory
00019 ============================================================================= */
00020 
00025 #include <vector>
00026 #include <cmath>
00027 #include "viennacl/forwards.h"
00028 #include "viennacl/vector.hpp"
00029 #include "viennacl/compressed_matrix.hpp"
00030 #include "viennacl/tools/tools.hpp"
00031 
00032 #include <map>
00033 
00034 namespace viennacl
00035 {
00036   namespace linalg
00037   {
00038 
00040     class row_scaling_tag
00041     {
00042       public:
00047         row_scaling_tag(unsigned int p = 2) : norm_(p) {}
00048 
00050         unsigned int norm() const { return norm_; }
00051 
00052       private:
00053         unsigned int norm_;
00054     };
00055 
00056 
00058     namespace detail
00059     {
00060       template <typename T>
00061       struct row_scaling_for_viennacl
00062       {
00063         enum { value = false };
00064       };
00065 
00066       template <typename ScalarType, unsigned int ALIGNMENT>
00067       struct row_scaling_for_viennacl< viennacl::compressed_matrix<ScalarType, ALIGNMENT> >
00068       {
00069         enum { value = true };
00070       };
00071 
00072       template <typename ScalarType, unsigned int ALIGNMENT>
00073       struct row_scaling_for_viennacl< viennacl::coordinate_matrix<ScalarType, ALIGNMENT> >
00074       {
00075         enum { value = true };
00076       };
00077     }
00085     template <typename MatrixType,
00086               bool is_viennacl = detail::row_scaling_for_viennacl<MatrixType>::value >
00087     class row_scaling
00088     {
00089       typedef typename MatrixType::value_type      ScalarType;
00090 
00091       public:
00097         row_scaling(MatrixType const & mat, row_scaling_tag const & tag) : diag_M(viennacl::traits::size1(mat))
00098         {
00099           assert(mat.size1() == mat.size2() && bool("Size mismatch"));
00100           init(mat, tag);
00101         }
00102 
00103         void init(MatrixType const & mat, row_scaling_tag const & tag)
00104         {
00105           diag_M.resize(mat.size1());  //resize without preserving values
00106 
00107           for (typename MatrixType::const_iterator1 row_it = mat.begin1();
00108                 row_it != mat.end1();
00109                 ++row_it)
00110           {
00111             for (typename MatrixType::const_iterator2 col_it = row_it.begin();
00112                   col_it != row_it.end();
00113                   ++col_it)
00114             {
00115               if (tag.norm() == 0)
00116                 diag_M[col_it.index1()] = std::max<ScalarType>(diag_M[col_it.index1()], std::fabs(*col_it));
00117               else if (tag.norm() == 1)
00118                 diag_M[col_it.index1()] += std::fabs(*col_it);
00119               else if (tag.norm() == 2)
00120                 diag_M[col_it.index1()] += (*col_it) * (*col_it);
00121             }
00122             if (diag_M[row_it.index1()] == 0)
00123               throw "ViennaCL: Zero row encountered while setting up row scaling preconditioner!";
00124 
00125             if (tag.norm() == 2)
00126               diag_M[row_it.index1()] = std::sqrt(diag_M[row_it.index1()]);
00127           }
00128         }
00129 
00130 
00132         template <typename VectorType>
00133         void apply(VectorType & vec) const
00134         {
00135           assert(vec.size() == diag_M.size() && bool("Size mismatch"));
00136           for (vcl_size_t i=0; i<vec.size(); ++i)
00137             vec[i] /= diag_M[i];
00138         }
00139 
00140       private:
00141         std::vector<ScalarType> diag_M;
00142     };
00143 
00144 
00149     template <typename MatrixType>
00150     class row_scaling< MatrixType, true>
00151     {
00152         typedef typename viennacl::result_of::cpu_value_type<typename MatrixType::value_type>::type  ScalarType;
00153 
00154 
00155       public:
00161         row_scaling(MatrixType const & mat, row_scaling_tag const & tag) : diag_M(mat.size1(), viennacl::traits::context(mat))
00162         {
00163           init(mat, tag);
00164         }
00165 
00166         void init(MatrixType const & mat, row_scaling_tag const & tag)
00167         {
00168           switch (tag.norm())
00169           {
00170             case 0:
00171               detail::row_info(mat, diag_M, detail::SPARSE_ROW_NORM_INF);
00172               break;
00173             case 1:
00174               detail::row_info(mat, diag_M, detail::SPARSE_ROW_NORM_1);
00175               break;
00176             case 2:
00177               detail::row_info(mat, diag_M, detail::SPARSE_ROW_NORM_2);
00178               break;
00179             default:
00180               throw "Unknown norm!";
00181           }
00182         }
00183 
00184         template <unsigned int ALIGNMENT>
00185         void apply(viennacl::vector<ScalarType, ALIGNMENT> & vec) const
00186         {
00187           assert(viennacl::traits::size(diag_M) == viennacl::traits::size(vec) && bool("Size mismatch"));
00188           vec = element_div(vec, diag_M);
00189         }
00190 
00191       private:
00192         viennacl::vector<ScalarType> diag_M;
00193     };
00194 
00195   }
00196 }
00197 
00198 
00199 
00200 
00201 #endif
00202 
00203 
00204