00001
00002
00003
00004
00005
00006
00007
00008 #ifndef IMPALGEBRA_MATRIX_2D_H
00009 #define IMPALGEBRA_MATRIX_2D_H
00010
00011
00012
00013 #include "MultiArray.h"
00014 #include "VectorD.h"
00015 #include "IMP/base_types.h"
00016 #include "IMP/exception.h"
00017 #include <IMP/VectorOfRefCounted.h>
00018 #include <complex>
00019
00020 IMPALGEBRA_BEGIN_NAMESPACE
00021
00022
00023
00024
00025
00026
00027 template<typename T>
00028 class Matrix2D: public MultiArray<T,2>
00029 {
00030 public:
00031 typedef boost::multi_array_types::index index;
00032 typedef MultiArray<T,2> MA2;
00033 typedef Matrix2D<T> This;
00034
00035
00036 Matrix2D() : MA2() {
00037 }
00038
00039
00040
00041
00042
00043
00044 Matrix2D(int Ydim, int Xdim) : MA2() {
00045 resize(Ydim, Xdim);
00046 }
00047
00048
00049 Matrix2D(const This& v) : MA2() {
00050 this->reshape(v);
00051 MA2::copy((MA2 &)v);
00052 }
00053
00054
00055
00056
00057
00058
00059 void resize(int Ydim, int Xdim) {
00060 typename This::extent_gen extents;
00061 MA2::resize(extents[Ydim][Xdim]);
00062 }
00063
00064
00065
00066
00067
00068 template<typename T1>
00069 void resize(const Matrix2D<T1>& m2) {
00070 this->resize(m2.shape()[0], m2.shape()[1]);
00071 }
00072
00073
00074
00075
00076
00077 template<typename T1>
00078 void reshape(const Matrix2D<T1>& v) {
00079 boost::array<index,2> shape,start;
00080 int dims=v.num_dimensions();
00081 for(int i=0;i<dims;i++) {
00082 shape[i]=v.shape()[i];
00083 start[i]=v.index_bases()[i];
00084 }
00085 resize(shape[0], shape[1]);
00086 MA2::reindex(start);
00087 }
00088
00089
00090 int get_number_of_rows() const {
00091 return (int)this->get_size(0);
00092 }
00093
00094
00095 int get_number_of_columns() const {
00096 return (int)this->get_size(1);
00097 }
00098
00099
00100
00101 This transpose() {
00102 This aux(get_number_of_columns(), get_number_of_rows());
00103 for (int j = 0;j < get_number_of_rows();j++) {
00104 for (int i = 0;i < get_number_of_columns();i++) {
00105 aux(i, j) = (*this)(j, i);
00106 }
00107 }
00108 return aux;
00109 }
00110
00111
00112 void set_zero() {
00113 this->init_zeros();
00114 }
00115
00116
00117 void set_identity() {
00118 IMP_INTERNAL_CHECK(is_square(), "the matrix must be square");
00119 this->init_zeros();
00120 for (int i = 0; i < get_number_of_rows(); i++) {
00121 (*this)(i,i)=1.;
00122 }
00123 }
00124
00125 void show(std::ostream &o=std::cout) const {
00126 for(int i=0;i<get_number_of_rows();i++) {
00127 for(int j=0;j<get_number_of_columns();j++) {
00128 o<<(*this)(i,j)<<" ";
00129 }
00130 o<<std::endl;
00131 }
00132 }
00133
00134
00135
00136
00137
00138 T& physical_get(const int j,const int i) const {
00139 if (0<=j && j<get_number_of_rows() && 0<=i && i<get_number_of_columns()) {
00140 return (*this)(j+this->get_start(0),i+this->get_start(1));
00141 } else {
00142 String msg = "Matri2D::physical_get: index out of range." ;
00143 throw ValueException(msg.c_str());
00144 }
00145 }
00146
00147
00148
00149
00150
00151
00152
00153 void physical_set(const int j,const int i,const T& val) {
00154 if (0<=j && j<get_number_of_rows() && 0<=i && i < get_number_of_columns()) {
00155 (*this)(j+this->get_start(0),i+this->get_start(1))=val;
00156 } else {
00157 String msg = "Matri2D::physical_set: index out of range." ;
00158 throw ValueException(msg.c_str());
00159 }
00160 }
00161
00162
00163
00164
00165
00166
00167
00168 void pad(This& padded,T val) {
00169 padded.resize(2*this->get_size(0),2*this->get_size(1));
00170
00171 padded.fill_with_value(val);
00172 std::vector<index> idx(2),idx_for_padded(2);
00173 while (internal::roll_inds(idx, this->shape(),this->index_bases())) {
00174 for(int i=0;i<2;i++) {
00175 idx_for_padded[i]=idx[i]+(int)this->get_size(i)/2;
00176 }
00177 padded(idx_for_padded)=(*this)(idx);
00178 }
00179 }
00180
00181
00182
00183
00184
00185
00186 void pad(This& padded) {
00187 double avg = this->compute_avg();
00188 this->pad(padded,avg);
00189 }
00190
00191
00192 template<typename T1>
00193 void cast_values(Matrix2D<T1> &out) {
00194 out.resize(*this);
00195 for(unsigned int i=0; i<this->num_elements(); i++) {
00196 out.data()[i] = (T1)this->data()[i];
00197 }
00198 }
00199
00200
00201
00202
00203
00204
00205
00206 T& operator()(int j, int i) const {
00207 if (this->get_start(0) <= j && j <= this->get_finish(0) &&
00208 this->get_start(1) <= i && i <= this->get_finish(1)) {
00209 return (T&)((*this)[j][i]);
00210 } else {
00211 String msg = "Matri2D::(): Index out of range." ;
00212 throw ValueException(msg.c_str());
00213 }
00214 }
00215
00216
00217
00218
00219
00220
00221 template<typename T1>
00222 T& operator()(T1& idx) const {
00223 return (T&)((*this)[idx[0]][idx[1]]);
00224 }
00225
00226 void operator=(const This& v) {
00227 this->reshape(v);
00228 MA2::copy((MA2 &)v);
00229 }
00230
00231
00232
00233
00234
00235 This operator+(const This& v)
00236 const {
00237 This result;
00238 result.resize(*this);
00239 internal::operate_arrays(*this, v, result, '+');
00240 return result;
00241 }
00242
00243
00244 This operator-(const This& v) const {
00245 This result;
00246 result.resize(*this);
00247 internal::operate_arrays(*this, v, result, '-');
00248 return result;
00249 }
00250
00251
00252 This operator*(const This& v) const {
00253 This result;
00254 result.resize(*this);
00255 internal::operate_arrays(*this, v, result, '*');
00256 return result;
00257 }
00258
00259
00260 This operator/(const This& v)
00261 const {
00262 This result;
00263 result.resize(*this);
00264 internal::operate_arrays(*this, v, result, '/');
00265 return result;
00266 }
00267
00268
00269 This operator+(const T& v) const {
00270 This result;
00271 result.resize(*this);
00272 internal::operate_array_and_scalar(*this, v, result, '+');
00273 return result;
00274 }
00275
00276
00277 This operator-(const T& v) const {
00278 This result;
00279 result.resize(*this);
00280 internal::operate_array_and_scalar(*this, v, result, '-');
00281 return result;
00282 }
00283
00284
00285 This operator*(const T& v) const {
00286 This result;
00287 result.resize(*this);
00288 internal::operate_array_and_scalar(*this, v, result, '*');
00289 return result;
00290 }
00291
00292
00293 This operator/(const T& v) const {
00294 This result;
00295 result.resize(*this);
00296 internal::operate_array_and_scalar(*this, v, result, '/');
00297 return result;
00298 }
00299
00300
00301
00302 This& operator+=(const This& v) {
00303 internal::operate_arrays(*this, v, *this, '+');
00304 return *this;
00305 }
00306
00307
00308 This& operator-=(const This& v) {
00309 internal::operate_arrays(*this, v, *this, '-');
00310 return *this;
00311 }
00312
00313
00314 This& operator*=(const This& v) {
00315 internal::operate_arrays(*this, v, *this, '*');
00316 return *this;
00317 }
00318
00319
00320 This& operator/=(const This& v) {
00321 internal::operate_arrays(*this, v, *this, '/');
00322 return *this;
00323 }
00324
00325
00326 This& operator+=(const T& v) {
00327 internal::operate_array_and_scalar(*this, v, *this, '+');
00328 return *this;
00329 }
00330
00331
00332 This& operator-=(const T& v) {
00333 internal::operate_array_and_scalar(*this, v, *this, '-');
00334 return *this;
00335 }
00336
00337
00338 This& operator*=(const T& v) {
00339 internal::operate_array_and_scalar(*this, v, *this, '*');
00340 return *this;
00341 }
00342
00343
00344 This& operator/=(const T& v) {
00345 internal::operate_array_and_scalar(*this, v, *this, '/');
00346 return *this;
00347 }
00348
00349
00350 friend This operator+(const T& X, const This& a1) {
00351 This result;
00352 result.resize(a1);
00353 internal::operate_scalar_and_array(X, a1, result, '+');
00354 return result;
00355 }
00356
00357
00358 friend This operator-(const T& X, const This& a1) {
00359 This result;
00360 result.resize(a1);
00361 internal::operate_scalar_and_array(X, a1, result, '-');
00362 return result;
00363 }
00364
00365
00366 friend This operator*(const T& X,const This& a1) {
00367 This result;
00368 result.resize(a1);
00369 internal::operate_scalar_and_array(X, a1, result, '*');
00370 return result;
00371 }
00372
00373
00374 friend This operator/(const T& X, const This& a1) {
00375 This result;
00376 result.resize(a1);
00377 internal::operate_scalar_and_array(X, a1, result, '/');
00378 return result;
00379 }
00380
00381
00382 double det() const {
00383 IMP_INTERNAL_CHECK(get_number_of_rows() == 2,"works only for 2x2 matrices");
00384 IMP_INTERNAL_CHECK(get_number_of_columns() == 2,
00385 "works only for 2x2 matrices");
00386 return (double)(physical_get(0,0)*physical_get(1,1) -
00387 physical_get(1,0)*physical_get(0,1));
00388 }
00389
00390 bool is_square() const {
00391 return (get_number_of_rows() == get_number_of_columns());
00392 }
00393
00394 protected:
00395 };
00396
00397
00398 typedef Matrix2D<int> Matrix2D_i;
00399 typedef Matrix2D<double> Matrix2D_d;
00400 typedef Matrix2D< std::complex<double> > Matrix2D_c;
00401
00402
00403 typedef VectorOfRefCounted<Matrix2D_d *> Matrix2Ds_d;
00404
00405 typedef VectorOfRefCounted<Matrix2D_c *> Matrix2Ds_c;
00406
00407 IMPALGEBRA_END_NAMESPACE
00408
00409
00410
00411 #endif