00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 #include "matrix.h"
00077 #include <string.h>
00078 #include <math.h>
00079
00080 namespace matrix {
00081
00082 #define COMPARE_EPS 1e-12
00083 const int T=0xFF;
00084
00085 Matrix::Matrix(const Matrix& c)
00086 : m(0), n(0), buffersize(0), data(0){
00087 copy(c);
00088 }
00089
00090 Matrix::Matrix(unsigned short _m, unsigned short _n, const D* _data )
00091 : m(_m), n(_n), buffersize(0), data(0) {
00092 allocate();
00093 set(_data);
00094 };
00095
00096
00097 void Matrix::allocate() {
00098 if((unsigned)m*n > buffersize){
00099 buffersize=m*n;
00100 if(data) { delete[] data; }
00101 data = new D[buffersize];
00102 assert(data);
00103 }
00104 }
00105
00106
00107
00108
00109 Matrix Matrix::row(unsigned short index) const{
00110 assert(index < m);
00111 Matrix result(1,n,data+(index*n));
00112 return result;
00113 }
00114
00115 Matrix Matrix::column(unsigned short index) const {
00116 assert(index < n);
00117 Matrix result(m,1);
00118 for(int i=0; i<m; i++){
00119 result.val(i,0) = val(i,index);
00120 }
00121 return result;
00122 }
00123
00124
00125 void Matrix::set(unsigned short _m, unsigned short _n, const D* _data ){
00126 m=_m;
00127 n=_n;
00128 allocate();
00129 set(_data);
00130 }
00131
00132 void Matrix::set(const D* _data){
00133 if (_data)
00134 memcpy(data,_data, m*n*sizeof(D));
00135 else toZero();
00136 }
00137
00138 int Matrix::convertToBuffer(D* buffer, unsigned int len) const {
00139 if(buffer && data){
00140 unsigned int minlen = (len < (unsigned)m*n) ? len : m*n;
00141 memcpy(buffer, data, sizeof(D) * minlen);
00142 return minlen;
00143 }
00144 return 0;
00145 }
00146
00147 list<D> Matrix::convertToList() const {
00148 list<D> l;
00149 if(data){
00150 for(int i=0; i < m*n; i++){
00151 l.push_back(data[i]);
00152 }
00153 }
00154 return l;
00155 }
00156
00157
00158
00159
00160
00161
00162 void Matrix::toTranspose(){
00163 assert(buffersize > 0);
00164 if(m!=1 && n!=1){
00165 double* newdata = new D[buffersize];
00166 for(unsigned short i=0; i < m; i++){
00167 for(unsigned short j=0; j < n; j++){
00168 newdata[j*m+i]=data[i*n+j];
00169 }
00170 }
00171 delete[] data;
00172 data=newdata;
00173 }
00174
00175 unsigned short t = m;
00176 m=n;
00177 n=t;
00178 }
00179
00180 void Matrix::toZero(){
00181 memset(data, D_Zero, m*n*sizeof(D));
00182 }
00183
00184 void Matrix::toId(){
00185 toZero();
00186 unsigned short smallerdim = m < n ? m : n;
00187 for(unsigned short i=0; i < smallerdim; i++){
00188 val(i,i)=D_One;
00189 }
00190 }
00191
00192 void Matrix::add(const Matrix& a,const Matrix& b){
00193 assert(a.m==b.m && a.n==b.n);
00194 copy(a);
00195 toSum(b);
00196 }
00197
00198 void Matrix::sub(const Matrix& a,const Matrix& b){
00199 assert(a.m==b.m && a.n==b.n);
00200 copy(a);
00201 toDiff(b);
00202 }
00203
00204 void Matrix::mult(const Matrix& a,const Matrix& b){
00205 assert(a.n==b.m);
00206 m=a.m;
00207 n=b.n;
00208 unsigned short interdim = a.n;
00209 allocate();
00210 D d;
00211 for(unsigned short i=0; i < m; i++){
00212 for(unsigned short j=0; j < n; j++){
00213 d=0;
00214 for(unsigned short k=0; k < interdim; k++){
00215 d+=a.val(i,k)*b.val(k,j);
00216 }
00217 val(i,j)=d;
00218 }
00219 }
00220 }
00221
00222 void Matrix::mult(const Matrix& a, const D& fac){
00223 m=a.m;
00224 n=a.n;
00225 allocate();
00226 for(unsigned short i=0; i<m*n; i++){
00227 data[i]=a.data[i]*fac;
00228 }
00229 }
00230
00231 void Matrix::toMult(const D& fac){
00232 for(unsigned short i=0; i<m*n; i++){
00233 data[i]*=fac;
00234 }
00235 }
00236
00237
00238
00239
00240
00241
00242 void Matrix::toExp (int exponent) {
00243 switch(exponent){
00244 case -1:
00245 if(m==1) val(0,0) = 1/val(0,0);
00246 else if(m==2) invert2x2();
00247 #ifndef AVR
00248 else if(m==3) invert3x3();
00249 else invertnonzero();
00250 #endif
00251 break;
00252 case 0:
00253 toId();
00254 break;
00255 case 1:
00256 break;
00257 case T:
00258 toTranspose();
00259 break;
00260 default:
00261 assert("Should not be reached" == 0);
00262 break;
00263 }
00264 }
00265
00266 void Matrix::toMap(D (*fun)(D)){
00267 unsigned int len = m*n;
00268 for(unsigned short i=0; i < len; i++){
00269 data[i]=fun(data[i]);
00270 }
00271 }
00272
00273 Matrix Matrix::map(D (*fun)(D)) const {
00274 Matrix result(*this);
00275 result.toMap(fun);
00276 return result;
00277 }
00278
00279 void Matrix::toMapP(void* param, D (*fun)(void*, D)){
00280 unsigned int len = m*n;
00281 for(unsigned short i=0; i < len; i++){
00282 data[i]=fun(param, data[i]);
00283 }
00284 }
00285
00286 Matrix Matrix::mapP(void* param, D (*fun)(void*, D)) const {
00287 Matrix result(*this);
00288 result.toMapP(param,fun);
00289 return result;
00290 }
00291
00292 void Matrix::toMultrowwise(const Matrix& factors){
00293 assert(m == factors.m && factors.n == 1);
00294 for(unsigned int i = 0; i < m; i++){
00295 for (unsigned int j = 0; j < n; j++){
00296 val(i,j) *= factors.val(i,0);
00297 }
00298 }
00299 }
00300
00301 void Matrix::toMultcolwise(const Matrix& factors){
00302 assert(n == factors.m && factors.n == 1);
00303 for(unsigned int i = 0; i < m; i++){
00304 for (unsigned int j = 0; j < n; j++){
00305 val(i,j) *= factors.val(j,0);
00306 }
00307 }
00308 }
00309
00310 void Matrix::toAbove(const Matrix& a){
00311 assert(a.n == this->n);
00312 data = (D*)realloc(data, sizeof(D) * (this->m * this->n + a.n * a.m));
00313 memcpy(data+this->m * this->n, a.data, sizeof(D) * (a.n * a.m));
00314 this->m+=a.m;
00315 }
00316
00317
00318 Matrix Matrix::multrowwise(const Matrix& factors) const {
00319 Matrix result(*this);
00320 result.toMultrowwise(factors);
00321 return result;
00322 }
00323
00324 Matrix Matrix::multcolwise(const Matrix& factors) const{
00325 Matrix result(*this);
00326 result.toMultcolwise(factors);
00327 return result;
00328 }
00329
00330
00331 Matrix Matrix::multMT() const {
00332 assert(m != 0 && n != 0);
00333 Matrix result(m,m);
00334 D d;
00335 for(unsigned short i=0; i < m; i++){
00336 for(unsigned short j=0; j < m; j++){
00337 d=0;
00338 for(unsigned short k=0; k < n; k++){
00339 d+=val(i,k) * val(j,k);
00340 }
00341 result.val(i,j)=d;
00342 }
00343 }
00344 return result;
00345 }
00346
00347
00348 Matrix Matrix::multTM() const {
00349 assert(m != 0 && n != 0);
00350 Matrix result(n,n);
00351 D d;
00352 for(unsigned short i=0; i < n; i++){
00353 for(unsigned short j=0; j < n; j++){
00354 d=0;
00355 for(unsigned short k=0; k < m; k++){
00356 d+=val(k,i) * val(k,j);
00357 }
00358 result.val(i,j)=d;
00359 }
00360 }
00361 return result;
00362 }
00363
00364
00365 D Matrix::elementProduct() const {
00366 D rv=1;
00367 for(unsigned short i=0; i<m*n; i++){
00368 rv*=data[i];
00369 }
00370 return rv;
00371 }
00372
00373
00374 D Matrix::elementSum() const {
00375 D rv=0;
00376 for(unsigned short i=0; i<m*n; i++){
00377 rv+=data[i];
00378 }
00379 return rv;
00380 }
00381
00382
00383 Matrix Matrix::above(const Matrix& b) const {
00384 Matrix r(*this);
00385 r.toAbove(b);
00386 return r;
00387 }
00388
00389
00390 #ifndef AVR
00391
00392
00393 void Matrix::invertnonzero() {
00394 assert(m==n && m>1);
00395
00396 for (unsigned int i=1; i < m; i++) data[i] /= data[0];
00397 for (unsigned int i=1; i < m; i++) {
00398 for (unsigned int j=i; j < m; j++) {
00399 D sum = 0.0;
00400 for (unsigned int k = 0; k < i; k++)
00401 sum += val(j,k) * val(k,i);
00402 val(j,i) -= sum;
00403 }
00404 if (i == (unsigned) m-1) continue;
00405 for (unsigned int j=i+1; j < m; j++) {
00406 D sum = 0.0;
00407 for (unsigned int k = 0; k < i; k++)
00408 sum += val(i,k)*val(k,j);
00409 val(i,j) = (val(i,j)-sum) / val(i,i);
00410 }
00411 }
00412 for (unsigned int i = 0; i < m; i++ )
00413 for (unsigned int j = i; j < m; j++ ) {
00414 D x = 1.0;
00415 if ( i != j ) {
00416 x = 0.0;
00417 for (unsigned int k = i; k < j; k++ )
00418 x -= val(j,k)*val(k,i);
00419 }
00420 val(j,i) = x / val(j,j);
00421 }
00422 for (unsigned int i = 0; i < m; i++ )
00423 for (unsigned int j = i; j < m; j++ ) {
00424 if ( i == j ) continue;
00425 D sum = 0.0;
00426 for (unsigned int k = i; k < j; k++ )
00427 sum += val(k,j)*( (i==k) ? 1.0 : val(i,k) );
00428 val(i,j) = -sum;
00429 }
00430 for (unsigned int i = 0; i < m; i++ )
00431 for (unsigned int j = 0; j < m; j++ ) {
00432 D sum = 0.0;
00433 for (unsigned int k = ((i>j)?i:j); k < m; k++ )
00434 sum += ((j==k)?1.0:val(j,k))*val(k,i);
00435 val(j,i) = sum;
00436 }
00437 };
00438 #endif
00439
00440
00441 void Matrix::invert2x2(){
00442 assert(m==n && m==2);
00443
00444 D detQ = data[0] * data[3] - data[1] * data[2];
00445 D tmp = data[0];
00446 data[0] = data[3] / detQ;
00447 data[3] = tmp / detQ;
00448 data[1] /= -detQ;
00449 data[2] /= -detQ;
00450 }
00451
00452 #ifndef AVR
00453 void Matrix::invert3x3(){
00454 assert(m==n && m==3);
00455 D Q_adjoint[3][3];
00456 D detQ=0;
00457
00458 Q_adjoint[0][0]=val(1,1)*val(2,2)-val(1,2)*val(2,1) ;
00459 Q_adjoint[0][1]=(val(1,2)*val(2,0)-val(1,0)*val(2,2)) ;
00460 Q_adjoint[0][2]=val(1,0)*val(2,1)-val(1,1)*val(2,0) ;
00461 Q_adjoint[1][0]=(val(2,1)*val(0,2)-val(0,1)*val(2,2)) ;
00462 Q_adjoint[1][1]=val(0,0)*val(2,2)-val(0,2)*val(2,0) ;
00463 Q_adjoint[1][2]=(val(0,1)*val(2,0)-val(0,0)*val(2,1)) ;
00464 Q_adjoint[2][0]=val(0,1)*val(1,2)-val(1,1)*val(0,2) ;
00465 Q_adjoint[2][1]=(val(1,0)*val(0,2)-val(0,0)*val(1,2)) ;
00466 Q_adjoint[2][2]=val(0,0)*val(1,1)-val(0,1)*val(1,0) ;
00467 detQ=val(0,0)*Q_adjoint[0][0]+val(0,1)*Q_adjoint[0][1]+val(0,2)*Q_adjoint[0][2] ;
00468 for(int i=0; i<3; i++){
00469 for(int j=0; j<3; j++) {
00470 val(i,j)=(Q_adjoint[j][i])/detQ ;
00471 }
00472 }
00473 }
00474 #endif
00475
00476
00477
00478
00479 Matrix Matrix::operator + (const Matrix& sum) const {
00480 Matrix result;
00481 result.add(*this, sum);
00482 return result;
00483 }
00484 Matrix Matrix::operator - (const Matrix& sum) const {
00485 Matrix result;
00486 result.sub(*this, sum);
00487 return result;
00488 }
00489
00490 Matrix Matrix::operator * (const Matrix& fac) const {
00491 Matrix result;
00492 result.mult(*this, fac);
00493 return result;
00494 }
00495
00496 Matrix Matrix::operator * (const D& scalar) const {
00497 Matrix result;
00498 result.mult(*this, scalar);
00499 return result;
00500 }
00501
00502
00503
00504
00505
00506 Matrix Matrix::operator ^ (int exponent) const {
00507 Matrix result(*this);
00508 result.toExp(exponent);
00509 return result;
00510 }
00511
00512 #ifndef AVR
00513 bool Matrix::operator == (const Matrix& c) const {
00514 if(m!=c.m || n!=c.n) return false;
00515 D* p1=data;
00516 D* p2=c.data;
00517 unsigned int len = m*n;
00518 for(unsigned int i = 0; i < len; i++){
00519 if(fabs(*p1 - *p2) > COMPARE_EPS) {
00520 return false;
00521 }
00522 p1++; p2++;
00523 }
00524 return true;
00525 }
00526
00527 ostream& operator<<(ostream& str, const Matrix& mat){
00528 if (mat.m==0 || mat.n==0) return str << "0";
00529 else {
00530 str << mat.m << "x" << mat.n << " (\n";
00531 for(int i=0; i < mat.m; i++){
00532 for(int j=0; j < mat.n; j++){
00533 str << mat.val(i,j) << "\t";
00534 }
00535 str << endl;
00536 }
00537 }
00538 return str << ")\n";
00539 }
00540 #endif
00541
00542 }
00543
00544 #include "matrix.tests.cpp"