]> git.donarmstrong.com Git - lilypond.git/blobdiff - flower/matrix.cc
release: 1.2.5
[lilypond.git] / flower / matrix.cc
index 7e1854827b223149729514389bb4d261e13f5833..b671238ac50527c1ebb2b289f544345eb4a18493 100644 (file)
 
   source file of the Flower Library
 
-  (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+  (c)  1997--1999 Han-Wen Nienhuys <hanwen@cs.uu.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
 {
-    Real r =0.0;
-    for (int i=0, j=0; dat->mult_ok(i,j); dat->mult_next(i,j))
-       r += sqr(dat->elem(i,j));
-    return sqrt(r);
+  Real r =0.0;
+  for (int i=0, j=0; dat_->mult_ok (i,j); dat_->mult_next (i,j))
+    r += sqr (dat_->elem (i,j));
+  return sqrt (r);
 }
 
 void
-Matrix::fill(Real r)
+Matrix::fill (Real r)
 {
-    for (int i=0, j=0; dat->mult_ok(i,j); dat->mult_next(i,j))
-       dat->elem(i,j)=r;
+  for (int i=0, j=0; dat_->mult_ok (i,j); dat_->mult_next (i,j))
+    dat_->elem (i,j)=r;
 }
 
 void
-Matrix::set_diag(Real r)
+Matrix::set_diag (Real r)
 {
-    for (int i=0, j=0; dat->mult_ok(i,j); dat->mult_next(i,j))   
-       dat->elem(i,j)=(i==j) ? r: 0.0;
+  for (int i=0, j=0; dat_->mult_ok (i,j); dat_->mult_next (i,j))         
+    dat_->elem (i,j)=(i==j) ? r: 0.0;
 }
 
 void
-Matrix::set_diag(Vector d)
+Matrix::set_diag (Vector d)
 {
-    for (int i=0, j=0; dat->mult_ok(i,j); dat->mult_next(i,j))   
-       dat->elem(i,j)=(i==j) ? d(i): 0.0;
+  for (int i=0, j=0; dat_->mult_ok (i,j); dat_->mult_next (i,j))         
+    dat_->elem (i,j)=(i==j) ? d (i): 0.0;
 }
 
 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))
-       dat->elem(i,j) += m(i,j);
+  assert (m.cols() == cols ());
+  assert (m.rows() == rows ());
+  for (int i=0, j=0; dat_->mult_ok (i,j); dat_->mult_next (i,j))
+    dat_->elem (i,j) += m (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))
-       dat->elem(i,j) -= m(i,j);
+  assert (m.cols() == cols ());
+  assert (m.rows() == rows ());
+  for (int i=0, j=0; dat_->mult_ok (i,j); dat_->mult_next (i,j))
+    dat_->elem (i,j) -= m (i,j);
 }
 
 
 void
 Matrix::operator*=(Real a)
 {
-    for (int i=0, j=0; dat->mult_ok(i,j); dat->mult_next(i,j))
-       dat->elem(i,j) *= a;
+  for (int i=0, j=0; dat_->mult_ok (i,j); dat_->mult_next (i,j))
+    dat_->elem (i,j) *= a;
 }
 
 void
 Matrix::operator=(Matrix const &m)
 {
-    if (&m == this)
-       return ;
-    delete dat;
-    dat = m.dat->clone();
+  if (&m == this)
+    return ;
+  delete dat_;
+  dat_ = new Full_storage (*m.dat_);
 }
 
+
 int
-Matrix::band_i()const
+Matrix::band_i () const
 {
-    if ( band_b() ) {
-       Diagonal_storage const * diag = (Diagonal_storage*) dat;
-       return diag->band_size_i();
-    }
-    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;
+  return dat_->band_i_;
 }
-    
-Matrix::Matrix(Matrix const &m)
+
+void
+Matrix::set_band ()
 {
-    m.OK();
-    
-    dat = m.dat->clone();
+  dat_->band_i_ = calc_band_i ();
 }
 
-
-Matrix::Matrix(int n, int m)
+int
+Matrix::calc_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)
 {
-    dat = Matrix_storage::get_full(n,m);
-    fill(0);
+  dat_ = new Full_storage (*m.dat_);
 }
 
