/// width of matrix
virtual int cols() const = 0;
-
+
+ /// size if square
+ virtual int dim() const =0;
/** set the size. contents lost.
PRE
i >=0, j>=0
*/
- virtual void set_size(int rows, int cols) = 0;
+ virtual void set_size(int rows, int cols) ;
+
/**set the size to square dimen. contents lost
PRE
i>=0
*/
- virtual void set_size(int i) = 0;
+ virtual void set_size(int i) ;
/**set the size to i.
keep contents. If enlarged contents unspecified
virtual void resize(int i) = 0;
- /**
+ /**
access an element.
Generate an errormessage, if this happens
virtual Real& elem(int i,int j) = 0;
/// access a element, no modify
- virtual Real const & elem(int i, int j) const = 0;
+ virtual Real elem(int i, int j) const = 0;
- virtual Array<Real> row(int i) const = 0;
- virtual Array<Real> column(int j) const = 0;
+ virtual Array<Real> row(int i) const ;
+ virtual Array<Real> column(int j) const;
/**
virtual void delete_row(int k)=0;
virtual void delete_column(int k)=0;
virtual ~Matrix_storage() { }
- virtual Matrix_storage *clone()=0;
+ virtual Matrix_storage *clone()const=0;
*/
virtual void mult_next(int &i, int &j) const = 0;
-/**
+ /**
valid matrix entry. return false if at end of row
*/
virtual bool trans_ok(int i, int j) const=0;
*/
virtual void trans_next(int &i, int &j) const = 0;
+
/// generate a "Full_storage" matrix
static Matrix_storage *get_full(int n, int m);
-
-
+ static void set_band(Matrix_storage*&, int band);
+ static void set_full(Matrix_storage*&);
virtual bool try_right_multiply(Matrix_storage *dest,
- const Matrix_storage *fact) ;
+ const Matrix_storage *fact)const ;
/**
RTTI.
*/
- NAME_MEMBERS();
-};
-
+ DECLARE_MY_RUNTIME_TYPEINFO;
+
+ static Matrix_storage* get_product_result(Matrix_storage *left,
+ Matrix_storage *right);
+
+
+ static void set_addition_result(
+ Matrix_storage *&dat, Matrix_storage *right);
+ static void set_product_result(
+ Matrix_storage*&dest, Matrix_storage*left, Matrix_storage*right);
+};
-inline bool
-Matrix_storage::try_right_multiply(Matrix_storage *,
- const Matrix_storage *)
-{
- return false;
-}
#endif // MATRIX_STORAGE_HH
+/*
+ matrix.cc -- implement Matrix
+
+ source file of the Flower Library
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
#include "matrix.hh"
+#include "full-storage.hh"
+#include "diagonal-storage.hh"
+
+bool
+Matrix::band_b()const
+{
+ return dat->is_type_b( Diagonal_storage::static_name());
+}
+
+void
+Matrix::set_full() const
+{
+ if ( dat->name() != Full_storage::static_name()) {
+ Matrix_storage::set_full( ((Matrix*)this)->dat );
+ }
+}
+
+void
+Matrix::try_set_band()const
+{
+ if (band_b())
+ return;
+
+ int b = band_i();
+ if ( b > dim()/2)
+ return;
+ // it only looks constant
+ Matrix*self = (Matrix*)this;
+ Matrix_storage::set_band(self->dat,b);
+}
Real
Matrix::norm() const
void
Matrix::operator+=(Matrix const &m)
{
+ Matrix_storage::set_addition_result(dat, m.dat);
assert(m.cols() == cols());
assert(m.rows() == rows());
for (int i=0, j=0; dat->mult_ok(i,j); dat->mult_next(i,j))
void
Matrix::operator-=(Matrix const &m)
{
+ Matrix_storage::set_addition_result(dat, m.dat);
assert(m.cols() == cols());
assert(m.rows() == rows());
for (int i=0, j=0; dat->mult_ok(i,j); dat->mult_next(i,j))
delete dat;
dat = m.dat->clone();
}
+
+int
+Matrix::band_i()const
+{
+ int starty = dim();
+ while (starty >= 0 ) {
+ for ( int i = starty, j = 0; i < dim(); i++, j++ )
+ if (dat->elem( i,j ))
+ goto gotcha;
+ for ( int i=0, j = starty; j < dim(); i++,j++)
+ if (dat->elem(i,j))
+ goto gotcha;
+ starty --;
+ }
+gotcha:
+ return starty;
+}
Matrix::Matrix(Matrix const &m)
{
fill(0);
}
+Matrix::Matrix(Matrix_storage*stor_p)
+{
+ dat = stor_p;
+}
+
Matrix::Matrix(int n)
{
dat = Matrix_storage::get_full(n,n);
return m;
}
-
-/* should do something smarter: bandmatrix * bandmatrix is also banded matrix. */
Matrix
operator *(Matrix const &m1, Matrix const &m2)
{
- Matrix result(m1.rows(), m2.cols());
+ Matrix result(Matrix_storage::get_product_result(m1.dat, m2.dat));
+
result.set_product(m1,m2);
return result;
}
{
assert(m1.cols()==m2.rows());
assert(cols()==m2.cols() && rows()==m1.rows());
-
+
if (m1.dat->try_right_multiply(dat, m2.dat))
return;
for (int i=0, j=0; dat->mult_ok(i,j);
return rows();
}
+
+