00001 #include "linalg.h"
00002 #include "util.h"
00003 #include "qscr.h"
00004 #include <sstream>
00005 #include <iomanip>
00006 #include <cassert>
00007 #include <cstring>
00008 #include <cstdlib>
00009 #include <cmath>
00010
00011
00012 matrix matrix::addcolumns()
00013 {
00014 long i,j;
00015 matrix B(rows);
00016 for(i=0;i<=rows-1;i++)
00017 {
00018 for(j=0;j<=columns-1;j++)
00019 B.A[i][0] += A[i][j];
00020 }
00021 return(B);
00022 }
00023
00024 matrix matrix::getrow(long i) const
00025 {
00026 long j;
00027 matrix B(1,columns);
00028 for (j=0; j<=columns-1;j++)
00029 B.A[0][j] = A[i][j];
00030 return(B);
00031 }
00032
00033 matrix matrix::getcolumn(long i) const
00034 {
00035 long j;
00036 matrix B(rows);
00037 for (j=0; j<=rows-1; j++)
00038 B.A[j][0] = A[j][i];
00039 return(B);
00040 }
00041
00042 void matrix::setrow(const matrix &B, long i)
00043 {
00044 long j;
00045 if (columns != B.columns)
00046 error("Wrong dimensions in matrix setrow \n");
00047 for (j=0; j<=columns-1; j++)
00048 A[i][j] = B.A[0][j];
00049 }
00050
00051 void matrix::setcolumn(const matrix &B, long i)
00052 {
00053 long j;
00054 if (rows != B.rows)
00055 error("Wrong dimensions in matrix setcolumn \n");
00056 for (j=0; j<=rows-1; j++)
00057 A[j][i] = B.A[j][0];
00058 }
00059
00060 long matrix::operator==(const matrix &B)
00061 {
00062 long i,j,eq=1;
00063 if ((rows != B.rows) & (columns != B.columns))
00064 error("Wrong dimensions in matrix equal \n");
00065 else
00066 {
00067 for(i=0; (i<=rows-1) & eq; i++)
00068 {
00069 for(j=0; (j<=columns-1) & eq; j++)
00070 eq = (A[i][j] == B.A[i][j]);
00071 }
00072 }
00073 return(eq);
00074 }
00075
00076 void matrix::print() const
00077 {
00078 long i,j;
00079
00080 for(i=0;i<=rows-1;i++)
00081 {
00082 for(j=0;j<=columns-1;j++) {
00083 std::string ss = numStr(A[i][j]) + " ";
00084 qaddstr(ss.c_str());
00085 }
00086 qinsertln();
00087
00088
00089 }
00090 }
00091
00092 void matrix::stdprint() const
00093 {
00094 long i,j;
00095 std::cerr << "[";
00096 for(i=0;i<=rows-1;i++)
00097 {
00098 for(j=0;j<=columns-1;j++) {
00099 std::cerr << A[i][j];
00100 if (j<columns-1)
00101 std::cerr << " ";
00102 }
00103 if (i<rows-1)
00104 std::cerr << ";" << std::endl;
00105 }
00106 std::cerr << "]";
00107 }
00108
00109
00110
00111 matrix matrix::operator*(const double &x)
00112 {
00113 long i,j;
00114 matrix C(rows,columns);
00115 for(i=0;i <= C.rows-1; i++)
00116 {
00117 for(j=0; j<=C.columns-1;j++)
00118 {
00119 C.A[i][j] = x*A[i][j];
00120 }
00121 }
00122 return(C);
00123 }
00124
00125
00126 matrix matrix::operator*(const matrix &B)
00127 {
00128 long i,j,k;
00129 matrix C(rows,B.columns);
00130 if (columns != B.rows)
00131 error("Wrong dimensions in matrix multiplication \n");
00132 else
00133 {
00134 for(i=0;i <= C.rows-1; i++)
00135 {
00136 for(j=0; j<=C.columns-1;j++)
00137 {
00138 for(k=0;k<=columns-1;k++)
00139 C.A[i][j] += A[i][k]*B.A[k][j];
00140 }
00141 }
00142 }
00143 return(C);
00144 }
00145
00146 matrix matrix::trans()
00147 {
00148 long i,j;
00149 matrix B(columns,rows);
00150 for (i=0;i<=columns-1;i++)
00151 {
00152 for(j=0;j<=rows-1;j++)
00153 B.A[i][j] = A[j][i];
00154 }
00155 return(B);
00156 }
00157
00158 matrix matrix::operator+(const matrix &B)
00159 {
00160 long i,j;
00161 matrix C(rows,columns);
00162 if ((rows != B.rows) & (columns != B.columns))
00163 error("Wrong dimensions in matrix plus \n");
00164 else
00165 {
00166 for(i=0;i <= rows-1; i++)
00167 {
00168 for(j=0; j<=columns-1;j++)
00169 C.A[i][j] = A[i][j] + B.A[i][j];
00170 }
00171 }
00172 return(C);
00173 }
00174
00175 matrix matrix::operator-(const matrix &B)
00176 {
00177 long i,j;
00178 matrix C(rows,columns);
00179 if ((rows != B.rows) & (columns != B.columns))
00180 error("Wrong dimensions in matrix minus \n");
00181 else
00182 {
00183 for(i=0;i <= rows-1; i++)
00184 {
00185 for(j=0; j<=columns-1;j++)
00186 C.A[i][j] = A[i][j] - B.A[i][j];
00187 }
00188 }
00189 return(C);
00190 }
00191
00192 double matrix::twonorm()
00193 {
00194 long i,j;
00195 double norm=0;
00196 for(i=0;i<=rows-1;i++)
00197 {
00198 for(j=0;j<=columns-1;j++)
00199 norm += A[i][j]*A[i][j];
00200 }
00201 norm = sqrt(norm);
00202 return(norm);
00203 }
00204
00205 double matrix::onenorm()
00206 {
00207 long i,j;
00208 double norm=0;
00209 for(i=0;i<=rows-1;i++)
00210 {
00211 for(j=0;j<=columns-1;j++)
00212 norm += num(A[i][j]);
00213 }
00214 return(norm);
00215 }
00216
00217 safevector<double> matrix::mean() const {
00218 safevector<double> m(columns);
00219 for (long s=0; s<columns; s++) {
00220 double sum = 0;
00221 for (long r=0; r<rows; r++) {
00222 sum += A[r][s];
00223 }
00224 m[s] = sum/(double)rows;
00225 }
00226 return m;
00227 }
00228
00229 safevector<double> matrix::var() const {
00230 safevector<double> mu = mean();
00231 safevector<double> v(columns);
00232 for (long s=0; s<columns; s++) {
00233 double sum = 0;
00234 for (long r=0; r<rows; r++) {
00235 double xe = A[r][s]-mu[s];
00236 sum += xe*xe;
00237 }
00238 v[s] = sum/((double)rows-1);
00239 }
00240 return v;
00241 }
00242
00243 matrix matrix::covar() const {
00244 safevector <double> m = mean();
00245 matrix res(columns, columns);
00246 for (int x=0; x<columns; x++) {
00247 for (int y=x; y<columns; y++) {
00248 double sum = 0;
00249 for (int i=0; i<rows; i++) {
00250 sum += (A[i][x]-m[x])*(A[i][y]-m[y]);
00251 }
00252 double val = sum/(double)(rows-1);
00253 res.set(val,x,y);
00254 res.set(val,y,x);
00255 }
00256 }
00257 return res;
00258 }
00259
00260
00261 matrix matrix::inv()
00262 {
00263 long *indxc =new long[rows];
00264 long *indxr = new long[rows];
00265 long *ipiv = new long[rows];
00266 long i, icol = 0, irow = 0, j, k, l, ll;
00267 double big, dum, pivinv;
00268 matrix B(rows,columns);
00269
00270 for(i=0;i<=rows-1;i++)
00271 {
00272 indxc[i]=0;
00273 indxr[i]=0;
00274 ipiv[i]=0;
00275 }
00276
00277 if (columns != rows)
00278 error("Cannot invert non-square matrix \n");
00279 else
00280 for(i=0;i<=rows-1;i++)
00281 {
00282 for(j=0;j<=columns-1;j++)
00283 B.A[i][j] = A[i][j];
00284 }
00285
00286
00287 for (i=0;i<=columns-1;i++)
00288 {
00289 big = 0.0;
00290 for (j=0;j<=rows-1;j++)
00291 {
00292 if (ipiv[j] != 1)
00293 for (k=0;k<=columns-1;k++)
00294 {
00295 if (ipiv[k] == 0)
00296 {
00297 if (fabs(B.A[j][k]) >=big)
00298 {
00299 big = fabs(B.A[j][k]);
00300 irow = j;
00301 icol = k;
00302 }
00303 }
00304 else if (ipiv[k] > 1) error("inv: Singular Matrix-1");
00305 }
00306 }
00307 ++(ipiv[icol]);
00308 if (irow != icol)
00309 {
00310 for (l=0;l<=columns-1;l++) B.swap(irow,icol);
00311 }
00312 indxr[i] = irow;
00313 indxc[i] = icol;
00314 if (B.A[icol][icol] == 0.0) error("inv: Singular Matrix-2");
00315 pivinv = 1.0/B.A[icol][icol];
00316 B.A[icol][icol] = 1.0;
00317 for (l=0;l<=columns-1;l++) B.A[icol][l] *= pivinv;
00318 for (ll=0;ll<=rows-1;ll++)
00319 if (ll != icol)
00320 {
00321 dum = B.A[ll][icol];
00322 B.A[ll][icol] = 0.0;
00323 for (l=0;l<=columns-1;l++)
00324 B.A[ll][l] -= B.A[icol][l]*dum;
00325
00326 }
00327 }
00328 for(l=columns-1;l>=0;l--)
00329 {
00330 if (indxr[l] != indxc[l])
00331 B.swapc(indxr[l],indxc[l]);
00332 }
00333 delete(ipiv);
00334 delete(indxr);
00335 delete(indxc);
00336 return(B);
00337 }
00338
00339 matrix matrix::map(double(*f)(double)) {
00340 matrix res(rows,columns);
00341 for (int r=0; r<rows; r++)
00342 for (int s=0; s<columns; s++)
00343 res.set(f(A[r][s]),r,s);
00344
00345 return res;
00346 }
00347
00348 double matrix::maxvalue(){
00349
00350 double max=A[0][0];
00351 for(int i=0; i<rows;i++){
00352 for(int j=0; j<columns; j++)
00353 if (A[i][j]>max) max=A[i][j];
00354 }
00355 return(max);
00356
00357 }
00358
00359
00360
00361 const char* matrix::row2string(int r) {
00362 assert(r>=0 && r<rows);
00363
00364 std::ostringstream mstr;
00365 mstr.setf(std::ios::fixed);
00366 std::string res;
00367 for (int i=0; i<columns; i++) {
00368 mstr << std::setw(9) << A[r][i] << " ";
00369 }
00370
00371 std::string ss = mstr.str();
00372
00373 return ss.c_str();
00374 }
00375
00376
00377 matrix covar2(matrix const& X, matrix const& Y) {
00378 assert(X.row()==Y.row() && (X.column()==Y.column() || Y.column()==1));
00379
00380 safevector <double> mx = X.mean();
00381 safevector <double> my = Y.mean();
00382 matrix cv(X.column());
00383
00384
00385
00386 if (Y.column()==1) {
00387 for (int s=0; s<X.column(); s++) {
00388 double sum=0;
00389 for (int i=0; i<X.row(); i++) {
00390 sum += (X.get(i,s)-mx[s])*(Y.get(i)-my[0]);
00391
00392 }
00393 cv.set(sum/(double)(X.row()-1),s);
00394 }
00395 return cv;
00396 }
00397
00398
00399
00400 for (int s=0; s<X.column(); s++) {
00401 double sum=0;
00402 for (int i=0; i<X.row(); i++) {
00403 sum += (X.get(i,s)-mx[s])*(Y.get(i,s)-my[s]);
00404 }
00405 cv.set(sum/(double)(X.row()-1),s);
00406 }
00407 return cv;
00408 }
00409
00410
00411
00412
00413 #ifdef TEST
00414
00415
00416 double cubic(double x) {
00417 return x*x*x;
00418 }
00419
00420 double square(double x) {
00421 return x*x;
00422 }
00423
00424 double identity(double x) {
00425 return x;
00426 }
00427
00428 int main() {
00429 try {
00430
00431 matrix A(4,4);
00432 for (unsigned i=0; i<4; i++)
00433 for (unsigned j=0; j<4; j++)
00434 A.set(i+j, i,j);
00435
00436 std::cerr << "A= "; A.stdprint();
00437 matrix B = A.map(cubic);
00438 std::cerr << "cubic=\n "; B.stdprint();
00439 B = A.map(square);
00440 std::cerr << "square=\n "; B.stdprint();
00441 B = A.map(identity);
00442 std::cerr << "identity=\n "; B.stdprint();
00443
00444
00445 matrix C(4,4);
00446 C.set(3,0,0); C.set(2,0,1); C.set(1,0,2); C.set(5,0,3);
00447 C.set(4,1,0); C.set(2,1,1); C.set(1,1,2); C.set(5,1,3);
00448 C.set(3,2,0); C.set(4,2,1); C.set(1,2,2); C.set(4,2,3);
00449 C.set(1,3,0); C.set(3,3,1); C.set(1,3,2); C.set(3,3,3);
00450
00451 matrix vec(4);
00452 vec.set(1,0); vec.set(4,1); vec.set(2,2); vec.set(9,3);
00453 std::cerr << "C="; C.stdprint();
00454 std::cerr << "x="; vec.stdprint();
00455 matrix covCx = covar2(C,vec);
00456 std::cerr << "cov(C,x)= "; covCx.stdprint();
00457
00458
00459 std::cerr << "Nothing to test in linalg.cpp\n";
00460 } catch(std::string const& err) {
00461 std::cerr << err << std::endl;
00462 return 1;
00463 }
00464 return 0;
00465 }
00466
00467
00468 #endif//TEST