-Matrix::Matrix(Matrix_storage*stor_p)
+
+Matrix::Matrix (int n, int m)
 {
-    dat = stor_p;
+  dat_ = new Full_storage(n,m);
+  fill (0);
 }
 
-Matrix::Matrix(int n)
+
+Matrix::Matrix (int n)
 {
-    dat = Matrix_storage::get_full(n,n);
-    fill(0);
+  dat_= new Full_storage (n,n);
+  fill (0);
 }
 
-Matrix::Matrix(Vector v, Vector w)
-{   
-    dat = Matrix_storage::get_full(v.dim(), w.dim());
-    for (int i=0, j=0; dat->mult_ok(i,j); dat->mult_next(i,j))
-       dat->elem(i,j)=v(i)*w(j);
+Matrix::Matrix (Vector v, Vector w)
+{
+  int n = v.dim();
+  int m = w.dim ();
+  dat_= new Full_storage (n,m);
+  for (int i=0; i < n; i++)
+    for (int j=0; j < m ; j++)
+      dat_->elem (i,j)=v (i)*w (j);
 }
 
 
 Vector
-Matrix::row(int k) const
+Matrix::row (int k) const
 {
-    int n=cols();
+  int n=cols();
 
-    
-    Vector v(n);
-    for(int i=0; i < n; i++)
-       v(i)=dat->elem(k,i);
+  
+  Vector v (n);
+  for (int i=0; i < n; i++)
+    v (i)=dat_->elem (k,i);
 
-    return v;
+  return v;
 }
 
 Vector
-Matrix::col(int k) const
+Matrix::col (int k) const
 {
-    int n=rows();
-    Vector v(n);
-    for(int i=0; i < n; i++)
-       v(i)=dat->elem(i,k);
-    return v;
+  int n=rows();
+  Vector v (n);
+  for (int i=0; i < n; i++)
+    v (i)=dat_->elem (i,k);
+  return v;
 }
 
 Vector
-Matrix::left_multiply(Vector const & v) const
+Matrix::left_multiply (Vector const & v) const
 {
-     Vector dest(v.dim());
-    assert(dat->cols()==v.dim());
-    for (int i=0, j=0; dat->mult_ok(i,j); dat->mult_next(i,j))
-       dest(i)+= dat->elem(j,i)*v(j);
-    return dest;
+  Vector dest (v.dim());
+  assert (dat_->cols()==v.dim ());
+  for (int i=0, j=0; dat_->mult_ok (i,j); dat_->mult_next (i,j))
+    dest (i)+= dat_->elem (j,i)*v (j);
+  return dest;
 }
 
 Vector
 Matrix::operator *(Vector const & v) const
 {
-    Vector dest(rows());
-    assert(dat->cols()==v.dim());
-    for (int i=0, j=0; dat->mult_ok(i,j); dat->mult_next(i,j))
-       dest(i)+= dat->elem(i,j)*v(j);
-    return dest;
+  Vector dest (rows());
+  assert (dat_->cols()==v.dim ());
+  for (int i=0, j=0; dat_->mult_ok (i,j); dat_->mult_next (i,j))
+    dest (i)+= dat_->elem (i,j)*v (j);
+  return dest;
 }
 
 Matrix
 operator /(Matrix const& m1,Real a)
 {
-    Matrix m(m1);
-    m /= a;
-    return  m;
+  Matrix m (m1);
+  m /= a;
+  return  m;
 }
 
 /*
   ugh. Only works for square matrices.
  */
 void
-Matrix::transpose()            // delegate to storage?
+Matrix::transpose()
 {
-#if 1
-    for (int i=0, j=0; dat->mult_ok(i,j); dat->mult_next(i,j)) {
-       if (i >= j)
-           continue;
-       Real r=dat->elem(i,j);
-       dat->elem(i,j) = dat->elem(j,i);
-       dat->elem(j,i)=r;
+  for (int i=0, j=0; dat_->mult_ok (i,j); dat_->mult_next (i,j)) 
+    {
+      if (i >= j)
+       continue;
+      Real r=dat_->elem (i,j);
+      dat_->elem (i,j) = dat_->elem (j,i);
+      dat_->elem (j,i)=r;
     }
-#endif
 }
 
 Matrix
 Matrix::operator-() const
 {
-    OK();
-    Matrix m(*this);
-    m*=-1.0;    
-    return m;
+  OK();
+  Matrix m (*this);
+  m*=-1.0;    
+  return m;
 }
 
 Matrix
 Matrix::transposed() const
 {
-    Matrix m(*this);
-    m.transpose();
-    return m;
+  Matrix m (*this);
+  m.transpose();
+  return m;
 }
 
 Matrix
 operator *(Matrix const &m1, Matrix const &m2)
 {
-    Matrix result(Matrix_storage::get_product_result(m1.dat, m2.dat));
-
-    result.set_product(m1,m2);
-    return result;
+  Matrix result (m1.rows (), m2.cols ());
+  result.set_product (m1,m2);
+  return result;
 }
 
+
+
 void
-Matrix::set_product(Matrix const &m1, Matrix const &m2)
+Matrix::set_product (Matrix const &m1, Matrix const &m2)
 {
-    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);
-        dat->mult_next(i,j)) {
+  assert (m1.cols()==m2.rows ());
+  assert (cols()==m2.cols () && rows ()==m1.rows ());
+  
+  for (int i=0; i < rows (); i++)
+    for (int j=0; j <  cols (); j++)
+      {
        Real r=0.0;
-       for (int k = 0; k < m1.cols(); k++)
+       for (int k = 0 >? i - m1.band_i () >? j - m2.band_i ();
+            k < m1.cols(); k++)
+         {
            r += m1(i,k)*m2(k,j);
-       dat->elem(i,j)=r;
-    }
+         }
+       dat_->elem (i,j)=r;
+      }
 }
 
 void
