00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef IXLIB_MATRIX
00011 #define IXLIB_MATRIX
00012
00013
00014
00015 #include <cmath>
00016 #include <iostream>
00017 #include <ixlib_exgen.hh>
00018 #include <ixlib_array.hh>
00019 #include <ixlib_numeric.hh>
00020
00021
00022
00023
00024 namespace ixion {
00025 template <class T>
00026 struct number_traits {
00027 typedef T number_type;
00028 typedef T scalar_type;
00029
00030 static const number_type zero = 0;
00031
00032 static scalar_type norm(number_type value) {
00033 return NUM_ABS(value);
00034 }
00035 static number_type sqrt(number_type value) {
00036 return ::sqrt(value);
00037 }
00038
00039 static void isRing();
00040 static void isField();
00041 static void isVectorSpace();
00042 };
00043
00044
00045
00046
00047
00048 template <class T,class Traits = number_traits<T> >
00049 class matrix {
00050 protected:
00051 TSize Height,Width;
00052 auto_array<T> Data;
00053
00054 public:
00055 typedef Traits traits_type;
00056 typedef typename traits_type::number_type entry_type;
00057 typedef typename traits_type::scalar_type scalar_type;
00058 typedef T *iterator;
00059 typedef T const *const_iterator;
00060
00061 matrix(TSize height = 0,TSize width = 0);
00062 template<class InputIterator>
00063 inline matrix(TSize height,TSize width,InputIterator first);
00064 matrix(matrix const &src);
00065
00066 matrix &operator=(matrix const &src);
00067
00068 matrix &operator+=(matrix const &op2);
00069 matrix &operator-=(matrix const &op2);
00070 matrix &operator*=(matrix const &op2) {
00071 return operator=(operator*(op2));
00072 }
00073
00074 matrix &operator*=(scalar_type scalar);
00075
00076 matrix operator-() const {
00077 matrix copy(*this);
00078 copy *= -1;
00079 return copy;
00080 }
00081 matrix operator+(matrix const &op2) const {
00082 matrix copy(*this);
00083 copy += op2;
00084 return copy;
00085 }
00086 matrix operator-(matrix const &op2) const {
00087 matrix copy(*this);
00088 copy -= op2;
00089 return copy;
00090 }
00091 matrix operator*(matrix const &op2) const;
00092
00093 matrix operator()(TIndex row) const {
00094 return extractRow(row);
00095 }
00096 entry_type &operator()(TIndex row,TIndex col) {
00097 return Data[getIndex(row,col)];
00098 }
00099 entry_type operator()(TIndex row,TIndex col) const {
00100 return Data[getIndex(row,col)];
00101 }
00102
00103 iterator begin() {
00104 return Data.get();
00105 }
00106 const_iterator begin() const {
00107 return Data.get();
00108 }
00109 iterator end() {
00110 return Data.get()+getSize();
00111 }
00112 const_iterator end() const {
00113 return Data.get()+getSize();
00114 }
00115
00116 TSize width() const {
00117 return Width;
00118 }
00119 TSize height() const {
00120 return Height;
00121 }
00122
00123 matrix extract(TIndex row,TIndex col,TSize height,TSize width) const;
00124 matrix extractRow(TIndex row) const {
00125 return extract(row,0,1,Width);
00126 }
00127 matrix extractColumn(TIndex col) const {
00128 return extract(0,col,Height,1);
00129 }
00130
00131 matrix &set(TIndex row,TIndex col,matrix const &src);
00132 matrix &setRow(TIndex row,matrix const &src) {
00133 return set(row,0,src);
00134 }
00135 matrix &setColumn(TIndex col,matrix const &src) {
00136 return set(0,col,src);
00137 }
00138
00139 matrix &add(TIndex row,TIndex col,matrix const &src,entry_type factor = 1);
00140 matrix &addRow(TIndex row,matrix &src,entry_type factor = 1) {
00141 return add(row,0,src,factor);
00142 }
00143 matrix &addColumn(TIndex col,matrix &src,entry_type factor = 1) {
00144 return add(0,col,src,factor);
00145 }
00146
00147 matrix &addRowSelf(TIndex to,TIndex from,entry_type factor = 1,TIndex startcol = 0);
00148 matrix &addColumnSelf(TIndex to,TIndex from,entry_type factor = 1,TIndex startrow = 0);
00149 matrix &multiplyRowSelf(TIndex row,entry_type factor,TIndex startcol = 0);
00150 matrix &multiplyColumnSelf(TIndex column,entry_type factor,TIndex startrow = 0);
00151 matrix &swapRowSelf(TIndex row1,TIndex row2);
00152 matrix &swapColumnSelf(TIndex col1,TIndex col2);
00153
00154 enum TMatrixNorm {
00155 NORM_TOTAL,
00156 NORM_ROW_SUM,
00157 NORM_COLUMN_SUM,
00158 NORM_SCHUR,
00159 };
00160
00161 entry_type norm(TMatrixNorm norm = NORM_SCHUR) const;
00162 entry_type det() const;
00163 entry_type trace() const;
00164 entry_type diagonalProduct() const;
00165 matrix transposed() const;
00166 matrix inverted() const;
00167 matrix gauss(scalar_type pivot_threshold = 0,TSize *swapcount = NULL) const;
00168 matrix gaussJordan(scalar_type pivot_threshold = 0,TSize *swapcount = NULL) const;
00169 matrix linearSolve(matrix const &vec,scalar_type pivot_threshold = 0) const;
00170 matrix cholesky() const;
00171 void decomposeLR(matrix &l,matrix &r) const;
00172
00173
00174 matrix &normalize();
00175 matrix upperTriangleSolve(matrix const &vec) const;
00176 matrix lowerTriangleSolve(matrix const &vec) const;
00177
00178 void wipe(entry_type value = traits_type::zero);
00179 void setDimension(TSize height,TSize width);
00180
00181 void outMatrix(std::ostream &ostr,void (*item_formatter)(std::ostream &os,bool first,bool last) = NULL) const;
00182
00184 TSize getWidth() const {
00185 return Width;
00186 }
00188 TSize getHeight() const {
00189 return Height;
00190 }
00192 matrix getTransposed() const {
00193 return transposed();
00194 }
00196 matrix getInverted() const {
00197 return inverted();
00198 }
00200 matrix getGaussElim(scalar_type pivot_threshold = 0,TSize *swapcount = NULL) const {
00201 return gauss(pivot_threshold,swapcount);
00202 }
00204 matrix getGaussJordan(scalar_type pivot_threshold = 0,TSize *swapcount = NULL) const {
00205 return gaussJordan(pivot_threshold,swapcount);
00206 }
00208 matrix getCholesky() const {
00209 return cholesky();
00210 }
00212 void getLR(matrix &l,matrix &r) const {
00213 decomposeLR(l,r);
00214 }
00215
00216 protected:
00217 void setup(TSize height,TSize width);
00218 TSize getSize() const {
00219 return Width*Height;
00220 }
00221 TIndex getIndex(TIndex row,TIndex col) const {
00222 return Width*row+col;
00223 }
00224 };
00225 }
00226
00227
00228
00229
00230
00231 template <class T,class Traits>
00232 inline ixion::matrix<T,Traits> operator*(T scalar,ixion::matrix<T,Traits> const &mat);
00233 template <class T,class Traits>
00234 inline ixion::matrix<T,Traits> operator*(ixion::matrix<T,Traits> const &mat,T scalar);
00235 template <class T,class Traits>
00236 inline std::istream &operator>>(std::istream &istr,ixion::matrix<T,Traits> &mat);
00237 template <class T,class Traits>
00238 inline std::ostream &operator<<(std::ostream &ostr,ixion::matrix<T,Traits> const &mat);
00239
00240
00241
00242
00243
00244 template<class T,class Traits>
00245 template<class InputIterator>
00246 inline ixion::matrix<T,Traits>::matrix(TSize width,TSize height,InputIterator first) {
00247 setup(width,height);
00248 TSize size = getSize();
00249 iterator it = begin();
00250
00251 while (size--)
00252 *it++ = *first++;
00253 }
00254
00255
00256
00257
00258
00259 template <class T,class Traits>
00260 inline ixion::matrix<T,Traits> operator*(ixion::matrix<T,Traits>::scalar_type scalar,ixion::matrix<T,Traits> const &mat) {
00261 ixion::matrix<T,Traits> copy(mat);
00262 copy *= scalar;
00263 return copy;
00264 }
00265
00266
00267
00268
00269 template <class T,class Traits>
00270 inline ixion::matrix<T,Traits> operator*(ixion::matrix<T,Traits> const &mat,ixion::matrix<T,Traits>::scalar_type scalar) {
00271 ixion::matrix<T,Traits> copy(mat);
00272 copy *= scalar;
00273 return copy;
00274 }
00275
00276
00277
00278
00279 template <class T,class Traits>
00280 inline std::istream &operator>>(std::istream &istr,ixion::matrix<T,Traits> &mat) {
00281 ixion::TSize height,width;
00282 char c;
00283 istr >> height >> c >> width;
00284 mat.setDimension(height,width);
00285 for (ixion::TIndex y = 0;y < height;y++)
00286 for (ixion::TIndex x = 0;x < width;x++)
00287 istr >> mat(y,x);
00288 return istr;
00289 }
00290
00291
00292
00293
00294 template <class T,class Traits>
00295 inline std::ostream &operator<<(std::ostream &ostr,ixion::matrix<T,Traits> const &mat) {
00296 mat.outMatrix(ostr);
00297 return ostr;
00298 }
00299
00300
00301
00302
00303 #endif