00001 #ifndef DUNE_ALGLIB_MATRIX_HH
00002 #define DUNE_ALGLIB_MATRIX_HH
00003
00004 #include <cassert>
00005 #include <vector>
00006
00007 #include <dune/localfunctions/utility/field.hh>
00008
00009
00010 #if HAVE_ALGLIB
00011 #include <alglib/amp.h>
00012 #include <alglib/inv.h>
00013 #endif
00014
00015 namespace Dune
00016 {
00017
00018 template< class F, bool aligned = false >
00019 class LFEMatrix;
00020
00021
00022 template< class F, bool aligned >
00023 class LFEMatrix
00024 {
00025 typedef LFEMatrix< F, aligned > This;
00026
00027 typedef std::vector< F > Row;
00028 typedef std::vector<Row> RealMatrix;
00029
00030 public:
00031 typedef F Field;
00032
00033 operator const RealMatrix & () const
00034 {
00035 return matrix_;
00036 }
00037
00038 operator RealMatrix & ()
00039 {
00040 return matrix_;
00041 }
00042
00043 template <class Vector>
00044 void row( const unsigned int row, Vector &vec ) const
00045 {
00046 assert(row<rows());
00047 for (int i=0;i<cols();++i)
00048 field_cast(matrix_[row][i], vec[i]);
00049 }
00050
00051 const Field &operator() ( const unsigned int row, const unsigned int col ) const
00052 {
00053 assert(row<rows());
00054 assert(col<cols());
00055 return matrix_[ row ][ col ];
00056 }
00057
00058 Field &operator() ( const unsigned int row, const unsigned int col )
00059 {
00060 assert(row<rows());
00061 assert(col<cols());
00062 return matrix_[ row ][ col ];
00063 }
00064
00065 unsigned int rows () const
00066 {
00067 return rows_;
00068 }
00069
00070 unsigned int cols () const
00071 {
00072 return cols_;
00073 }
00074
00075 const Field *rowPtr ( const unsigned int row ) const
00076 {
00077 assert(row<rows());
00078 return &(matrix_[row][0]);
00079 }
00080
00081 Field *rowPtr ( const unsigned int row )
00082 {
00083 assert(row<rows());
00084 return &(matrix_[row][0]);
00085 }
00086
00087 void resize ( const unsigned int rows, const unsigned int cols )
00088 {
00089 matrix_.resize(rows);
00090 for (unsigned int i=0;i<rows;++i)
00091 matrix_[i].resize(cols);
00092 rows_ = rows;
00093 cols_ = cols;
00094 }
00095
00096 bool invert ()
00097 {
00098 assert( rows() == cols() );
00099 std::vector<unsigned int> p(rows());
00100 for (unsigned int j=0;j<rows();++j)
00101 p[j] = j;
00102 for (unsigned int j=0;j<rows();++j)
00103 {
00104
00105 unsigned int r = j;
00106 Field max = std::abs( (*this)(j,j) );
00107 for (unsigned int i=j+1;i<rows();++i)
00108 {
00109 if ( std::abs( (*this)(i,j) ) > max )
00110 {
00111 max = std::abs( (*this)(i,j) );
00112 r = i;
00113 }
00114 }
00115 if (max == Zero<Field>())
00116 return false;
00117
00118 if (r > j)
00119 {
00120 for (unsigned int k=0;k<cols();++k)
00121 std::swap( (*this)(j,k), (*this)(r,k) );
00122 std::swap( p[j], p[r] );
00123 }
00124
00125 Field hr = Unity<Field>()/(*this)(j,j);
00126 for (unsigned int i=0;i<rows();++i)
00127 (*this)(i,j) *= hr;
00128 (*this)(j,j) = hr;
00129 for (unsigned int k=0;k<cols();++k)
00130 {
00131 if (k==j) continue;
00132 for (unsigned int i=0;i<rows();++i)
00133 {
00134 if (i==j) continue;
00135 (*this)(i,k) -= (*this)(i,j)*(*this)(j,k);
00136 }
00137 (*this)(j,k) *= -hr;
00138 }
00139 }
00140
00141 Row hv(rows());
00142 for (unsigned int i=0;i<rows();++i)
00143 {
00144 for (unsigned int k=0;k<rows();++k)
00145 hv[ p[k] ] = (*this)(i,k);
00146 for (unsigned int k=0;k<rows();++k)
00147 (*this)(i,k) = hv[k];
00148 }
00149 return true;
00150 }
00151
00152 private:
00153 RealMatrix matrix_;
00154 unsigned int cols_,rows_;
00155 };
00156
00157 #if HAVE_ALGLIB
00158 template< unsigned int precision, bool aligned >
00159 class LFEMatrix< amp::ampf< precision >, aligned >
00160 {
00161 public:
00162 typedef amp::ampf< precision > Field;
00163 private:
00164 typedef LFEMatrix< amp::ampf< precision >, aligned > This;
00165 typedef ap::template_2d_array< Field, aligned > RealMatrix;
00166
00167 public:
00168 operator const RealMatrix & () const
00169 {
00170 return matrix_;
00171 }
00172
00173 operator RealMatrix & ()
00174 {
00175 return matrix_;
00176 }
00177
00178 template <class Vector>
00179 void row( const unsigned int row, Vector &vec ) const
00180 {
00181 assert(row<rows());
00182 for (unsigned int i=0;i<cols();++i)
00183 field_cast(matrix_(row,i), vec[i]);
00184 }
00185
00186 const Field &operator() ( const unsigned int row, const unsigned int col ) const
00187 {
00188 assert(row<rows());
00189 assert(col<cols());
00190 return matrix_( row, col );
00191 }
00192
00193 Field &operator() ( const unsigned int row, const unsigned int col )
00194 {
00195 assert(row<rows());
00196 assert(col<cols());
00197 return matrix_( row, col );
00198 }
00199
00200 unsigned int rows () const
00201 {
00202 return matrix_.gethighbound( 1 )+1;
00203 }
00204
00205 unsigned int cols () const
00206 {
00207 return matrix_.gethighbound( 2 )+1;
00208 }
00209
00210 const Field *rowPtr ( const unsigned int row ) const
00211 {
00212 assert(row<rows());
00213 const int lastCol = matrix_.gethighbound( 2 );
00214 ap::const_raw_vector< Field > rowVector = matrix_.getrow( row, 0, lastCol );
00215 assert( (rowVector.GetStep() == 1) && (rowVector.GetLength() == lastCol+1) );
00216 return rowVector.GetData();
00217 }
00218
00219 Field *rowPtr ( const unsigned int row )
00220 {
00221 assert(row<rows());
00222 const int lastCol = matrix_.gethighbound( 2 );
00223 ap::raw_vector< Field > rowVector = matrix_.getrow( row, 0, lastCol );
00224 assert( (rowVector.GetStep() == 1) && (rowVector.GetLength() == lastCol+1) );
00225 return rowVector.GetData();
00226 }
00227
00228 void resize ( const unsigned int rows, const unsigned int cols )
00229 {
00230 matrix_.setbounds( 0, rows-1, 0, cols-1 );
00231 }
00232
00233 bool invert ()
00234 {
00235 assert( rows() == cols() );
00236 return inv::rmatrixinverse< precision >( matrix_, rows() );
00237 }
00238
00239 private:
00240 RealMatrix matrix_;
00241 };
00242 #endif
00243
00244 template< class Field, bool aligned >
00245 inline std::ostream &operator<<(std::ostream &out, const LFEMatrix<Field,aligned> &mat)
00246 {
00247 for (unsigned int r=0;r<mat.rows();++r)
00248 {
00249 out << field_cast<double>(mat(r,0));
00250 for (unsigned int c=1;c<mat.cols();++c)
00251 {
00252 out << " , " << field_cast<double>(mat(r,c));
00253 }
00254 out << std::endl;
00255 }
00256 return out;
00257 }
00258 }
00259
00260 #endif // #ifndef DUNE_ALGLIB_MATRIX_HH