-Matrix::insert_row(Vector v, int k)
+Matrix::insert_row (Vector v, int k)
 {
-    int c = cols();
-    assert(v.dim()==cols());
-    dat->insert_row(k);
-    for (int j=0; j < c; j++)
-       dat->elem(k,j)=v(j);
+  int c = cols();
+  assert (v.dim()==cols ());
+  dat_->insert_row (k);
+  for (int j=0; j < c; j++)
+    dat_->elem (k,j)=v (j);
 }
 
 
 void
-Matrix::swap_columns(int c1, int c2)
+Matrix::swap_columns (int c1, int c2)
 {
-    assert(c1>=0&& c1 < cols()&&c2 < cols() && c2 >=0);
-    int r = rows();
-    for (int i=0; i< r; i++) {
-       Real r=dat->elem(i,c1);
-       dat->elem(i,c1) = dat->elem(i,c2);
-       dat->elem(i,c2)=r;
+  assert (c1>=0&& c1 < cols()&&c2 < cols () && c2 >=0);
+  int r = rows();
+  for (int i=0; i< r; i++) 
+    {
+      Real r=dat_->elem (i,c1);
+      dat_->elem (i,c1) = dat_->elem (i,c2);
+      dat_->elem (i,c2)=r;
     }
 }
 
 void
-Matrix::swap_rows(int c1, int c2)
+Matrix::swap_rows (int c1, int c2)
 {
-    assert(c1>=0&& c1 < rows()&&c2 < rows() && c2 >=0);
-    int c = cols();
-    for (int i=0; i< c; i++) {
-       Real r=dat->elem(c1,i);
-       dat->elem(c1,i) = dat->elem(c2,i);
-       dat->elem(c2,i)=r;
+  assert (c1>=0&& c1 < rows()&&c2 < rows () && c2 >=0);
+  int c = cols();
+  for (int i=0; i< c; i++) 
+    {
+      Real r=dat_->elem (c1,i);
+      dat_->elem (c1,i) = dat_->elem (c2,i);
+      dat_->elem (c2,i)=r;
     }
 }
 
@@ -310,9 +289,11 @@ Matrix::swap_rows(int c1, int c2)
 int
 Matrix::dim() const
 {
-    assert(cols() == rows());
-    return rows();
+  assert (cols() == rows ());
+  return rows();
 }
 
-
-
+Matrix::~Matrix ()
+{
+  delete dat_;
+}