00001
00002 #ifndef HDNUM_MATRIX_HH
00003 #define HDNUM_MATRIX_HH
00004
00005 #include <iostream>
00006 #include <iomanip>
00007 #include <string>
00008 #include <fstream>
00009
00010 #include "countablearray.hh"
00011 #include "exceptions.hh"
00012
00017 namespace hdnum {
00018
00021 template<class T>
00022 class Matrix {
00023
00024 typedef CountableArray<T> ArrayType;
00025
00026 public:
00027
00029 typedef T value_type;
00030
00032 typedef value_type& reference;
00033
00035 typedef const value_type& const_reference;
00036
00038 typedef std::size_t size_type;
00039
00041 typedef std::ptrdiff_t difference_type;
00042
00044 Matrix () : base(), m(0), n(0), stride(0), data(0)
00045 {}
00046
00048 Matrix (size_type _m, size_type _n)
00049 : base(new ArrayType(_m*_n)), m(_m), n(_n), stride(_n)
00050 {
00051 data = &((*base)[0]);
00052 }
00053
00055 Matrix (size_type _m, size_type _n, const T& _t)
00056 : base(new ArrayType(_m*_n,_t)), m(_m), n(_n), stride(_n)
00057 {
00058 data = &((*base)[0]);
00059 }
00060
00062 Matrix (const Matrix& A)
00063 : base(A.base), m(A.m), n(A.n), stride(A.stride), data(A.data)
00064 {}
00065
00067 Matrix& operator= (const Matrix& A)
00068 {
00069 base = A.base;
00070 m = A.m;
00071 n = A.n;
00072 stride = A.stride;
00073 data = A.data;
00074 }
00075
00077 Matrix<T> sub (size_type i, size_type j, size_type rows, size_type cols) const
00078 {
00079 Matrix<T> A;
00080 A.base = base;
00081 A.stride = stride;
00082 A.m = rows;
00083 A.n = cols;
00084 A.data = data+i*stride+j;
00085 return A;
00086 }
00087
00089 T* operator[] (size_type i)
00090 {
00091 return data+i*stride;
00092 }
00093
00095 const T* operator[] (size_type i) const
00096 {
00097 return data+i*stride;
00098 }
00099
00101 size_type rowsize () const
00102 {
00103 return m;
00104 }
00105
00107 size_type colsize () const
00108 {
00109 return n;
00110 }
00111
00113 int iwidth () const
00114 {
00115 return iwidth_;
00116 }
00117
00119 int width () const
00120 {
00121 return width_;
00122 }
00123
00125 int precision () const
00126 {
00127 return precision_;
00128 }
00129
00131 void iwidth (int i) const
00132 {
00133 iwidth_=i;
00134 }
00135
00137 void width (int i) const
00138 {
00139 width_=i;
00140 }
00141
00143 void precision (int i) const
00144 {
00145 precision_=i;
00146 }
00147
00148 private:
00149 CP<ArrayType> base;
00150 size_type m,n;
00151 size_type stride;
00152 T* data;
00153 static int iwidth_, width_, precision_;
00154 };
00155
00156 template<class T>
00157 int Matrix<T>::iwidth_ = 3;
00158 template<class T>
00159 int Matrix<T>::width_ = 10;
00160 template<class T>
00161 int Matrix<T>::precision_ = 2;
00162
00164 template <class T>
00165 inline std::ostream& operator<< (std::ostream& s, const Matrix<T>& A)
00166 {
00167 s << " " << std::setw(A.iwidth()) << " " << " ";
00168 for (typename Matrix<T>::size_type j=0; j<A.colsize(); ++j)
00169 s << std::setw(A.width()) << j << " ";
00170 s << std::endl;
00171 for (typename Matrix<T>::size_type i=0; i<A.rowsize(); ++i)
00172 {
00173 s << " " << std::setw(A.iwidth()) << i << " ";
00174 for (typename Matrix<T>::size_type j=0; j<A.colsize(); ++j)
00175 s << std::setw(A.width()) << std::scientific << std::showpoint
00176 << std::setprecision(A.precision()) << A[i][j] << " ";
00177 s << std::endl;
00178 }
00179 return s;
00180 }
00181
00183 template<class T>
00184 inline void fill (Matrix<T>& A, const T& t)
00185 {
00186 for (typename Matrix<T>::size_type i=0; i<A.rowsize(); ++i)
00187 for (typename Matrix<T>::size_type j=0; j<A.colsize(); ++j)
00188 A[i][j] = t;
00189 }
00190
00192 template<class T>
00193 inline void zero (Matrix<T>& A)
00194 {
00195 for (typename Matrix<T>::size_type i=0; i<A.rowsize(); ++i)
00196 for (typename Matrix<T>::size_type j=0; j<A.colsize(); ++j)
00197 A[i][j] = T(0);
00198 }
00199
00201 template<class T>
00202 inline void identity (Matrix<T>& A)
00203 {
00204 for (typename Matrix<T>::size_type i=0; i<A.rowsize(); ++i)
00205 for (typename Matrix<T>::size_type j=0; j<A.colsize(); ++j)
00206 if (i==j)
00207 A[i][i] = T(1);
00208 else
00209 A[i][j] = T(0);
00210 }
00211
00213 template<class T>
00214 inline void spd (Matrix<T>& A)
00215 {
00216 if (A.rowsize()!=A.colsize() || A.rowsize()==0)
00217 HDNUM_ERROR("need square and nonempty matrix");
00218 for (typename Matrix<T>::size_type i=0; i<A.rowsize(); ++i)
00219 for (typename Matrix<T>::size_type j=0; j<A.colsize(); ++j)
00220 if (i==j)
00221 A[i][i] = T(4.0);
00222 else
00223 A[i][j] = - T(1.0)/((i-j)*(i-j));
00224 }
00225
00227 template<class T>
00228 inline Matrix<T> copy (const Matrix<T>& A)
00229 {
00230 Matrix<T> B(A.rowsize(),A.colsize());
00231 for (typename Matrix<T>::size_type i=0; i<A.rowsize(); ++i)
00232 for (typename Matrix<T>::size_type j=0; j<A.colsize(); ++j)
00233 B[i][j] = A[i][j];
00234 return B;
00235 }
00236
00238 template<class T>
00239 inline void gnuplot (const std::string& fname, const Matrix<T>& A)
00240 {
00241 std::fstream f(fname.c_str(),std::ios::out);
00242 for (typename Matrix<T>::size_type i=0; i<A.rowsize(); ++i)
00243 {
00244 for (typename Matrix<T>::size_type j=0; j<A.colsize(); ++j)
00245 f << std::setw(A.width()) << std::scientific << std::showpoint
00246 << std::setprecision(A.precision()) << A[i][j] << std::endl;
00247 f << std::endl;
00248 }
00249 f.close();
00250 }
00251
00252
00253 }
00254
00255 #endif