00001 #ifndef Matrix_HEADER
00002 #define Matrix_HEADER
00003
00004 #ifdef HAVE_CONFIG_H
00005 # include <config.h>
00006 #endif
00007
00008 #include <boost/array.hpp>
00009 #include <utilities/foreach.h>
00010 #include "Point.h"
00011
00012 #if 0
00013 #define dprintf(...) printf(__VA_ARGS__);
00014 #else
00015 #define dprintf(...)
00016 #endif
00017
00018 namespace Geometry {
00019
00020 template <unsigned rows, unsigned cols>
00021 class Matrix {
00022
00023 static const unsigned n = rows * cols;
00024 boost::array<double, n> data_;
00025
00026 public:
00027 Matrix() { }
00028 Matrix(double value) {
00029 data_.assign(value);
00030 }
00031
00032 Matrix(const Point<rows>& p, const Point<cols>& q) {
00033 for(unsigned r = 0; r < rows; ++r) {
00034 for(unsigned c = 0; c < cols; ++c) {
00035 get(r, c) = p[r] * q[c];
00036 }
00037 }
00038 }
00039
00040 const double *column_major_array() const {
00041 return data_.c_array();
00042 }
00043 double *column_major_array() {
00044 return data_.c_array();
00045 }
00046
00047 double operator() (unsigned r, unsigned c) const {
00048 return data_[r * cols + c];
00049 }
00050 double& operator() (unsigned r, unsigned c) {
00051 return data_[r * cols + c];
00052 }
00053 double get(unsigned r, unsigned c) const {
00054 return data_[r * cols + c];
00055 }
00056 double& get(unsigned r, unsigned c) {
00057 return data_[r * cols + c];
00058 }
00059
00060 void operator+= (const Matrix& other) {
00061 for(unsigned i = 0; i < n; ++i) {
00062 data_[i] += other.data_[i];
00063 }
00064 }
00065 void operator-= (const Matrix& other) {
00066 for(unsigned i = 0; i < n; ++i) {
00067 data_[i] -= other.data_[i];
00068 }
00069 }
00070 void operator*= (double x) {
00071 for(unsigned i = 0; i < n; ++i) {
00072 data_[i] *= x;
00073 }
00074 }
00075 void operator/= (double x) {
00076 for(unsigned i = 0; i < n; ++i) {
00077 data_[i] /= x;
00078 }
00079 }
00080
00081
00082 Point<rows> operator * (const Point<cols>& p) const {
00083 Point<rows> q;
00084 for(unsigned i = 0; i < rows; ++i) {
00085 q[i] = 0.0;
00086 for(unsigned j = 0; j < cols; ++j) {
00087 q[i] += (*this)(i,j) * p[j];
00088 }
00089 }
00090 return q;
00091 }
00092
00093 void qd_print()
00094 {
00095 for(unsigned i = 0; i < rows; ++i) {
00096 for(unsigned j = 0; j < cols; ++j) {
00097 dprintf("%f ",get(i,j));
00098 }
00099 dprintf("\n");
00100 }
00101 return;
00102 }
00103
00104
00105
00106
00107
00108 template <unsigned newcols>
00109 Matrix<rows, newcols>
00110 operator * (const Matrix<cols, newcols>& other) {
00111 Matrix<rows, newcols> m;
00112 for(unsigned i = 0; i < newcols; ++i) {
00113 for(unsigned j = 0; j < rows; ++j) {
00114 double d = 0.0;
00115 for(unsigned k = 0; k < cols; ++k) {
00116 d += get(j, k) * other.get(i, k);
00117 }
00118 m(i, j) = d;
00119 }
00120 }
00121 return m;
00122 }
00123
00124 private:
00125 void largest_eigenvector(Matrix<rows, rows> M, Point<rows>& v) const {
00126
00127 enum { NSQUARE = 20 };
00128
00129 for (unsigned i = 0 ; i < NSQUARE; ++i) {
00130 M = M * M;
00131 double maxabs = 0.0;
00132 BOOST_FOREACH(double d, M.data_) {
00133 d = fabs(d);
00134 maxabs = maxabs > d ? maxabs : d;
00135 }
00136 if (maxabs != 0.0) {
00137 M /= maxabs;
00138 }
00139 }
00140
00141
00142 unsigned use_col = 0;
00143 for (unsigned c = 0; c < cols; ++c) {
00144 for(unsigned r = 0; r < rows; ++r) {
00145 if (M(r,c) != 0.0) {
00146 use_col = c;
00147 break;
00148 }
00149 }
00150 }
00151
00152
00153 for (unsigned r = 0; r < rows; ++r) {
00154 v[r] = M(r,use_col);
00155 }
00156 if (v.norm2() != 0.0) {
00157 v /= sqrt(v.norm2());
00158 }
00159 }
00160
00161
00162 public:
00168 template<unsigned k> void eigenvectors(boost::array<Point<rows>, k>& vectors) const {
00169 BOOST_STATIC_ASSERT(rows == cols);
00170
00171 Matrix<rows, rows> M = *this;
00172 for (unsigned eigen = 0; eigen < k; ++eigen) {
00173 largest_eigenvector(M, vectors[eigen]);
00174
00175 dprintf("Big EIV is %f %f %f\n",vectors[eigen][0],vectors[eigen][1],vectors[eigen][2]);
00176
00177
00178 const Point<rows>& v = vectors[eigen];
00179 double lambda = v.dot(M * v);
00180 assert(lambda != 0);
00181
00182 dprintf("L is %f\n",lambda);
00183
00184
00185 Matrix<rows,rows> vv(v, v);
00186 vv *= lambda;
00187 M -= vv;
00188
00189 dprintf("Lvv then M-Lvv\n");
00190 vv.qd_print();
00191 dprintf("----\n");
00192 M.qd_print();
00193 }
00194 }
00195
00196 };
00197
00198 }
00199
00200 #undef dprintf
00201 #endif