Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

Mat.cc

Go to the documentation of this file.
00001 /*
00002     File:           Mat.cc
00003 
00004     Function:       Implements Mat.h
00005 
00006     Author(s):      Andrew Willmott
00007 
00008     Copyright:      (c) 1995-2000, Andrew Willmott
00009 
00010     Notes:          
00011 
00012 */
00013 
00014 #include "vl/Mat.h"
00015 #include <ctype.h>
00016 #include <string.h>
00017 #include <stdarg.h>
00018 #include <iomanip.h>
00019 #ifndef __SVL__
00020 #include "cl/Array.h"
00021 #endif
00022 
00023 
00024 // --- Mat Constructors & Destructors -----------------------------------------
00025 
00026 
00027 TMat::TMat(Int rows, Int cols, ZeroOrOne k) : rows(rows), cols(cols)
00028 {
00029     Assert(rows > 0 && cols > 0, "(Mat) illegal matrix size");
00030     
00031     data = new TMReal[rows * cols];
00032     Assert(data != 0, "(Mat) Out of memory");
00033     
00034     MakeDiag(k);
00035 }
00036 
00037 TMat::TMat(Int rows, Int cols, Block k) : rows(rows), cols(cols)
00038 {
00039     Assert(rows > 0 && cols > 0, "(Mat) illegal matrix size");
00040     
00041     data = new TMReal[rows * cols];
00042     Assert(data != 0, "(Mat) Out of memory");
00043     
00044     MakeBlock(k);
00045 }
00046 
00047 TMat::TMat(Int rows, Int cols, double elt0, ...) : rows(rows), cols(cols)
00048 // The double is hardwired here because it is the only type that will work 
00049 // with var args and C++ real numbers. 
00050 {
00051     Assert(rows > 0 && cols > 0, "(Mat) illegal matrix size");
00052     
00053     va_list ap;
00054     Int     i, j;
00055     
00056     data = new TMReal[rows * cols];
00057     Assert(data != 0, "(Mat) Out of memory");
00058     va_start(ap, elt0);
00059         
00060     SetReal(data[0], elt0);
00061     
00062     for (i = 1; i < cols; i++)
00063         SetReal(SELF[0][i], va_arg(ap, double));
00064 
00065     for (i = 1; i < rows; i++)
00066         for (j = 0; j < cols; j++)
00067             SetReal(SELF[i][j], va_arg(ap, double));
00068 
00069     va_end(ap);
00070 }
00071 
00072 TMat::TMat(const TMat &m) : cols(m.cols)
00073 {
00074     Assert(m.data != 0, "(Mat) Can't construct from null matrix");
00075     rows = m.Rows();
00076     
00077     UInt    elts = rows * cols;
00078     
00079     data = new TMReal[elts];
00080     Assert(data != 0, "(Mat) Out of memory");
00081     memcpy(data, m.data, elts * sizeof(TMReal));
00082 }
00083 
00084 #ifndef __SVL__
00085 TMat::TMat(const TSubMat &m) : rows(m.Rows()), cols(m.Cols())
00086 {
00087     data = new TMReal[rows * cols];
00088     Assert(data != 0, "(Mat) Out of memory");
00089 
00090     for (Int i = 0; i < Rows(); i++) 
00091         SELF[i] = m[i];
00092 }
00093 #endif
00094 
00095 TMat::TMat(const TMat2 &m) : rows(2 | VL_REF_FLAG), cols(2), data(m.Ref())
00096 {
00097 }
00098 
00099 TMat::TMat(const TMat3 &m) : rows(3 | VL_REF_FLAG), cols(3), data(m.Ref())
00100 {
00101 }
00102 
00103 TMat::TMat(const TMat4 &m) : rows(4 | VL_REF_FLAG), cols(4), data(m.Ref())
00104 {
00105 }
00106 
00107 
00108 // --- Mat Assignment Operators -----------------------------------------------
00109 
00110 
00111 TMat &TMat::operator = (const TMat &m)  
00112 {   
00113     if (!IsRef())
00114         SetSize(m.Rows(), m.Cols());
00115     else
00116         Assert(Rows() == m.Rows(), "(Mat::=) Matrix rows don't match");
00117     for (Int i = 0; i < Rows(); i++) 
00118         SELF[i] = m[i];
00119 
00120     return(SELF);
00121 }
00122       
00123 #ifndef __SVL__
00124 TMat &TMat::operator = (const TSubMat &m)
00125 {   
00126     if (!IsRef())
00127         SetSize(m.Rows(), m.Cols());
00128     else
00129         Assert(Rows() == m.Rows(), "(Mat::=) Matrix rows don't match");
00130     for (Int i = 0; i < Rows(); i++) 
00131         SELF[i] = m[i];
00132 
00133     return(SELF);
00134 }
00135 #endif
00136       
00137 TMat &TMat::operator = (const TMat2 &m)
00138 {   
00139     if (!IsRef())
00140         SetSize(m.Rows(), m.Cols());
00141     else
00142         Assert(Rows() == m.Rows(), "(Mat::=) Matrix rows don't match");
00143     for (Int i = 0; i < Rows(); i++) 
00144         SELF[i] = m[i];
00145 
00146     return(SELF);
00147 }
00148       
00149 TMat &TMat::operator = (const TMat3 &m)
00150 {   
00151     if (!IsRef())
00152         SetSize(m.Rows(), m.Cols());
00153     else
00154         Assert(Rows() == m.Rows(), "(Mat::=) Matrix rows don't match");
00155     for (Int i = 0; i < Rows(); i++) 
00156         SELF[i] = m[i];
00157 
00158     return(SELF);
00159 }
00160       
00161 TMat &TMat::operator = (const TMat4 &m)
00162 {   
00163     if (!IsRef())
00164         SetSize(m.Rows(), m.Cols());
00165     else
00166         Assert(Rows() == m.Rows(), "(Mat::=) Matrix rows don't match");
00167 
00168     for (Int i = 0; i < Rows(); i++) 
00169         SELF[i] = m[i];
00170 
00171     return(SELF);
00172 }
00173 
00174 Void TMat::SetSize(Int nrows, Int ncols)
00175 {
00176     UInt    elts = nrows * ncols;
00177     Assert(elts > 0, "(Mat::SetSize) Illegal matrix size.");
00178     UInt    oldElts = Rows() * Cols();
00179     Bool    wasRef = IsRef();
00180     
00181     rows = nrows;
00182     cols = ncols;
00183 
00184     if (wasRef)
00185     {
00186         // Do we already have enough storage?
00187         rows |= VL_REF_FLAG;
00188         if (elts <= oldElts)
00189             return;
00190 
00191         _Error("(Mat::SetSize) Trying to increase size of a reference vector");
00192 
00193         delete[] data;
00194     }
00195 
00196     data = new TMReal[elts];
00197     Assert(data != 0, "(Mat::SetSize) Out of memory");
00198 }
00199 
00200 Void TMat::SetSize(const TMat &m)
00201 {
00202     SetSize(m.Rows(), m.Cols());
00203 }
00204 
00205 Void TMat::MakeZero()
00206 {
00207     Int     i, j;
00208     
00209     for (i = 0; i < Rows(); i++)
00210         for (j = 0; j < Cols(); j++)
00211             Elt(i,j) = vl_zero;     
00212 }
00213 
00214 Void TMat::MakeDiag(TMReal k)
00215 {
00216     Int     i, j;
00217     
00218     for (i = 0; i < Rows(); i++)
00219         for (j = 0; j < Cols(); j++)
00220             if (i == j) 
00221                 Elt(i,j) = k;
00222             else
00223                 Elt(i,j) = vl_zero;     
00224 }
00225 
00226 Void TMat::MakeDiag()
00227 {
00228     Int     i, j;
00229     
00230     for (i = 0; i < Rows(); i++)
00231         for (j = 0; j < Cols(); j++)
00232             Elt(i,j) = (i == j) ? vl_one : vl_zero;     
00233 }
00234 
00235 Void TMat::MakeBlock(TMReal k)
00236 {
00237     Int     i, j;
00238     
00239     for (i = 0; i < Rows(); i++)
00240         for (j = 0; j < Cols(); j++)
00241             Elt(i,j) = k;       
00242 }
00243 
00244 Void TMat::MakeBlock()
00245 {
00246     Int     i, j;
00247     
00248     for (i = 0; i < Rows(); i++)
00249         for (j = 0; j < Cols(); j++)
00250             Elt(i,j) = vl_one;      
00251 }
00252 
00253 
00254 // --- Mat Assignment Operators -----------------------------------------------
00255 
00256 
00257 TMat &operator += (TMat &m, const TMat &n)
00258 {
00259     Assert(n.Rows() == m.Rows(), "(Mat::+=) matrix rows don't match");  
00260     
00261     Int     i;
00262     TMVec   t;
00263     
00264     for (i = 0; i < n.Rows(); i++) 
00265         m[i] += n[i];
00266     
00267     return(m);
00268 }
00269 
00270 TMat &operator -= (TMat &m, const TMat &n)
00271 {
00272     Assert(n.Rows() == m.Rows(), "(Mat::-=) matrix rows don't match");  
00273     
00274     Int     i;
00275     TMVec   t;
00276     
00277     for (i = 0; i < m.Rows(); i++) 
00278         m[i] -= n[i];
00279     
00280     return(m);
00281 }
00282 
00283 TMat &operator *= (TMat &m, const TMat &n)
00284 {
00285     Assert(m.Cols() == n.Cols(), "(Mat::*=) matrix columns don't match");   
00286     
00287     Int     i;
00288     TMVec   t;
00289     
00290     for (i = 0; i < m.Rows(); i++) 
00291         m[i] *= n;
00292     
00293     return(m);
00294 }
00295 
00296 TMat &operator *= (TMat &m, TMReal s)
00297 {   
00298     Int     i;
00299     TMVec   t;
00300     
00301     for (i = 0; i < m.Rows(); i++) 
00302         m[i] *= s;
00303     
00304     return(m);
00305 }
00306 
00307 TMat &operator /= (TMat &m, TMReal s)
00308 {   
00309     Int     i;
00310     TMVec   t;
00311     
00312     for (i = 0; i < m.Rows(); i++) 
00313         m[i] /= s;
00314     
00315     return(m);
00316 }
00317 
00318 
00319 // --- Mat Comparison Operators -----------------------------------------------
00320 
00321 
00322 Bool operator == (const TMat &m, const TMat &n)
00323 {
00324     Assert(n.Rows() == m.Rows(), "(Mat::==) matrix rows don't match");  
00325     
00326     Int     i;
00327     
00328     for (i = 0; i < m.Rows(); i++) 
00329         if (m[i] != n[i])
00330             return(0);
00331 
00332     return(1);
00333 }
00334 
00335 Bool operator != (const TMat &m, const TMat &n)
00336 {
00337     Assert(n.Rows() == m.Rows(), "(Mat::!=) matrix rows don't match");  
00338     
00339     Int     i;
00340     
00341     for (i = 0; i < m.Rows(); i++) 
00342         if (m[i] != n[i])
00343             return(1);
00344 
00345     return(0);
00346 }
00347 
00348 
00349 // --- Mat Arithmetic Operators -----------------------------------------------
00350 
00351 
00352 TMat operator + (const TMat &m, const TMat &n)
00353 {
00354     Assert(n.Rows() == m.Rows(), "(Mat::+) matrix rows don't match");   
00355     
00356     TMat    result(m.Rows(), m.Cols());
00357     Int     i;
00358     
00359     for (i = 0; i < m.Rows(); i++) 
00360         result[i] = m[i] + n[i];
00361     
00362     return(result);
00363 }
00364 
00365 TMat operator - (const TMat &m, const TMat &n)
00366 {
00367     Assert(n.Rows() == m.Rows(), "(Mat::-) matrix rows don't match");   
00368     
00369     TMat    result(m.Rows(), m.Cols());
00370     Int     i;
00371     
00372     for (i = 0; i < m.Rows(); i++) 
00373         result[i] = m[i] - n[i];
00374     
00375     return(result);
00376 }
00377 
00378 TMat operator - (const TMat &m)
00379 {
00380     TMat    result(m.Rows(), m.Cols());
00381     Int     i;
00382     
00383     for (i = 0; i < m.Rows(); i++) 
00384         result[i] = -m[i];
00385     
00386     return(result);
00387 }
00388 
00389 TMat operator * (const TMat &m, const TMat &n)
00390 {
00391     Assert(m.Cols() == n.Rows(), "(Mat::*m) matrix cols don't match");  
00392     
00393     TMat    result(m.Rows(), n.Cols());
00394     Int     i;
00395     
00396     for (i = 0; i < m.Rows(); i++) 
00397         result[i] = m[i] * n;
00398     
00399     return(result);
00400 }
00401 
00402 TMVec operator * (const TMat &m, const TMVec &v)
00403 {
00404     Assert(m.Cols() == v.Elts(), "(Mat::*v) matrix and vector sizes don't match");
00405     
00406     Int     i;
00407     TMVec   result(m.Rows());
00408     
00409     for (i = 0; i < m.Rows(); i++) 
00410         result[i] = dot(v, m[i]);
00411     
00412     return(result);
00413 }
00414 
00415 TMat operator * (const TMat &m, TMReal s)
00416 {
00417     Int     i;
00418     TMat    result(m.Rows(), m.Cols());
00419     
00420     for (i = 0; i < m.Rows(); i++) 
00421         result[i] = m[i] * s;
00422     
00423     return(result);
00424 }
00425 
00426 TMat operator / (const TMat &m, TMReal s)
00427 {
00428     Int     i;
00429     TMat    result(m.Rows(), m.Cols());
00430     
00431     for (i = 0; i < m.Rows(); i++) 
00432         result[i] = m[i] / s;
00433     
00434     return(result);
00435 }
00436 
00437 
00438 // --- Mat Mat-Vec Functions --------------------------------------------------
00439 
00440 
00441 TMVec operator * (const TMVec &v, const TMat &m)            // v * m
00442 {
00443     Assert(v.Elts() == m.Rows(), "(Mat::v*m) vector/matrix sizes don't match");
00444     
00445     TMVec   result(m.Cols(), vl_zero);
00446     Int     i;
00447     
00448     for (i = 0; i < m.Rows(); i++) 
00449         result += m[i] * v[i];
00450     
00451     return(result);
00452 }
00453 
00454 TMVec &operator *= (TMVec &v, const TMat &m)                // v *= m
00455 {
00456     v = v * m;      // Can't optimise much here...
00457     
00458     return(v);
00459 }
00460 
00461 
00462 // --- Mat Special Functions --------------------------------------------------
00463 
00464 
00465 TMat trans(const TMat &m)
00466 {
00467     Int     i,j;
00468     TMat    result(m.Cols(), m.Rows());
00469     
00470     for (i = 0; i < m.Rows(); i++) 
00471         for (j = 0; j < m.Cols(); j++)
00472             result.Elt(j,i) = m.Elt(i,j);
00473     
00474     return(result);
00475 }
00476 
00477 TMReal trace(const TMat &m)
00478 {
00479     Int     i;
00480     TMReal  result = vl_0;
00481     
00482     for (i = 0; i < m.Rows(); i++) 
00483         result += m.Elt(i,i);
00484     
00485     return(result);
00486 }
00487 
00488 TMat &TMat::Clamp(Real fuzz)
00489 //  clamps all values of the matrix with a magnitude
00490 //  smaller than fuzz to zero.
00491 {
00492     Int i;
00493 
00494     for (i = 0; i < Rows(); i++)
00495         SELF[i].Clamp(fuzz);
00496             
00497     return(SELF);
00498 }
00499 
00500 TMat &TMat::Clamp()
00501 {
00502     return(Clamp(1e-7));
00503 }
00504 
00505 TMat clamped(const TMat &m, Real fuzz)
00506 //  clamps all values of the matrix with a magnitude
00507 //  smaller than fuzz to zero.
00508 {
00509     TMat    result(m);
00510             
00511     return(result.Clamp(fuzz));
00512 }
00513 
00514 TMat clamped(const TMat &m)
00515 {
00516     return(clamped(m, 1e-7));
00517 }
00518 
00519 TMat oprod(const TMVec &a, const TMVec &b)
00520 // returns outerproduct of a and b:  a * trans(b)
00521 {
00522     TMat    result;
00523     Int     i;
00524     
00525     result.SetSize(a.Elts(), b.Elts());
00526     for (i = 0; i < a.Elts(); i++)
00527         result[i] = a[i] * b;
00528 
00529     return(result);
00530 }
00531 
00532 
00533 // --- Mat Input & Output -----------------------------------------------------
00534 
00535 
00536 ostream &operator << (ostream &s, const TMat &m)
00537 {
00538     Int i, w = s.width();
00539     
00540     s << '[';
00541     for (i = 0; i < m.Rows() - 1; i++)
00542         s << setw(w) << m[i] << endl;
00543     s << setw(w) << m[i] << ']' << endl;
00544     return(s);
00545 }
00546 
00547 #ifndef __SVL__
00548 istream &operator >> (istream &s, TMat &m)
00549 {
00550     Array< Array<TMReal> > array;   
00551     Int     i;
00552     
00553     s >> array;                     // Read input into array of arrays
00554     
00555     m.SetSize(array.NumItems(), array[0].NumItems());
00556     
00557     for (i = 0; i < m.Rows(); i++)  // copy the result into m
00558     {
00559         Assert(m.Cols() == array[i].NumItems(), "(Mat/>>) different sized matrix rows");
00560         m[i] = TMVec(m.Cols(), array[i].Ref());
00561     }
00562     
00563     return(s);
00564 }
00565 #endif
00566 
00567 //
00568 //  inv: matrix inversion using Gaussian pivoting
00569 //
00570 
00571 #if !defined(CL_CHECKING) && !defined(VL_CHECKING)
00572 // we #define away pAssertEps if it is not used, to avoid
00573 // compiler warnings.
00574 #define pAssertEps
00575 #endif
00576 
00577 TMat inv(const TMat &m, TMReal *determinant, TMReal pAssertEps)
00578 {
00579     Assert(m.IsSquare(), "(inv) Matrix not square");
00580 
00581     Int             i, j, k;
00582     Int             n = m.Rows();
00583     TMReal          t, pivot, det;
00584     Real            max;
00585     TMat            A(m);
00586     TMat            B(n, n, vl_I);      
00587 
00588     // ---------- Forward elimination ---------- ------------------------------
00589     
00590     det = vl_1;
00591     
00592     for (i = 0; i < n; i++)             // Eliminate in column i, below diag
00593     {       
00594         max = -1.0;
00595         
00596         for (k = i; k < n; k++)         // Find a pivot for column i 
00597             if (len(A[k][i]) > max)
00598             {
00599                 max = len(A[k][i]);
00600                 j = k;
00601             }
00602             
00603         Assert(max > pAssertEps, "(inv) Matrix not invertible");
00604                     
00605         if (j != i)                     // Swap rows i and j
00606         {           
00607             for (k = i; k < n; k++)
00608                 Swap(A.Elt(i, k), A.Elt(j, k));
00609             for (k = 0; k < n; k++)
00610                 Swap(B.Elt(i, k), B.Elt(j, k));
00611                 
00612             det = -det;
00613         }
00614         
00615         pivot = A.Elt(i, i);
00616         Assert(abs(pivot) > pAssertEps, "(inv) Matrix not invertible");
00617         det *= pivot;
00618         
00619         for (k = i + 1; k < n; k++)     // Only do elements to the right of the pivot 
00620             A.Elt(i, k) /= pivot;
00621             
00622         for (k = 0; k < n; k++)
00623             B.Elt(i, k) /= pivot;
00624             
00625         // We know that A(i, i) will be set to 1, so don't bother to do it
00626     
00627         for (j = i + 1; j < n; j++)
00628         {                               // Eliminate in rows below i 
00629             t = A.Elt(j, i);            // We're gonna zero this guy 
00630             for (k = i + 1; k < n; k++) // Subtract scaled row i from row j 
00631                 A.Elt(j, k) -= A.Elt(i, k) * t; // (Ignore k <= i, we know they're 0) 
00632             for (k = 0; k < n; k++)
00633                 B.Elt(j, k) -= B.Elt(i, k) * t;
00634         }
00635     }
00636 
00637     // ---------- Backward elimination ---------- -----------------------------
00638 
00639     for (i = n - 1; i > 0; i--)         // Eliminate in column i, above diag 
00640     {       
00641         for (j = 0; j < i; j++)         // Eliminate in rows above i 
00642         {       
00643             t = A.Elt(j, i);            // We're gonna zero this guy 
00644             for (k = 0; k < n; k++)     // Subtract scaled row i from row j 
00645                 B.Elt(j, k) -= B.Elt(i, k) * t;
00646         }
00647     }
00648     if (determinant)
00649         *determinant = det;
00650     return(B);
00651 }
00652 

Generated at Sat Aug 5 00:16:46 2000 for Class Library by doxygen 1.1.0 written by Dimitri van Heesch, © 1997-2000