ViennaCL - The Vienna Computing Library
1.5.0
|
00001 #ifndef VIENNACL_LINALG_ROW_SCALING_HPP_ 00002 #define VIENNACL_LINALG_ROW_SCALING_HPP_ 00003 00004 /* ========================================================================= 00005 Copyright (c) 2010-2013, 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