Matrix.cpp

Go to the documentation of this file.
00001 /**
00002 \file     Matrix.cpp
00003 \brief    The Zenautics Matrix Class
00004 \author   Glenn D. MacGougan (GDM)
00005 \date     2007-12-21
00006 \version  1.11
00007 
00008 \b LICENSE \b INFORMATION \n
00009 Copyright (c) 2007, Glenn D. MacGougan, Zenautics Technologies Inc. \n
00010 
00011 Redistribution pertains only to the following files and their contents. \n
00012 - Matrix.h\n
00013 - Matrix.cpp\n
00014 - cmatrix.h\n
00015 - cmatrix_basic.lib (for windows), cmatrix_basic_lib.a (for linux)\n
00016 
00017 Redistribution and use in source and binary forms, with or without
00018 modification, of the specified files is permitted provided the following 
00019 conditions are met: \n
00020 
00021 - Redistributions of source code must retain the above copyright
00022   notice, this list of conditions and the following disclaimer. \n
00023 - Redistributions in binary form must reproduce the above copyright
00024   notice, this list of conditions and the following disclaimer in the
00025   documentation and/or other materials provided with the distribution. \n
00026 - The name(s) of the contributor(s) may not be used to endorse or promote 
00027   products derived from this software without specific prior written 
00028   permission. \n
00029 
00030 THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS 
00031 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
00032 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00033 DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
00034 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00035 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
00036 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
00037 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
00038 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
00039 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
00040 SUCH DAMAGE.
00041 
00042 \b NOTES: \n
00043 This code was developed using rigourous unit testing for every function 
00044 and operation. Despite any rigorous development process, bugs are
00045 inevitable. Please report bugs and suggested fixes to glenn@zenautics.com.\n
00046 */
00047 
00048 
00049 #include <stdlib.h>
00050 #include <string.h>
00051 
00052 #include "Matrix.h"
00053 #include "cmatrix.h"
00054 
00055 #ifndef WIN32
00056 #define _CRT_SECURE_NO_DEPRECATE
00057 #endif
00058 
00059 
00060 #ifndef DEG2RAD
00061 #define DEG2RAD   (0.017453292519943295769236907684886)  //!< PI/180.0
00062 #endif
00063 
00064 #ifndef RAD2DEG
00065 #define RAD2DEG   (57.295779513082320876798154814105)    //!< 180.0/PI
00066 #endif
00067 
00068 
00069 namespace Zenautics
00070 {
00071   /// A static double  value used for bad referencing. i.e. give me element 10 of 1x9 vector.
00072   static double staticglobal_BadDouble = 0.0;
00073 
00074   // A boolean used to ensure initialization of the mtx engine.
00075   bool Matrix::m_IsMTXInitialized = false;
00076 
00077 
00078 
00079   MatrixException::MatrixException( const char* msg )
00080   {
00081     unsigned msgLength = 0;
00082     if( msg == NULL )
00083     {
00084 #ifndef _CRT_SECURE_NO_DEPRECATE
00085       strcpy_s( m_msg, 256, "Unknown Matrix Exception" );
00086 #else
00087       strcpy( m_msg, "Unknown Matrix Exception" );
00088 #endif
00089     }
00090     else
00091     {
00092       msgLength = (unsigned)strlen( msg );
00093       // note 255 here, not 256, 
00094       // just in case msgLength is 255 and we add '\0' to the end of m_msg.
00095 #ifndef _CRT_SECURE_NO_DEPRECATE
00096       if( msgLength < 255 )
00097       {
00098         strncpy_s( m_msg, 256, msg, msgLength );
00099         m_msg[msgLength] = '\0';
00100       }
00101       else
00102       {
00103         strncpy_s( m_msg, 256, msg, 255 );
00104         m_msg[255] = '\0';
00105       }
00106 #else
00107       if( msgLength < 255 )
00108       {
00109         strncpy( m_msg, msg, msgLength );
00110         m_msg[msgLength] = '\0';
00111       }
00112       else
00113       {
00114         strncpy( m_msg, msg, 255 );
00115         m_msg[255] = '\0';
00116       }
00117 #endif
00118     }
00119     m_ExceptionString = m_msg;
00120   }
00121 
00122   MatrixException::MatrixException(const MatrixException& matrix_exception)
00123   {
00124     // This will copy only the matrix exception string.
00125     m_ExceptionString = matrix_exception.m_ExceptionString;
00126   }
00127 
00128   std::string MatrixException::GetExceptionMessage()
00129   {
00130     return m_ExceptionString;
00131   }
00132 
00133   MatrixException::operator const char*()
00134   {
00135     return m_ExceptionString.c_str();
00136   }
00137 
00138 
00139 
00140 
00141 
00142 
00143 
00144 
00145 
00146 
00147   // default constructor
00148   Matrix::Matrix()
00149     :m_MatrixElement(m_Matrix)
00150   {
00151     if( !m_IsMTXInitialized )
00152     {
00153       if( !MTX_Initialize_MTXEngine() )
00154       {
00155         m_IsMTXInitialized = false;
00156         MatrixError( "Matrix", "Failed to initialize the MTX Engine. Try commenting out #define MTX_SIMD_OPTIMIZED in cmatrix.h" );
00157       }
00158       else
00159       {
00160         m_IsMTXInitialized = true;
00161       }
00162     }
00163 
00164     MTX_Init( &m_Matrix );
00165   }
00166 
00167 
00168   // destructor
00169   Matrix::~Matrix()
00170   { 
00171     if( !m_IsMTXInitialized )
00172     {
00173       if( !MTX_Initialize_MTXEngine() )
00174       {
00175         m_IsMTXInitialized = false;
00176         MatrixError( "Matrix", "Failed to initialize the MTX Engine. Try commenting out #define MTX_SIMD_OPTIMIZED in cmatrix.h" );
00177       }
00178       else
00179       {
00180         m_IsMTXInitialized = true;
00181       }
00182     }
00183 
00184     if( !MTX_Free( &m_Matrix ) )
00185     {
00186       MatrixError( "~Matrix", "Unable to free memory properly" );
00187     }
00188   }
00189 
00190 
00191   // vector style constructor
00192   Matrix::Matrix( const unsigned nrows )
00193     :m_MatrixElement(m_Matrix)
00194   { 
00195     if( !m_IsMTXInitialized )
00196     {
00197       if( !MTX_Initialize_MTXEngine() )
00198       {
00199         m_IsMTXInitialized = false;
00200         MatrixError( "Matrix", "Failed to initialize the MTX Engine. Try commenting out #define MTX_SIMD_OPTIMIZED in cmatrix.h" );
00201       }
00202       else
00203       {
00204         m_IsMTXInitialized = true;
00205       }
00206     }
00207 
00208     MTX_Init( &m_Matrix );
00209     if( !MTX_Calloc( &m_Matrix, nrows, 1, true ) )
00210     {
00211       char msg[128];
00212 #ifndef _CRT_SECURE_NO_DEPRECATE
00213       sprintf_s( msg, 128, "Unable to allocate enough memory for Matrix as vector(%d)", nrows );
00214 #else
00215       sprintf( msg, "Unable to allocate enough memory for Matrix as vector(%d)", nrows );
00216 #endif
00217       MatrixError( "Matrix", msg );
00218     }
00219   }
00220 
00221 
00222   // matrix style constructor
00223   Matrix::Matrix( const unsigned nrows, const unsigned ncols, const bool isReal )
00224     :m_MatrixElement(m_Matrix)
00225   { 
00226     if( !m_IsMTXInitialized )
00227     {
00228       if( !MTX_Initialize_MTXEngine() )
00229       {
00230         m_IsMTXInitialized = false;
00231         MatrixError( "Matrix", "Failed to initialize the MTX Engine. Try commenting out #define MTX_SIMD_OPTIMIZED in cmatrix.h" );
00232       }
00233       else
00234       {
00235         m_IsMTXInitialized = true;
00236       }
00237     }
00238 
00239     MTX_Init( &m_Matrix );
00240     if( !MTX_Calloc( &m_Matrix, nrows, ncols, isReal ) )
00241     {
00242       char msg[128];
00243 #ifndef _CRT_SECURE_NO_DEPRECATE
00244       if( isReal )
00245         sprintf_s( msg, 128, "Unable to allocate enough memory for Matrix(%d,%d)", nrows, ncols );
00246       else
00247         sprintf_s( msg, 128, "Unable to allocate enough memory for complex Matrix(%d,%d)", nrows, ncols );
00248 #else
00249       if( isReal )
00250         sprintf( msg, "Unable to allocate enough memory for Matrix(%d,%d)", nrows, ncols );
00251       else
00252         sprintf( msg, "Unable to allocate enough memory for complex Matrix(%d,%d)", nrows, ncols );
00253 #endif
00254 
00255       MatrixError( "Matrix", msg );
00256     }
00257   }
00258 
00259 
00260   // constructor reading data from file   
00261   Matrix::Matrix( const char* path, bool& itWorked )
00262     :m_MatrixElement(m_Matrix)
00263   {
00264     if( !m_IsMTXInitialized )
00265     {
00266       if( !MTX_Initialize_MTXEngine() )
00267       {
00268         m_IsMTXInitialized = false;
00269         MatrixError( "Matrix", "Failed to initialize the MTX Engine. Try commenting out #define MTX_SIMD_OPTIMIZED in cmatrix.h" );
00270       }
00271       else
00272       {
00273         m_IsMTXInitialized = true;
00274       }
00275     }
00276 
00277     MTX_Init( &m_Matrix );
00278 
00279     if( MTX_ReadFromFile( &m_Matrix, path ) )
00280       itWorked = true;
00281     else
00282       itWorked = false;  
00283   }
00284 
00285   // copy constructor
00286   Matrix::Matrix( const Matrix& mat )
00287     :m_MatrixElement(m_Matrix)
00288   {
00289     MTX_Init( &m_Matrix );
00290     if( !MTX_Copy( &(mat.m_Matrix), &m_Matrix ) )
00291     {
00292       MatrixError( "Matrix", "Copy constructor failed to copy input matrix." );
00293     }
00294   }
00295 
00296   // copy from a static matrix
00297   Matrix::Matrix(const double mat[], const unsigned nrows, const unsigned ncols )
00298     :m_MatrixElement(m_Matrix)
00299   {
00300     MTX_Init( &m_Matrix );
00301     if( mat == NULL )
00302     {
00303       MatrixError( "Matrix", "Input static double array(matrix) pointer is NULL" );
00304     }
00305     if( !MTX_SetFromStaticMatrix( &m_Matrix, mat, nrows, ncols ) )
00306     {
00307       MatrixError( "Matrix", "Failed to set the matrix from a static double array(matrix)" );
00308     }
00309   }
00310 
00311 
00312   // assignment operator (constructor)
00313   Matrix& Matrix::operator= (const Matrix& mat)
00314   {
00315     // trap assignment to self
00316     if( this == &mat )
00317       return *this;
00318 
00319     if( !MTX_Copy( &mat.m_Matrix, &m_Matrix ) )
00320     {
00321       MatrixError( "operator=", "Failed to copy input matrix" );
00322     }
00323 
00324     return *this;
00325   }
00326 
00327 
00328   Matrix& Matrix::operator= (const double value)
00329   {
00330     if( !MTX_Malloc( &m_Matrix, 1, 1, true ) )
00331     {
00332       MatrixError( "operator=double", "Unable to redimension to 1x1." );
00333     }
00334 
00335     if( !MTX_SetValue( &m_Matrix, 0, 0, value ) )
00336     {
00337       MatrixError( "operator=double", "Unable to set double value." );
00338     }
00339 
00340     return *this;
00341   }
00342 
00343   Matrix& Matrix::operator= (const std::complex<double> value)
00344   {
00345     if( !MTX_Malloc( &m_Matrix, 1, 1, false ) )
00346     {
00347       MatrixError( "operator=std::complex<double>", "Unable to redimension to 1x1." );
00348     }
00349 
00350     if( !MTX_SetComplexValue( &m_Matrix, 0, 0, value.real(), value.imag() ) )
00351     {
00352       MatrixError( "operator=std::complex<double>", "Unable to set the value." );
00353     }
00354 
00355     return *this;
00356   }
00357 
00358   Matrix& Matrix::operator=(const char* strMatrix)
00359   {
00360     if( !MTX_SetFromMatrixString( &m_Matrix, strMatrix ) )
00361     {
00362       MatrixError( "operator=string", "Unable to set matrix from the string specified." );
00363     }
00364     return *this;
00365   }
00366 
00367   bool Matrix::Clear()
00368   {
00369     if( MTX_Free( &m_Matrix ) )
00370       return true;
00371     else
00372       return false;    
00373   }
00374 
00375   void Matrix::MatrixError( const char* error )
00376   {
00377     Clear();
00378     StaticMatrixError( error );
00379   }
00380 
00381   void Matrix::MatrixError( const char* function, const char* error )
00382   {
00383     Clear();
00384     StaticMatrixError( function, error );
00385   }
00386 
00387 
00388   // static
00389   void Matrix::StaticMatrixError( const char* error )
00390   {
00391     StaticMatrixError( "", error );
00392   }
00393 
00394   // static
00395   void Matrix::StaticMatrixError( const char* function, const char* error )
00396   {
00397     char msg[256];
00398 #ifndef _CRT_SECURE_NO_DEPRECATE
00399     if( strstr(function,"operator") != NULL )
00400       sprintf_s( msg, 256, "\nMatrix::%s, Error:\n%s\n", function, error );   
00401     else
00402       sprintf_s( msg, 256, "\nMatrix::%s(), Error:\n%s\n", function, error );
00403 #else
00404     if( strstr(function,"operator") != NULL )
00405       sprintf( msg, "\nMatrix::%s, Error:\n%s\n", function, error );   
00406     else
00407       sprintf( msg, "\nMatrix::%s(), Error:\n%s\n", function, error );
00408 #endif
00409 
00410 
00411 #ifdef MATRIX_USE_EXCEPTION_HANDLING
00412 
00413     throw MatrixException(msg);
00414     return;
00415 
00416 #else
00417 
00418 #ifdef USING_MFC
00419     CString errMsg = msg;
00420     AfxMessageBox(errMsg);   
00421 #else
00422     printf( "%s\r\n", msg );   
00423 #endif
00424 
00425     // no choice but to call exit!
00426     exit(1);
00427 #endif    
00428   }
00429 
00430 
00431   bool Matrix::isEmpty() const
00432   {
00433     if( MTX_isNull( &m_Matrix ) )
00434       return true;
00435     else
00436       return false;
00437   }
00438 
00439   bool Matrix::isConformal(const Matrix& mat) const
00440   {
00441     if( MTX_isConformalForMultiplication( &m_Matrix, &mat.m_Matrix ) )
00442       return true;
00443     else
00444       return false;
00445   }
00446 
00447   bool Matrix::isSameSize(const Matrix& mat) const
00448   {
00449     if( MTX_isSameSize( &m_Matrix, &mat.m_Matrix ) )
00450       return true;
00451     else 
00452       return false;
00453   }
00454 
00455   bool Matrix::isSquare() const
00456   {
00457     if( MTX_isSquare( &m_Matrix ) )
00458       return true;
00459     else 
00460       return false;
00461   }
00462 
00463   unsigned  Matrix::GetNrCols() const
00464   {
00465     return m_Matrix.ncols;
00466   }
00467 
00468   unsigned  Matrix::ncols() const
00469   {
00470     return m_Matrix.ncols;
00471   }
00472 
00473   unsigned Matrix::GetNrElems() const
00474   {
00475     return m_Matrix.ncols*m_Matrix.nrows;
00476   }
00477 
00478   unsigned Matrix::nelems() const
00479   {
00480     return m_Matrix.ncols*m_Matrix.nrows;
00481   }
00482 
00483   unsigned Matrix::GetNrRows() const
00484   {
00485     return m_Matrix.nrows;
00486   }
00487 
00488   unsigned Matrix::nrows() const
00489   {
00490     return m_Matrix.nrows;
00491   }
00492 
00493   unsigned Matrix::GetLength() const
00494   {
00495     if( m_Matrix.nrows > m_Matrix.ncols )
00496       return m_Matrix.nrows;
00497     else
00498       return m_Matrix.ncols;
00499   }
00500 
00501   double Matrix::real(const unsigned row, const unsigned col)
00502   {
00503     if( IndexCheck(row,col) )
00504     {
00505       if( m_Matrix.isReal )
00506       {
00507         return m_Matrix.data[col][row];
00508       }
00509       else
00510       {
00511         return m_Matrix.cplx[col][row].re;
00512       }
00513     }
00514     else
00515     {
00516       return 0.0;
00517     }
00518   }
00519 
00520   double Matrix::real(const unsigned index)
00521   {
00522     unsigned row = 0;
00523     unsigned col = 0;
00524 
00525     if( IndexCheck(index) )
00526     {
00527       if( m_Matrix.ncols == 1 )
00528       {
00529         row = index;
00530       }
00531       else if( m_Matrix.nrows == 1 )
00532       {
00533         col = index;
00534       }
00535       else
00536       {
00537         // access the matrix as a singular column array
00538         col = index / m_Matrix.nrows;
00539         row = index - col*m_Matrix.nrows;
00540       }
00541       if( m_Matrix.isReal )
00542       {
00543         return m_Matrix.data[col][row];
00544       }
00545       else
00546       {
00547         return m_Matrix.cplx[col][row].re;
00548       }
00549     }
00550     else
00551     {
00552       return 0.0;
00553     }
00554   }
00555 
00556   double Matrix::imag(const unsigned row, const unsigned col)
00557   {
00558     if( IndexCheck(row,col) )
00559     {
00560       if( m_Matrix.isReal )
00561       {
00562         return 0.0;
00563       }
00564       else
00565       {
00566         return m_Matrix.cplx[col][row].im;
00567       }
00568     }
00569     else
00570     {
00571       return 0.0;
00572     }
00573   }
00574 
00575   double Matrix::imag(const unsigned index)
00576   {
00577     unsigned row = 0;
00578     unsigned col = 0;
00579 
00580     if( IndexCheck(index) )
00581     {
00582       if( m_Matrix.ncols == 1 )
00583       {
00584         row = index;
00585       }
00586       else if( m_Matrix.nrows == 1 )
00587       {
00588         col = index;
00589       }
00590       else
00591       {
00592         // access the matrix as a singular column array
00593         col = index / m_Matrix.nrows;
00594         row = index - col*m_Matrix.nrows;
00595       }
00596       if( m_Matrix.isReal )
00597       {
00598         return 0.0;
00599       }
00600       else
00601       {
00602         return m_Matrix.cplx[col][row].im;
00603       }
00604     }
00605     else
00606     {
00607       return 0.0;
00608     }
00609   }
00610 
00611   bool Matrix::isStoredAsComplex()
00612   {
00613     if( m_Matrix.isReal )
00614       return false;
00615     else
00616       return true;
00617   }
00618 
00619   /// Is this a real matrix for accessing by (row,col) operator? e.g. double d = A(0,4).
00620   bool Matrix::isReal()
00621   {
00622     BOOL isItReal = 0;
00623     
00624     // not checking return value
00625     MTX_isReal(&m_Matrix,&isItReal);
00626 
00627     if( isItReal )
00628       return true;
00629     else
00630       return false;    
00631   }
00632 
00633   /// Is this a complex matrix for accessing by [row][col] operators? e.g. stComplex d = A[0][4].
00634   bool Matrix::isComplex()
00635   {
00636     return !isReal();
00637   }
00638 
00639   bool Matrix::isVector()
00640   {
00641     if( m_Matrix.nrows == 1 )
00642       return true;
00643     if( m_Matrix.ncols == 1 )
00644       return true;
00645 
00646     // otherwise
00647     return false;
00648   }
00649 
00650   bool Matrix::ReadFromFile( const char *path )
00651   {
00652     if( MTX_ReadFromFile( &m_Matrix, path ) )
00653       return true;
00654     else 
00655       return false;
00656   }
00657 
00658 
00659   bool Matrix::ReadFromFile( std::string path )
00660   {
00661     return ReadFromFile( path.c_str() );
00662   }
00663 
00664 
00665   bool Matrix::Copy( Matrix& src )
00666   {
00667     if( MTX_Copy( &src.m_Matrix, &m_Matrix ) )
00668       return true;
00669     else
00670       return false;
00671   }
00672 
00673   bool Matrix::Copy( const double& value )
00674   {
00675     if( !MTX_Malloc( &m_Matrix, 1, 1, true ) )
00676       return false;
00677 
00678     if( MTX_SetValue( &m_Matrix, 0, 0, value ) )
00679       return true;
00680     else
00681       return false;
00682   }
00683 
00684   bool Matrix::Copy( const std::complex<double>& cplx )
00685   {
00686     if( !MTX_Malloc( &m_Matrix, 1, 1, false ) )
00687       return false;
00688 
00689     if( MTX_SetComplexValue( &m_Matrix, 0, 0, cplx.real(), cplx.imag() ) )
00690       return true;
00691     else
00692       return false;
00693   }
00694 
00695   bool Matrix::Save( const char* path )
00696   {
00697     if( MTX_SaveCompressed( &m_Matrix, path ) )
00698       return true;
00699     else 
00700       return false;
00701   }
00702 
00703   bool Matrix::Save( std::string path )
00704   {
00705     return Save( path.c_str() );
00706   }
00707 
00708   bool Matrix::Print( const char *path, const unsigned precision, bool append )
00709   {
00710     if( MTX_PrintAutoWidth( &m_Matrix, path, precision, append ) )
00711       return true;
00712     else 
00713       return false;
00714   }
00715 
00716   bool Matrix::Print( std::string path, const unsigned precision, bool append ) 
00717   {
00718     return Print( path.c_str(), precision );
00719   }
00720 
00721   bool Matrix::PrintStdout( const unsigned precision )
00722   {
00723     if( MTX_PrintStdoutAutoWidth( &m_Matrix, precision ) )
00724       return true;
00725     else
00726       return false;
00727   }
00728 
00729   bool Matrix::PrintToBuffer( char* buffer, const unsigned maxlength, const unsigned precision )
00730   {
00731     if( MTX_PrintAutoWidth_ToBuffer( &m_Matrix, buffer, maxlength, precision ) )
00732       return true;
00733     else 
00734       return false;
00735   }
00736 
00737   bool Matrix::PrintFixedWidth( const char* path, const unsigned width, const unsigned precision, bool append )
00738   {
00739     if( MTX_Print( &m_Matrix, path, width, precision, append ) )
00740       return true;
00741     else 
00742       return false;
00743   }
00744 
00745   bool Matrix::PrintFixedWidth( std::string path, const unsigned width, const unsigned precision, bool append )
00746   {
00747     return PrintFixedWidth( path.c_str(), width, precision, append );
00748   }
00749 
00750   bool Matrix::PrintFixedWidthToBuffer( char* buffer, const unsigned maxlength, const unsigned width, const unsigned precision )
00751   {
00752     if( MTX_Print_ToBuffer( &m_Matrix, buffer, maxlength, width, precision ) )
00753       return true;
00754     else 
00755       return false;
00756   }
00757 
00758   bool Matrix::PrintDelimited( const char *path, const unsigned precision, const char delimiter, bool append )
00759   {
00760     if( MTX_PrintDelimited( &m_Matrix, path, precision, delimiter, append ) )
00761       return true;
00762     else 
00763       return false;
00764   }
00765 
00766   bool Matrix::PrintDelimited( std::string path, const unsigned precision, const char delimiter, bool append )
00767   {
00768     return PrintDelimited( path.c_str(), precision, delimiter, append );
00769   }
00770     
00771 
00772   bool Matrix::PrintDelimitedToBuffer( char *buffer, const unsigned maxlength, const unsigned precision, const char delimiter )
00773   {
00774     if( MTX_PrintDelimited_ToBuffer( &m_Matrix, buffer, maxlength, precision, delimiter ) )
00775       return true;
00776     else 
00777       return false;
00778   }
00779 
00780   bool Matrix::PrintRowToString( const unsigned row, char *buffer, const unsigned maxlength, const int width, const int precision )
00781   {
00782     if( MTX_PrintRowToString( &m_Matrix, row, buffer, maxlength, width, precision ) )
00783       return true;
00784     else
00785       return false;
00786   }
00787 
00788 
00789   bool Matrix::RemoveColumn( const unsigned col )
00790   {
00791     if( MTX_RemoveColumn( &m_Matrix, col ) )
00792       return true;
00793     else 
00794       return false;
00795   }
00796 
00797   bool Matrix::RemoveColumnsAfterIndex( const unsigned col )
00798   {
00799     if( MTX_RemoveColumnsAfterIndex( &m_Matrix, col ) )
00800       return true;
00801     else 
00802       return false;
00803   }
00804 
00805   bool Matrix::RemoveRowsAndColumns( const unsigned nrows, const unsigned rows[], const unsigned ncols, const unsigned cols[] )
00806   {
00807     if( MTX_RemoveRowsAndColumns( &m_Matrix, nrows, rows, ncols, cols ) )
00808       return true;
00809     else
00810       return false;
00811   }
00812 
00813   bool Matrix::InsertColumn( const Matrix &src, const unsigned dst_col, const unsigned src_col )
00814   {
00815     if( MTX_InsertColumn( &m_Matrix, &src.m_Matrix, dst_col, src_col ) )
00816       return true;
00817     else 
00818       return false;
00819   }
00820 
00821   bool Matrix::AddColumn( const Matrix &src, const unsigned src_col )
00822   {
00823     if( MTX_AddColumn( &m_Matrix, &src.m_Matrix, src_col ) )
00824       return true;
00825     else 
00826       return false;
00827   }
00828 
00829   bool Matrix::Concatonate( const Matrix &src )
00830   {
00831     if( MTX_Concatonate( &m_Matrix, &src.m_Matrix ) )
00832       return true;
00833     else 
00834       return false;
00835   }
00836 
00837   bool Matrix::Redim( const unsigned nrows, const unsigned ncols )
00838   {
00839     if( MTX_Redim( &m_Matrix, nrows, ncols ) )
00840       return true;
00841     else 
00842       return false;
00843   }
00844 
00845   bool Matrix::Resize( const unsigned nrows, const unsigned ncols )
00846   {
00847     if( MTX_Resize( &m_Matrix, nrows, ncols, m_Matrix.isReal ) )
00848       return true;
00849     else 
00850       return false;
00851   }
00852 
00853 
00854   bool Matrix::SetFromStaticMatrix( const double mat[], const unsigned nrows, const unsigned ncols )
00855   {
00856     if( MTX_SetFromStaticMatrix( &m_Matrix, mat, nrows, ncols ) )
00857       return true;
00858     else 
00859       return false;
00860   }
00861 
00862   bool Matrix::SetFromMatrixString(const char* strMatrix)
00863   {
00864     if( MTX_SetFromMatrixString( &m_Matrix, strMatrix ) )
00865       return true;
00866     else
00867       return false;
00868   }
00869 
00870   bool Matrix::CopyColumn( const unsigned src_col, Matrix &dst )
00871   {
00872     if( MTX_CopyColumn( &m_Matrix, src_col, &dst.m_Matrix ) )
00873       return true;
00874     else 
00875       return false;
00876   }
00877 
00878   bool Matrix::InsertSubMatrix( const Matrix &src, const unsigned dst_row, const unsigned dst_col )
00879   {
00880     if( MTX_InsertSubMatrix( &m_Matrix, &src.m_Matrix, dst_row, dst_col ) )
00881       return true;
00882     else 
00883       return false;
00884   }
00885 
00886   bool Matrix::Zero()
00887   {
00888     if( MTX_Zero( &m_Matrix ) )
00889       return true;
00890     else 
00891       return false;
00892   }
00893 
00894   bool Matrix::ZeroColumn( const unsigned col )
00895   {
00896     if( MTX_ZeroColumn( &m_Matrix, col ) )
00897       return true;
00898     else 
00899       return false;
00900   }
00901 
00902   bool Matrix::ZeroRow( const unsigned row )
00903   {
00904     if( MTX_ZeroRow( &m_Matrix, row ) )
00905       return true;
00906     else 
00907       return false;
00908   }
00909 
00910   bool Matrix::Fill( const double value )
00911   {
00912     if( MTX_Fill( &m_Matrix, value ) )
00913       return true;
00914     else 
00915       return false;
00916   }
00917 
00918   bool Matrix::FillColumn( const unsigned col, const double value )
00919   {
00920     if( MTX_FillColumn( &m_Matrix, col, value ) )
00921       return true;
00922     else 
00923       return false;
00924   }
00925 
00926   bool Matrix::FillRow( const unsigned row, const double value )
00927   {
00928     if( MTX_FillRow( &m_Matrix, row, value ) )
00929       return true;
00930     else 
00931       return false;
00932   }
00933 
00934   bool Matrix::FlipColumn( const unsigned col )
00935   {
00936     if( MTX_FlipColumn( &m_Matrix, col ) )
00937       return true;
00938     else 
00939       return false;
00940   }
00941 
00942   bool Matrix::FlipRow( const unsigned row )
00943   {
00944     if( MTX_FlipRow( &m_Matrix, row ) )
00945       return true;
00946     else 
00947       return false;
00948   }
00949 
00950   bool Matrix::Identity()
00951   {
00952     if( MTX_Identity( &m_Matrix ) )
00953       return true;
00954     else 
00955       return false;
00956   }
00957 
00958   bool Matrix::Identity(const unsigned dimension)
00959   {
00960     if( MTX_Malloc( &m_Matrix, dimension, dimension, true ) )
00961     {
00962       if( MTX_Identity( &m_Matrix ) )
00963         return true;
00964       else
00965         return false;
00966     }
00967     else
00968     {
00969       return false;
00970     }
00971   }
00972 
00973   bool Matrix::Inplace_Transpose()
00974   {
00975     if( MTX_TransposeInplace( &m_Matrix ) )
00976       return true;
00977     else 
00978       return false;
00979   }
00980 
00981   bool Matrix::Inplace_Round( const unsigned precision )
00982   {
00983     if( MTX_Round( &m_Matrix, precision ) )
00984       return true;
00985     else 
00986       return false;
00987   }
00988 
00989   bool Matrix::Inplace_Floor()
00990   {
00991     if( MTX_Floor( &m_Matrix ) )
00992       return true;
00993     else 
00994       return false;
00995   }
00996 
00997   bool Matrix::Inplace_Ceil()
00998   {
00999     if( MTX_Ceil( &m_Matrix ) )
01000       return true;
01001     else 
01002       return false;
01003   }
01004 
01005   bool Matrix::Inplace_Fix()
01006   {
01007     if( MTX_Fix( &m_Matrix ) )
01008       return true;
01009     else 
01010       return false;
01011   }
01012 
01013   bool Matrix::Inplace_AddScalar( const double scalar )
01014   {
01015     if( MTX_Add_Scalar( &m_Matrix, scalar ) )
01016       return true;
01017     else 
01018       return false;
01019   }
01020 
01021   bool Matrix::Inplace_SubtractScalar( const double scalar )
01022   {
01023     if( MTX_Subtract_Scalar( &m_Matrix, scalar ) )
01024       return true;
01025     else 
01026       return false;
01027   }
01028 
01029   bool Matrix::Inplace_MultiplyScalar( const double scalar )
01030   {
01031     if( MTX_Multiply_Scalar( &m_Matrix, scalar ) )
01032       return true;
01033     else 
01034       return false;
01035   }
01036 
01037   bool Matrix::Inplace_DivideScalar( const double scalar )
01038   {
01039     if( MTX_Divide_Scalar( &m_Matrix, scalar ) )
01040       return true;
01041     else 
01042       return false;
01043   }
01044 
01045   bool Matrix::Inplace_PowerScalar( const double scalar )
01046   {
01047     if( MTX_PowInplace( &m_Matrix, scalar, 0.0 ) ) 
01048       return true;
01049     else
01050       return false;
01051   }
01052 
01053   bool Matrix::Inplace_AddScalarComplex( const std::complex<double> cplx )
01054   {
01055     if( MTX_Add_ScalarComplex( &m_Matrix, cplx.real(), cplx.imag() ) )
01056       return true;
01057     else 
01058       return false;
01059   }
01060 
01061   bool Matrix::Inplace_SubtractScalarComplex( const std::complex<double> cplx )
01062   {
01063     if( MTX_Subtract_ScalarComplex( &m_Matrix, cplx.real(), cplx.imag() ) )
01064       return true;
01065     else 
01066       return false;
01067   }
01068 
01069   bool Matrix::Inplace_MultiplyScalarComplex( const std::complex<double> cplx )
01070   {
01071     if( MTX_Multiply_ScalarComplex( &m_Matrix, cplx.real(), cplx.imag() ) )
01072       return true;
01073     else 
01074       return false;
01075   }
01076 
01077   bool Matrix::Inplace_DivideScalarComplex( const std::complex<double> cplx )
01078   {
01079     if( MTX_Divide_ScalarComplex( &m_Matrix,  cplx.real(), cplx.imag() ) )
01080       return true;
01081     else 
01082       return false;
01083   }
01084 
01085   bool Matrix::Inplace_PowerScalarComplex( const std::complex<double> cplx )
01086   {
01087     if( MTX_PowInplace( &m_Matrix, cplx.real(), cplx.imag() ) ) 
01088       return true;
01089     else
01090       return false;
01091   }
01092 
01093   bool Matrix::Inplace_Abs()
01094   {
01095     if( MTX_Abs( &m_Matrix ) )
01096       return true;
01097     else 
01098       return false;
01099   }
01100 
01101   bool Matrix::Inplace_acos()
01102   {
01103     if( MTX_acos( &m_Matrix ) )
01104       return true;
01105     else 
01106       return false;
01107   }
01108 
01109   bool Matrix::Inplace_acosd()
01110   {
01111     if( MTX_acos( &m_Matrix ) )
01112     {
01113       if( MTX_Multiply_Scalar( &m_Matrix, RAD2DEG ) )
01114         return true;
01115       else
01116         return false;
01117     }
01118     else 
01119     {
01120       return false;
01121     }
01122   }
01123 
01124   bool Matrix::Inplace_acosh()
01125   {
01126     if( MTX_acosh( &m_Matrix ) )
01127       return true;
01128     else 
01129       return false;
01130   }
01131 
01132   bool Matrix::Inplace_angle()
01133   {
01134     if( MTX_angle( &m_Matrix ) )
01135       return true;
01136     else
01137       return false;
01138   }
01139 
01140   bool Matrix::Inplace_asin()
01141   {
01142     if( MTX_asin( &m_Matrix ) )
01143       return true;
01144     else 
01145       return false;
01146   }
01147 
01148   bool Matrix::Inplace_asind()
01149   {
01150     if( MTX_asin( &m_Matrix ) )
01151     {
01152       if( MTX_Multiply_Scalar( &m_Matrix, RAD2DEG ) )
01153         return true;
01154       else
01155         return false;
01156     }
01157     else 
01158     {
01159       return false;
01160     }
01161   }
01162 
01163   bool Matrix::Inplace_asinh()
01164   {
01165     if( MTX_asinh( &m_Matrix ) )
01166       return true;
01167     else 
01168       return false;
01169   }
01170 
01171   bool Matrix::Inplace_atan()
01172   {
01173     if( MTX_atan( &m_Matrix ) )
01174       return true;
01175     else
01176       return false;
01177   }
01178 
01179   bool Matrix::Inplace_atand()
01180   {
01181     if( MTX_atan( &m_Matrix ) )
01182     {
01183       if( MTX_Multiply_Scalar( &m_Matrix, RAD2DEG ) )
01184         return true;
01185       else
01186         return false;
01187     }
01188     else 
01189     {
01190       return false;
01191     }
01192   }
01193 
01194   bool Matrix::Inplace_atanh()
01195   {
01196     if( MTX_atanh( &m_Matrix ) )
01197       return true;
01198     else
01199       return false;
01200   }
01201 
01202   bool Matrix::Inplace_Sqr()
01203   {
01204     if( MTX_Sqr( &m_Matrix ) )
01205       return true;
01206     else 
01207       return false;
01208   }
01209 
01210   bool Matrix::Inplace_Sqrt()
01211   {
01212     if( MTX_Sqrt( &m_Matrix ) )
01213       return true;
01214     else 
01215       return false;
01216   }
01217 
01218   bool Matrix::Inplace_Exp()
01219   {
01220     if( MTX_Exp( &m_Matrix ) )
01221       return true;
01222     else 
01223       return false;
01224   }
01225 
01226   bool Matrix::Inplace_Ln()
01227   {
01228     if( MTX_Ln( &m_Matrix ) )
01229       return true;
01230     else 
01231       return false;
01232   }
01233 
01234   bool Matrix::Inplace_Increment()
01235   {
01236     if( MTX_Increment( &m_Matrix ) )
01237       return true;
01238     else 
01239       return false;
01240   }
01241 
01242   bool Matrix::Inplace_Decrement()
01243   {
01244     if( MTX_Decrement( &m_Matrix ) )
01245       return true;
01246     else 
01247       return false;
01248   }
01249 
01250   bool Matrix::Inplace_Add( const Matrix &B )
01251   {
01252     if( MTX_Add_Inplace( &m_Matrix, &B.m_Matrix ) )
01253       return true;
01254     else 
01255       return false;
01256   }
01257 
01258   bool Matrix::Inplace_Subtract( const Matrix &B )
01259   {
01260     if( MTX_Subtract_Inplace( &m_Matrix, &B.m_Matrix ) )
01261       return true;
01262     else 
01263       return false;
01264   }
01265 
01266   bool Matrix::Inplace_PreMultiply( const Matrix &B )
01267   {
01268     if( MTX_PreMultiply_Inplace( &m_Matrix, &B.m_Matrix ) )
01269       return true;
01270     else 
01271       return false;
01272   }
01273 
01274   bool Matrix::Inplace_PostMultiply( const Matrix &B )
01275   {
01276     if( MTX_PostMultiply_Inplace( &m_Matrix, &B.m_Matrix ) )
01277       return true;
01278     else 
01279       return false;
01280   }
01281 
01282   bool Matrix::Inplace_DotMultiply( const Matrix &B )
01283   {
01284     if( MTX_DotMultiply_Inplace( &m_Matrix, &B.m_Matrix ) )
01285       return true;
01286     else 
01287       return false;
01288   }
01289 
01290   bool Matrix::Inplace_DotDivide( const Matrix &B )
01291   {
01292     if( MTX_DotDivide_Inplace( &m_Matrix, &B.m_Matrix ) )
01293       return true;
01294     else 
01295       return false;
01296   }
01297 
01298   bool Matrix::Inplace_SortAscending()
01299   {
01300     if( MTX_SortAscending( &m_Matrix ) )
01301       return true;
01302     else 
01303       return false;
01304   }
01305 
01306   bool Matrix::Inplace_SortDescending()
01307   {
01308     if( MTX_SortDescending( &m_Matrix ) )
01309       return true;
01310     else 
01311       return false;
01312   }
01313 
01314   bool Matrix::Inplace_SortColumnAscending( const unsigned col )
01315   {
01316     if( MTX_SortColumnAscending( &m_Matrix, col ) )
01317       return true;
01318     else 
01319       return false;
01320   }
01321 
01322   bool Matrix::Inplace_SortColumnDescending( const unsigned col )
01323   {
01324     if( MTX_SortColumnDescending( &m_Matrix, col ) )
01325       return true;
01326     else 
01327       return false;
01328   }
01329 
01330   bool Matrix::Inplace_SortColumnIndexed( const unsigned col, Matrix &Index )
01331   {
01332     if( MTX_SortColumnIndexed( &m_Matrix, col, &Index.m_Matrix ) )
01333       return true;
01334     else 
01335       return false;
01336   }
01337 
01338   bool Matrix::Inplace_SortByColumn( const unsigned col )
01339   {
01340     if( MTX_SortByColumn( &m_Matrix, col ) )
01341       return true;
01342     else 
01343       return false;
01344   }
01345 
01346   bool Matrix::Inplace_Invert()
01347   {
01348     if( MTX_InvertInPlace( &m_Matrix ) )
01349       return true;
01350     else 
01351       return false;
01352   }
01353 
01354   bool Matrix::Inplace_InvertRobust()
01355   {
01356     if( MTX_InvertInPlaceRobust( &m_Matrix ) )
01357       return true;
01358     else 
01359       return false;
01360   }
01361 
01362   bool Matrix::Inplace_LowerTriangularInverse()
01363   {
01364     if( MTX_LowerTriangularInverseInplace( &m_Matrix ) )
01365       return true;
01366     else 
01367       return false;
01368   }
01369 
01370   bool Matrix::Inplace_FFT()
01371   {
01372     if( MTX_FFT_Inplace( &m_Matrix ) )
01373       return true;
01374     else
01375       return false;
01376   }
01377 
01378   bool Matrix::Inplace_IFFT()
01379   {
01380     if( MTX_IFFT_Inplace( &m_Matrix ) )
01381       return true;
01382     else
01383       return false;
01384   }
01385 
01386 
01387   bool Matrix::Add( const Matrix &B, const Matrix &C )
01388   {
01389     if( MTX_Add( &m_Matrix, &B.m_Matrix, &C.m_Matrix ) )
01390       return true;
01391     else 
01392       return false;
01393 
01394   }
01395 
01396   bool Matrix::Subtract( const Matrix &B, const Matrix &C )
01397   {
01398     if( MTX_Subtract( &m_Matrix, &B.m_Matrix, &C.m_Matrix ) )
01399       return true;
01400     else 
01401       return false;
01402   }
01403 
01404   bool Matrix::Multiply( const Matrix &B, const Matrix &C )
01405   {
01406     if( MTX_Multiply( &m_Matrix, &B.m_Matrix, &C.m_Matrix ) )
01407       return true;
01408     else 
01409       return false;
01410   }
01411 
01412 
01413   bool Matrix::Inplace_abs()
01414   {
01415     if( MTX_Abs( &m_Matrix ) )
01416       return true;
01417     else
01418       return false;
01419   }
01420 
01421   bool Matrix::Inplace_colon( double start, double increment, double end )
01422   {
01423     if( MTX_Colon( &m_Matrix, start, increment, end) )
01424       return true;
01425     else
01426       return false;
01427   }
01428 
01429   bool Matrix::Inplace_conj()
01430   {
01431     if( MTX_Conjugate( &m_Matrix ) )
01432       return true;
01433     else
01434       return false;
01435   }
01436 
01437   bool Matrix::Inplace_cos()
01438   {
01439     if( MTX_cos( &m_Matrix ) )
01440       return true;
01441     else
01442       return false;
01443   }
01444 
01445   bool Matrix::Inplace_cosh()
01446   {
01447     if( MTX_cosh( &m_Matrix ) )
01448       return true;
01449     else
01450       return false;
01451   }
01452 
01453   bool Matrix::Inplace_cot()
01454   {
01455     if( MTX_cot( &m_Matrix ) )
01456       return true;
01457     else
01458       return false;
01459   }
01460 
01461   bool Matrix::Inplace_coth()
01462   {
01463     if( MTX_coth( &m_Matrix ) )
01464       return true;
01465     else
01466       return false;
01467   }
01468   
01469   bool Matrix::Inplace_imag()
01470   {
01471     if( MTX_ConvertComplexToImag( &m_Matrix ) )
01472       return true;
01473     else
01474       return false;
01475   }
01476 
01477   bool Matrix::Inplace_exp()
01478   {
01479     if( MTX_Exp( &m_Matrix ) )
01480       return true;
01481     else
01482       return false;
01483   }
01484 
01485   bool Matrix::Inplace_eye( const unsigned nrows, const unsigned ncols )
01486   {
01487     if( MTX_Eye( &m_Matrix, nrows, ncols ) )
01488       return true;
01489     else
01490       return false;
01491   }
01492 
01493   bool Matrix::Inplace_log2()
01494   {
01495     if( MTX_Ln( &m_Matrix ) )
01496     {
01497       if( MTX_Divide_Scalar( &m_Matrix, log(2.0) ) )
01498         return true;
01499       else
01500         return false;
01501     }
01502     else
01503     {
01504       return false;
01505     }
01506   }
01507 
01508   bool Matrix::Inplace_log10()
01509   {
01510     if( MTX_Ln( &m_Matrix ) )
01511     {
01512       if( MTX_Divide_Scalar( &m_Matrix, log(10.0) ) )
01513         return true;
01514       else
01515         return false;
01516     }
01517     else
01518     {
01519       return false;
01520     }
01521   }
01522 
01523 
01524   bool Matrix::Inplace_ones( const unsigned nrows, const unsigned ncols )
01525   {
01526     if( m_Matrix.nrows == nrows && m_Matrix.ncols == ncols && m_Matrix.isReal )
01527     { 
01528       if( !MTX_Fill( &m_Matrix, 1.0 ) )
01529         return false;
01530     }
01531     else
01532     {
01533       if( !MTX_Malloc( &m_Matrix, nrows, ncols, TRUE ) )
01534         return false;
01535       if( !MTX_Fill( &m_Matrix, 1.0 ) )
01536         return false;
01537     }
01538     return true;
01539   }
01540 
01541   bool Matrix::Inplace_real()
01542   {
01543     if( MTX_ConvertComplexToReal( &m_Matrix ) )
01544       return true;
01545     else
01546       return false;
01547   }
01548 
01549   bool Matrix::Inplace_sin()
01550   {
01551     if( MTX_sin( &m_Matrix ) )
01552       return true;
01553     else
01554       return false;
01555   }
01556 
01557   bool Matrix::Inplace_sinc()
01558   {
01559     if( MTX_sinc( &m_Matrix ) )
01560       return true;
01561     else
01562       return false;
01563   }
01564 
01565   bool Matrix::Inplace_sinh()
01566   {
01567     if( MTX_sinh( &m_Matrix ) )
01568       return true;
01569     else
01570       return false;
01571   }
01572 
01573   bool Matrix::Inplace_sqrt()
01574   {
01575     if( MTX_Sqrt( &m_Matrix ) )
01576       return true;
01577     else
01578       return false;
01579   }
01580 
01581   bool Matrix::Inplace_tan()
01582   {
01583     if( MTX_tan( &m_Matrix ) )
01584       return true;
01585     else
01586       return false;
01587   }
01588 
01589   bool Matrix::Inplace_tanh()
01590   {
01591     if( MTX_tanh( &m_Matrix ) )
01592       return true;
01593     else
01594       return false;
01595   }
01596 
01597   bool Matrix::Inplace_zeros( const unsigned nrows, const unsigned ncols )
01598   {
01599     if( m_Matrix.nrows == nrows && m_Matrix.ncols == ncols && m_Matrix.isReal )
01600     { 
01601       if( !MTX_Fill( &m_Matrix, 0.0 ) )
01602         return false;
01603     }
01604     else
01605     {
01606       if( !MTX_Malloc( &m_Matrix, nrows, ncols, TRUE ) )
01607         return false;
01608       if( !MTX_Fill( &m_Matrix, 0.0 ) )
01609         return false;
01610     }
01611     return true;
01612   }
01613   
01614 
01615   bool Matrix::GetStats_MaxAbs(unsigned &row, unsigned &col, double &value )
01616   {
01617     if( MTX_MaxAbsIndex( &m_Matrix, &value, &row, &col ) )
01618       return true;
01619     else 
01620       return false;
01621   }
01622 
01623   bool Matrix::GetStats_Max(unsigned &row, unsigned &col, double &re, double &im )
01624   {
01625     if( MTX_MaxIndex( &m_Matrix, &re, &im, &row, &col ) )
01626       return true;
01627     else 
01628       return false;
01629   }
01630 
01631   bool Matrix::GetStats_MaxVal(double &re, double &im )
01632   {
01633     if( MTX_Max( &m_Matrix, &re, &im ) )
01634       return true;
01635     else 
01636       return false;
01637   }
01638 
01639   bool Matrix::GetStats_MaxAbsCol(const unsigned col, double &value, unsigned &row )
01640   {
01641     if( MTX_MaxAbsColIndex( &m_Matrix, col, &value, &row ) )
01642       return true;
01643     else 
01644       return false;
01645   }
01646 
01647   bool Matrix::GetStats_MaxCol(const unsigned col, double &re, double &im, unsigned &row )
01648   {
01649     if( MTX_MaxColIndex( &m_Matrix, col, &re, &im, &row ) )
01650       return true;
01651     else 
01652       return false;
01653   }
01654 
01655   bool Matrix::GetStats_MaxColVal(const unsigned col, double &re, double &im )
01656   {
01657     if( MTX_MaxColumn( &m_Matrix, col, &re, &im ) )
01658       return true;
01659     else 
01660       return false;
01661   }
01662 
01663   bool Matrix::GetStats_MaxAbsRow(const unsigned row, double &value, unsigned &col )
01664   {
01665     if( MTX_MaxAbsRowIndex( &m_Matrix, row, &value, &col ) )
01666       return true;
01667     else 
01668       return false;
01669   }
01670 
01671   bool Matrix::GetStats_MaxRow(const unsigned row, double &re, double &im, unsigned &col )
01672   {
01673     if( MTX_MaxRowIndex( &m_Matrix, row, &re, &im, &col ) )
01674       return true;
01675     else 
01676       return false;
01677   }
01678 
01679   bool Matrix::GetStats_MaxRowVal(const unsigned row, double &re, double &im )
01680   {
01681     if( MTX_MaxRow( &m_Matrix, row, &re, &im ) )
01682       return true;
01683     else 
01684       return false;
01685   }
01686 
01687   bool Matrix::GetStats_MinAbs(unsigned &row, unsigned &col, double &value )
01688   {
01689     if( MTX_MinAbsIndex( &m_Matrix, &value, &row, &col ) )
01690       return true;
01691     else 
01692       return false;
01693   }
01694 
01695   bool Matrix::GetStats_Min(unsigned &row, unsigned &col, double &re, double &im )
01696   {
01697     if( MTX_MinIndex( &m_Matrix, &re, &im, &row, &col ) )
01698       return true;
01699     else 
01700       return false;
01701   }
01702 
01703   bool Matrix::GetStats_MinVal(double &re, double &im )
01704   {
01705     if( MTX_Min( &m_Matrix, &re, &im ) )
01706       return true;
01707     else 
01708       return false;
01709   }
01710 
01711   bool Matrix::GetStats_MinAbsCol(const unsigned col, double &value, unsigned &row )
01712   {
01713     if( MTX_MinAbsColIndex( &m_Matrix, col, &value, &row ) )
01714       return true;
01715     else 
01716       return false;
01717   }
01718 
01719   bool Matrix::GetStats_MinCol(const unsigned col, double &re, double &im, unsigned &row )
01720   {
01721     if( MTX_MinColIndex( &m_Matrix, col, &re, &im, &row ) )
01722       return true;
01723     else 
01724       return false;
01725   }
01726 
01727 
01728   bool Matrix::GetStats_MinColVal(const unsigned col, double &re, double &im )
01729   {
01730     if( MTX_MinColumn( &m_Matrix, col, &re, &im ) )
01731       return true;
01732     else 
01733       return false;
01734   }
01735 
01736   bool Matrix::GetStats_MinAbsRow(const unsigned row, double &value, unsigned &col )
01737   {
01738     if( MTX_MinAbsRowIndex( &m_Matrix, row, &value, &col ) )
01739       return true;
01740     else 
01741       return false;
01742   }
01743 
01744   bool Matrix::GetStats_MinRow(const unsigned row, double &re, double &im, unsigned &col )
01745   {
01746     if( MTX_MinRowIndex( &m_Matrix, row, &re, &im, &col ) )
01747       return true;
01748     else 
01749       return false;
01750   }
01751 
01752   bool Matrix::GetStats_MinRowVal(const unsigned row, double &re, double &im )
01753   {
01754     if( MTX_MinRow(  &m_Matrix, row, &re, &im ) )
01755       return true;
01756     else 
01757       return false;
01758   }
01759 
01760   bool Matrix::GetStats_ColRange( const unsigned col, double &re, double &im )
01761   {
01762     if( MTX_ColumnRange( &m_Matrix, col, &re, &im ) )
01763       return true;
01764     else 
01765       return false;
01766   }
01767 
01768   bool Matrix::GetStats_RowRange( const unsigned row, double &re, double &im )
01769   {
01770     if( MTX_RowRange( &m_Matrix, row, &re, &im ) )
01771       return true;
01772     else 
01773       return false;
01774   }
01775 
01776   bool Matrix::GetStats_Range( double &re, double &im )
01777   {
01778     if( MTX_Range( &m_Matrix, &re, &im ) )
01779       return true;
01780     else 
01781       return false;
01782   }
01783 
01784   bool Matrix::GetStats_ColumnSum( const unsigned col, double &re, double &im )
01785   {
01786     if( MTX_ColumnSum( &m_Matrix, col, &re, &im ) )
01787       return true;
01788     else 
01789       return false;
01790   }
01791 
01792   bool Matrix::GetStats_RowSum( const unsigned row, double &re, double &im )
01793   {
01794     if( MTX_RowSum( &m_Matrix, row, &re, &im ) )
01795       return true;
01796     else 
01797       return false;
01798   }
01799 
01800   bool Matrix::GetStats_Sum( double &re, double &im )
01801   {
01802     if( MTX_Sum( &m_Matrix, &re, &im ) )
01803       return true;
01804     else 
01805       return false;
01806   }
01807 
01808   bool Matrix::GetStats_ColumnMean( const unsigned col, double &re, double &im )
01809   {
01810     if( MTX_ColumnMean( &m_Matrix, col, &re, &im ) )
01811       return true;
01812     else 
01813       return false;
01814   }
01815 
01816   bool Matrix::GetStats_RowMean( const unsigned row, double &re, double &im )
01817   {
01818     if( MTX_RowMean( &m_Matrix, row, &re, &im ) )
01819       return true;
01820     else 
01821       return false;
01822   }
01823 
01824   bool Matrix::GetStats_Mean( double &re, double &im )
01825   {
01826     if( MTX_Mean( &m_Matrix, &re, &im ) )
01827       return true;
01828     else 
01829       return false;
01830   }
01831 
01832   bool Matrix::GetStats_ColumnStdev( const unsigned col, double &value )
01833   {
01834     if( MTX_ColumnStdev( &m_Matrix, col, &value ) )
01835       return true;
01836     else 
01837       return false;
01838   }
01839 
01840   bool Matrix::GetStats_RowStdev( const unsigned row, double &value )
01841   {
01842     if( MTX_RowStdev( &m_Matrix, row, &value ) )
01843       return true;
01844     else 
01845       return false;
01846   }
01847 
01848   bool Matrix::GetStats_Stdev( double &value )
01849   {
01850     if( MTX_Stdev( &m_Matrix, &value ) )
01851       return true;
01852     else 
01853       return false;
01854   }
01855 
01856   bool Matrix::GetStats_ColumnVar( const unsigned col, double &value )
01857   {
01858     if( MTX_ColumnVar( &m_Matrix, col, &value ) )
01859       return true;
01860     else 
01861       return false;
01862   }
01863 
01864   bool Matrix::GetStats_RowVar( const unsigned row, double &value )
01865   {
01866     if( MTX_RowVar( &m_Matrix, row, &value ) )
01867       return true;
01868     else 
01869       return false;
01870   }
01871 
01872   bool Matrix::GetStats_Var( double &value )
01873   {
01874     if( MTX_Var( &m_Matrix, &value ) )
01875       return true;
01876     else 
01877       return false;
01878   }
01879 
01880   bool Matrix::GetStats_ColumnNorm( const unsigned col, double &value )
01881   {
01882     if( MTX_ColumnNorm( &m_Matrix, col, &value ) )
01883       return true;
01884     else 
01885       return false;
01886   }
01887 
01888   bool Matrix::GetStats_RowNorm( const unsigned row, double &value )
01889   {
01890     if( MTX_RowNorm( &m_Matrix, row, &value ) )
01891       return true;
01892     else 
01893       return false;
01894   }
01895 
01896   bool Matrix::GetStats_Norm( double &value )
01897   {
01898     if( MTX_Norm( &m_Matrix, &value ) )
01899       return true;
01900     else 
01901       return false;
01902   }
01903 
01904   bool Matrix::GetStats_ColumnRMS( const unsigned col, double &value )
01905   {
01906     if( MTX_ColumnRMS( &m_Matrix, col, &value ) )
01907       return true;
01908     else 
01909       return false;
01910   }
01911 
01912   bool Matrix::GetStats_RowRMS( const unsigned row, double &value )
01913   {
01914     if( MTX_RowRMS( &m_Matrix, row, &value ) )
01915       return true;
01916     else 
01917       return false;
01918   }
01919 
01920   bool Matrix::GetStats_RMS( double &value )
01921   {
01922     if( MTX_RMS( &m_Matrix, &value ) )
01923       return true;
01924     else 
01925       return false;
01926   }
01927 
01928   bool Matrix::GetStats_ColumnSkewness( const unsigned col, double &re, double &im )
01929   {
01930     if( MTX_ColumnSkewness( &m_Matrix, col, &re, &im ) )
01931       return true;
01932     else 
01933       return false;
01934   }
01935 
01936   bool Matrix::GetStats_RowSkewness( const unsigned row, double &re, double &im )
01937   {
01938     if( MTX_RowSkewness( &m_Matrix, row, &re, &im ) )
01939       return true;
01940     else 
01941       return false;
01942   }
01943 
01944   bool Matrix::GetStats_Skewness( double &re, double &im )
01945   {
01946     if( MTX_Skewness( &m_Matrix, &re, &im ) )
01947       return true;
01948     else 
01949       return false;
01950   }
01951 
01952   bool Matrix::GetStats_ColumnKurtosis( const unsigned col, double &re, double &im )
01953   {
01954     if( MTX_ColumnKurtosis( &m_Matrix, col, &re, &im ) )
01955       return true;
01956     else 
01957       return false;
01958   }
01959 
01960   bool Matrix::GetStats_RowKurtosis( const unsigned row, double &re, double &im )
01961   {
01962     if( MTX_RowKurtosis( &m_Matrix, row, &re, &im ) )
01963       return true;
01964     else 
01965       return false;
01966   }
01967 
01968   bool Matrix::GetStats_Kurtosis( double &re, double &im )
01969   {
01970     if( MTX_Kurtosis( &m_Matrix, &re, &im ) )
01971       return true;
01972     else 
01973       return false;
01974   }
01975 
01976   bool Matrix::GetTrace( double &re, double &im )
01977   {
01978     if( MTX_Trace( &m_Matrix, &re, &im ) )
01979       return true;
01980     else 
01981       return false;
01982   }
01983 
01984   bool Matrix::GetDeterminant( double &re, double &im )
01985   {
01986     if( MTX_Det( &m_Matrix, &re, &im ) )
01987       return true;
01988     else 
01989       return false;
01990   }
01991 
01992   bool Matrix::GetDiagonal( Matrix& DiagonalVector )
01993   {
01994     if( MTX_Diagonal( &m_Matrix, &DiagonalVector.m_Matrix ) )
01995       return true;
01996     else 
01997       return false;
01998   }
01999 
02000   bool Matrix::GetColumnMovAvg( const unsigned col, const unsigned lead, const unsigned lag, Matrix &MovAvg )
02001   {
02002     if( MTX_ColumnMovAvg( &m_Matrix, col, lead, lag, &MovAvg.m_Matrix ) )
02003       return true;
02004     else 
02005       return false;
02006   }
02007 
02008   bool Matrix::GetMovAvg( const unsigned lead, const unsigned lag, Matrix &MovAvg )
02009   {
02010     if( MTX_MovAvg( &m_Matrix, lead, lag, &MovAvg.m_Matrix ) )
02011       return true;
02012     else 
02013       return false;
02014   }
02015 
02016   bool Matrix::GetATAInverse( Matrix &InvATA )
02017   {
02018     if( MTX_ATAInverse( &m_Matrix, &InvATA.m_Matrix ) )
02019       return true;
02020     else 
02021       return false;
02022   }
02023 
02024   bool Matrix::GetLUFactorization( bool &isFullRank, Matrix &P, Matrix &L, Matrix &U )
02025   {
02026     BOOL b_isFullRank;
02027     if( MTX_LUFactorization( &m_Matrix, &b_isFullRank, &P.m_Matrix, &L.m_Matrix, &U.m_Matrix ) )
02028     {
02029       if( b_isFullRank )
02030         isFullRank = true;
02031       else
02032         isFullRank = false;
02033 
02034       return true;
02035     }
02036     else 
02037     {
02038       if( b_isFullRank )
02039         isFullRank = true;
02040       else
02041         isFullRank = false;
02042 
02043       return false;
02044     }
02045   }
02046 
02047   bool Matrix::GetIndexedValues( Matrix& RowIndex, Matrix& ColIndex, Matrix& Result )
02048   {
02049     Matrix _rowIndex; // a copy if needed
02050     Matrix _colIndex; // a copy if needed
02051     if( !RowIndex.m_Matrix.isReal )
02052     {
02053       if( !MTX_Real( &RowIndex.m_Matrix, &_rowIndex.m_Matrix ) )
02054         return false;
02055     }
02056     if( !ColIndex.m_Matrix.isReal )
02057     {
02058       if( !MTX_Real( &ColIndex.m_Matrix, &_colIndex.m_Matrix ) )
02059         return false;
02060     }
02061 
02062     if( !_rowIndex.isEmpty() )
02063     {
02064       if( !_colIndex.isEmpty() )
02065       {
02066         if( MTX_IndexedValues( &m_Matrix, &_rowIndex.m_Matrix, &_colIndex.m_Matrix, &Result.m_Matrix ) )
02067           return true;
02068         else
02069           return false;
02070       }
02071       else
02072       {
02073         if( MTX_IndexedValues( &m_Matrix, &_rowIndex.m_Matrix, &ColIndex.m_Matrix, &Result.m_Matrix ) )
02074           return true;
02075         else
02076           return false;
02077       }
02078     }
02079     else
02080     {
02081       if( !_colIndex.isEmpty() )
02082       {
02083         if( MTX_IndexedValues( &m_Matrix, &RowIndex.m_Matrix, &_colIndex.m_Matrix, &Result.m_Matrix ) )
02084           return true;
02085         else
02086           return false;
02087       }
02088       else
02089       {
02090         if( MTX_IndexedValues( &m_Matrix, &RowIndex.m_Matrix, &ColIndex.m_Matrix, &Result.m_Matrix ) )
02091           return true;
02092         else
02093           return false;
02094       }
02095     }    
02096   }
02097 
02098 
02099   bool Matrix::SetIndexedValues( Matrix& RowIndex, Matrix& ColIndex, Matrix& SourceData )
02100   {
02101     Matrix _rowIndex; // a copy if needed
02102     Matrix _colIndex; // a copy if needed
02103     if( !RowIndex.m_Matrix.isReal )
02104     {
02105       if( !MTX_Real( &RowIndex.m_Matrix, &_rowIndex.m_Matrix ) )
02106         return false;
02107     }
02108     if( !ColIndex.m_Matrix.isReal )
02109     {
02110       if( !MTX_Real( &ColIndex.m_Matrix, &_colIndex.m_Matrix ) )
02111         return false;
02112     }
02113 
02114     if( !_rowIndex.isEmpty() )
02115     {
02116       if( !_colIndex.isEmpty() )
02117       {
02118         if( MTX_SetIndexedValues( &m_Matrix, &_rowIndex.m_Matrix, &_colIndex.m_Matrix, &SourceData.m_Matrix ) )
02119           return true;
02120         else
02121           return false;
02122       }
02123       else
02124       {
02125         if( MTX_SetIndexedValues( &m_Matrix, &_rowIndex.m_Matrix, &ColIndex.m_Matrix, &SourceData.m_Matrix ) )
02126           return true;
02127         else
02128           return false;
02129       }
02130     }
02131     else
02132     {
02133       if( !_colIndex.isEmpty() )
02134       {
02135         if( MTX_SetIndexedValues( &m_Matrix, &RowIndex.m_Matrix, &_colIndex.m_Matrix, &SourceData.m_Matrix ) )
02136           return true;
02137         else
02138           return false;
02139       }
02140       else
02141       {
02142         if( MTX_SetIndexedValues( &m_Matrix, &RowIndex.m_Matrix, &ColIndex.m_Matrix, &SourceData.m_Matrix ) )
02143           return true;
02144         else
02145           return false;
02146       }
02147     }    
02148   }
02149 
02150 
02151   std::string Matrix::GetMatrixComment()
02152   {
02153     std::string result;
02154     if( m_Matrix.comment != NULL )
02155       result = m_Matrix.comment;
02156     
02157     return result;
02158   }
02159 
02160 
02161   bool Matrix::TimeWindow( 
02162     const unsigned timeColumn, //!< The column containing time.
02163     const double startTime,    //!< The specified start time (inclusive).
02164     const double duration,     //!< The duration to include.
02165     const double rolloverTime  //!< The potential time at which system time rolls over.
02166     )
02167   {
02168     if( MTX_TimeWindow(
02169       &m_Matrix, 
02170       timeColumn, 
02171       startTime,
02172       duration,
02173       rolloverTime ) )
02174       return true;
02175     else 
02176       return false;
02177   }
02178 
02179   bool Matrix::TimeLimit( 
02180     const unsigned timeColumn, //!< The column containing time
02181     const double startTime,    //!< The specified start time (inclusive)
02182     const double endTime       //!< The duration to include
02183     )
02184   {
02185     if( MTX_TimeLimit(
02186       &m_Matrix,
02187       timeColumn,
02188       startTime,
02189       endTime ) )
02190       return true;
02191     else 
02192       return false;
02193   }
02194 
02195   bool Matrix::TimeMatch( 
02196     Matrix &A,                   //!< The matrix with interpolation times
02197     const unsigned timeColumnA,  //!< The zero based column index for matrix A
02198     Matrix &B,                   //!< The matrix to be interpolated
02199     const unsigned timeColumnB,  //!< The zero based column index for matrix B
02200     const unsigned precision,    //!< The rounding precision used for time matching, 0 = whole, 1 = 0.1, 2 = 0.01, etc
02201     const double rolloverTime    //!< The rollover time, e.g. 60 s for minute based timing, 0.0 means rollovers not allowed
02202     )
02203   {
02204     // check that the mtx engine is initialized
02205     if( !m_IsMTXInitialized )
02206     {
02207       if( !MTX_Initialize_MTXEngine() )
02208       {
02209         m_IsMTXInitialized = false;
02210         StaticMatrixError( "Matrix", "Failed to initialize the MTX Engine. Try commenting out #define MTX_SIMD_OPTIMIZED in cmatrix.h" );
02211       }
02212       else
02213       {
02214         m_IsMTXInitialized = true;
02215       }
02216     }
02217 
02218     if( MTX_TimeMatch(
02219       &A.m_Matrix,
02220       timeColumnA,
02221       &B.m_Matrix,
02222       timeColumnB,
02223       precision,
02224       rolloverTime ) )
02225       return true;
02226     else 
02227       return false;
02228   }
02229 
02230   bool Matrix::Interpolate( 
02231     Matrix &A,                    //!< The matrix with interpolation times
02232     const unsigned timeColumnA,   //!< The zero based column index for matrix A
02233     Matrix &B,                    //!< The matrix to be interpolated
02234     const unsigned timeColumnB,   //!< The zero based column index for matrix B
02235     const double maxInterpolationInterval, //!< The largest interpolation interval allowed
02236     const double rolloverTime     //!< The rollover time, e.g. 60 s for minute based timing, 0.0 means rollovers not allowed
02237     )
02238   {
02239     // check that the mtx engine is initialized
02240     if( !m_IsMTXInitialized )
02241     {
02242       if( !MTX_Initialize_MTXEngine() )
02243       {
02244         m_IsMTXInitialized = false;
02245         StaticMatrixError( "Matrix", "Failed to initialize the MTX Engine. Try commenting out #define MTX_SIMD_OPTIMIZED in cmatrix.h" );
02246       }
02247       else
02248       {
02249         m_IsMTXInitialized = true;
02250       }
02251     }
02252 
02253     if( MTX_Interpolate(
02254       &A.m_Matrix,
02255       timeColumnA,
02256       &B.m_Matrix,
02257       timeColumnB,
02258       maxInterpolationInterval,
02259       rolloverTime ) )
02260       return true;
02261     else 
02262       return false;
02263   }
02264 
02265 
02266 
02267   // Return the column matrix specified by the column index. Returns (nrows x 1).
02268   Matrix  Matrix::Column(const unsigned col)
02269   {
02270     Matrix A;
02271     if( !MTX_CopyColumn( &m_Matrix, col, &A.m_Matrix ) )
02272     {
02273       MatrixError( "Column", "Unable to copy the source matrix column." );
02274     }
02275     return A;
02276   }
02277 
02278   // Return the row matrix specified by the column index. Returns (ncols x 1).
02279   Matrix  Matrix::Row(const unsigned row)
02280   {
02281     Matrix A;
02282     if( !MTX_CopyRow(&m_Matrix, row, &A.m_Matrix ) )
02283     {
02284       MatrixError( "Column", "Unable to copy the source matrix column." );
02285     }
02286     return A;
02287   }
02288 
02289   // Return the tranpose of the matrix.
02290   Matrix  Matrix::Transpose()
02291   {
02292     Matrix A;
02293     if( !MTX_Transpose( &m_Matrix, &A.m_Matrix ) )
02294     {
02295       MatrixError( "Column", "Unable to transpose the source matrix." );
02296     }
02297     return A;
02298   }
02299 
02300   // Return the tranpose of the matrix.
02301   Matrix  Matrix::T()
02302   {
02303     return Transpose();
02304   }
02305 
02306   // Return the diagonal of the matrix as a vector.
02307   Matrix  Matrix::Diagonal()
02308   {
02309     Matrix A;
02310     if( !MTX_Diagonal( &m_Matrix, &A.m_Matrix ) )
02311     {
02312       MatrixError( "Diagonal", "Unable to get the diagonal of the source matrix." );
02313     }
02314     return A;
02315   }
02316 
02317   // Return the inverse of the matrix.
02318   Matrix  Matrix::Inverse()
02319   {
02320     Matrix A;
02321     if( !MTX_Copy( &m_Matrix, &A.m_Matrix ) )
02322     {
02323       MatrixError( "Inverse", "Unable to copy the source matrix." );
02324     }
02325     if( !MTX_InvertInPlace( &A.m_Matrix ) )
02326     {
02327       MatrixError( "Inverse", "Unable to invert the matrix." );
02328     }
02329     return A;
02330   }
02331 
02332   // Return the inverse of the matrix.
02333   Matrix  Matrix::Inv()// short version
02334   {
02335     return Inverse();
02336   }
02337 
02338   // Return the Fourier Transform of each column of the matrix. Power of two uses FFT, otherwise fast DFT.
02339   Matrix  Matrix::FFT()
02340   {
02341     Matrix A;
02342     if( !MTX_FFT( &m_Matrix, &A.m_Matrix ) )
02343     {
02344       MatrixError( "FFT", "Unable to perform the FFT." );
02345     }
02346     return A;
02347   }
02348 
02349   // Return the inverse Fourier Transform of each column of the matrix. Power of two uses IFFT, otherwise fast IDFT.
02350   Matrix  Matrix::IFFT()
02351   {
02352     Matrix A;
02353     if( !MTX_IFFT( &m_Matrix, &A.m_Matrix ) )
02354     {
02355       MatrixError( "IFFT", "Unable to perform the IFFT." );
02356     }
02357     return A;
02358   }
02359 
02360 
02361 
02362   /// Get a reference to an element in the matrix to set its value.
02363   Matrix::Element& Matrix::operator() (unsigned row, unsigned col)
02364   {
02365     if( IndexCheck(row,col) )
02366     {
02367       m_MatrixElement.m_row = row;
02368       m_MatrixElement.m_col = col;
02369     }
02370     else
02371     {
02372       // This code should not be reached!
02373       m_MatrixElement.m_row = 0;
02374       m_MatrixElement.m_col = 0;
02375     }
02376     return m_MatrixElement; 
02377   }
02378 
02379 
02380   /// Get a reference to an element in the matrix as a column or row vector to set its value.
02381   Matrix::Element& Matrix::operator() (unsigned index)
02382   {
02383     if( IndexCheck( index ) )
02384     {
02385       if( m_Matrix.ncols == 1 ) // column array
02386       {
02387         m_MatrixElement.m_row = index;
02388         m_MatrixElement.m_col = 0;
02389       }
02390       else if( m_Matrix.nrows == 1 ) // row array
02391       {
02392         m_MatrixElement.m_row = 0;
02393         m_MatrixElement.m_col = index;
02394       }
02395       else
02396       {
02397         // access the matrix as a singular column array
02398         m_MatrixElement.m_col = index / m_Matrix.nrows;
02399         m_MatrixElement.m_row = index - m_MatrixElement.m_col*m_Matrix.nrows;
02400       }
02401     }
02402     else
02403     {
02404       // This code should not be reached!
02405       m_MatrixElement.m_row = 0;
02406       m_MatrixElement.m_col = 0;
02407     }
02408 
02409     return m_MatrixElement;
02410   }
02411 
02412 
02413   Matrix::Element::Element(MTX& mtx)
02414     : m_mtx(mtx), m_row(0), m_col(0)
02415   {
02416     // Note that there is no index checking at this level. The 
02417     // index checking is performed at the Matrix operator() level.
02418   }
02419 
02420   Matrix::Element::~Element()
02421   {}
02422 
02423   const double Matrix::Element::real()
02424   {
02425     if( m_mtx.isReal )
02426     {
02427       return m_mtx.data[m_col][m_row];
02428     }
02429     else
02430     {
02431       return m_mtx.cplx[m_col][m_row].re;
02432     }
02433   }
02434   
02435   const double Matrix::Element::imag()
02436   {
02437     if( m_mtx.isReal )
02438     {
02439       return 0.0;
02440     }
02441     else
02442     {
02443       return m_mtx.cplx[m_col][m_row].im;
02444     }
02445   }
02446 
02447   const Matrix::Element& Matrix::Element::operator= (double v)
02448   {
02449     if( m_mtx.isReal )
02450     {
02451       m_mtx.data[m_col][m_row] = v;
02452     }
02453     else
02454     {
02455       m_mtx.cplx[m_col][m_row].re = v;
02456       m_mtx.cplx[m_col][m_row].im = 0.0;
02457     }
02458     return *this;
02459   }
02460   
02461   const Matrix::Element& Matrix::Element::operator= (std::complex<double> v)
02462   {
02463     if( m_mtx.isReal )
02464     {
02465       if( v.imag() != 0.0 )
02466       {
02467         // This is on the fly conversion to a complex matrix!
02468         if( !MTX_ConvertRealToComplex( &m_mtx ) )
02469         {
02470           MTX_Free( &m_mtx );
02471           Matrix::StaticMatrixError( "Element::operator=", "Unable to convert matrix from real to complex" );
02472           return *this;
02473         }
02474       }
02475       else
02476       {
02477         m_mtx.data[m_col][m_row] = v.real();
02478         return *this;
02479       }
02480     }
02481     m_mtx.cplx[m_col][m_row].re = v.real();
02482     m_mtx.cplx[m_col][m_row].im = v.imag();
02483     return *this;
02484   }
02485 
02486   const Matrix::Element& Matrix::Element::operator= (Element v)
02487   {
02488     if( v.m_mtx.isReal )
02489     {
02490       if( m_mtx.isReal )
02491       {
02492         m_mtx.data[m_col][m_row] = v.m_mtx.data[v.m_col][v.m_row];
02493       }
02494       else
02495       {
02496         m_mtx.cplx[m_col][m_row].re = v.m_mtx.data[v.m_col][v.m_row];
02497         m_mtx.cplx[m_col][m_row].im = 0.0;
02498       }
02499     }
02500     else
02501     {
02502       if( m_mtx.isReal )
02503       {
02504         // This is on the fly conversion to a complex matrix!
02505         if( !MTX_ConvertRealToComplex( &m_mtx ) )
02506         {
02507           MTX_Free( &m_mtx );
02508           Matrix::StaticMatrixError( "Element::operator=", "Unable to convert matrix from real to complex" );
02509           return *this;
02510         }        
02511       }
02512       
02513       m_mtx.cplx[m_col][m_row].re = v.m_mtx.cplx[v.m_col][v.m_row].re;
02514       m_mtx.cplx[m_col][m_row].im = v.m_mtx.cplx[v.m_col][v.m_row].im;      
02515     }
02516     return *this;
02517   }
02518 
02519 
02520   Matrix::Element::operator const std::complex<double>() const
02521   {
02522     if( m_mtx.isReal )
02523     {
02524       std::complex<double> v( m_mtx.data[m_col][m_row], 0.0 );
02525       return v;
02526     }
02527     else
02528     {
02529       std::complex<double> v( m_mtx.cplx[m_col][m_row].re, m_mtx.cplx[m_col][m_row].im );
02530       return v;
02531     }
02532   }
02533 
02534 
02535   void Matrix::Element::operator+= (const double scalar)
02536   {
02537     if( m_mtx.isReal )
02538     {
02539       m_mtx.data[m_col][m_row] += scalar;
02540     }
02541     else
02542     {
02543       m_mtx.cplx[m_col][m_row].re += scalar;
02544     }
02545   }
02546 
02547   void Matrix::Element::operator+= (const std::complex<double>& v)
02548   {
02549     if( m_mtx.isReal )
02550     {
02551       if( v.imag() != 0.0 )
02552       {
02553         // This is on the fly conversion to a complex matrix!
02554         if( !MTX_ConvertRealToComplex( &m_mtx ) )
02555         {
02556           MTX_Free( &m_mtx );
02557           Matrix::StaticMatrixError( "Element::operator=", "Unable to convert matrix from real to complex" );
02558           return;
02559         }
02560       }
02561       else
02562       {
02563         m_mtx.data[m_col][m_row] += v.real();
02564         return;
02565       }
02566     }
02567     
02568     m_mtx.cplx[m_col][m_row].re += v.real();
02569     m_mtx.cplx[m_col][m_row].im += v.imag();    
02570   }
02571   
02572   void Matrix::Element::operator+= (const Element& v)
02573   {
02574     std::complex<double> cplx = (const std::complex<double>)v;
02575     *this += cplx;
02576   }
02577 
02578 
02579   void Matrix::Element::operator-= (const double scalar)
02580   {
02581     if( m_mtx.isReal )
02582     {
02583       m_mtx.data[m_col][m_row] -= scalar;
02584     }
02585     else
02586     {
02587       m_mtx.cplx[m_col][m_row].re -= scalar;
02588     }
02589   }
02590 
02591   void Matrix::Element::operator-= (const std::complex<double>& v)
02592   {
02593     if( m_mtx.isReal )
02594     {
02595       if( v.imag() != 0.0 )
02596       {
02597         // This is on the fly conversion to a complex matrix!
02598         if( !MTX_ConvertRealToComplex( &m_mtx ) )
02599         {
02600           MTX_Free( &m_mtx );
02601           Matrix::StaticMatrixError( "Element::operator=", "Unable to convert matrix from real to complex" );
02602           return;
02603         }
02604       }
02605       else
02606       {
02607         m_mtx.data[m_col][m_row] -= v.real();
02608         return;
02609       }
02610     }
02611     
02612     m_mtx.cplx[m_col][m_row].re -= v.real();
02613     m_mtx.cplx[m_col][m_row].im -= v.imag();    
02614   }
02615   
02616   void Matrix::Element::operator-= (const Element& v)
02617   {
02618     std::complex<double> cplx = (const std::complex<double>)v;
02619     *this -= cplx;
02620   }
02621 
02622 
02623   void Matrix::Element::operator*= (const double scalar)
02624   {
02625     if( m_mtx.isReal )
02626     {
02627       m_mtx.data[m_col][m_row] *= scalar;
02628     }
02629     else
02630     {
02631       m_mtx.cplx[m_col][m_row].re *= scalar;
02632       m_mtx.cplx[m_col][m_row].im *= scalar;
02633     }
02634   }
02635 
02636   void Matrix::Element::operator*= (const std::complex<double>& v)
02637   {
02638     if( m_mtx.isReal )
02639     {
02640       if( v.imag() != 0.0 )
02641       {
02642         // This is on the fly conversion to a complex matrix!
02643         if( !MTX_ConvertRealToComplex( &m_mtx ) )
02644         {
02645           MTX_Free( &m_mtx );
02646           Matrix::StaticMatrixError( "Element::operator=", "Unable to convert matrix from real to complex" );
02647           return;
02648         }
02649       }
02650       else
02651       {
02652         m_mtx.data[m_col][m_row] *= v.real();
02653         return;
02654       }
02655     }
02656 
02657     double re = m_mtx.cplx[m_col][m_row].re;
02658     double im = m_mtx.cplx[m_col][m_row].im;
02659     
02660     m_mtx.cplx[m_col][m_row].re = re*v.real() - im*v.imag();
02661     m_mtx.cplx[m_col][m_row].im = re*v.imag() + im*v.real();    
02662   }
02663   
02664   void Matrix::Element::operator*= (const Element& v)
02665   {
02666     std::complex<double> cplx = (const std::complex<double>)v;
02667     *this *= cplx;
02668   }
02669 
02670 
02671   void Matrix::Element::operator/= (const double scalar)
02672   {
02673     //if( scalar == 0.0 )
02674     //{
02675     //  MTX_Free( &m_mtx );
02676     //  Matrix::StaticMatrixError("Element/=","Divide by zero!");
02677     //}
02678     //else
02679     //{
02680       if( m_mtx.isReal )
02681       {
02682         m_mtx.data[m_col][m_row] /= scalar;
02683       }
02684       else
02685       {
02686         m_mtx.cplx[m_col][m_row].re /= scalar;
02687         m_mtx.cplx[m_col][m_row].im /= scalar;
02688       }
02689     //}
02690   }
02691 
02692   void Matrix::Element::operator/= (const std::complex<double>& v)
02693   {
02694     if( m_mtx.isReal )
02695     {
02696       if( v.imag() == 0.0 )
02697       {
02698       //  if( v.real() == 0.0 )
02699       //  {
02700       //    MTX_Free( &m_mtx );
02701       //    Matrix::StaticMatrixError( "Element/=", "Divide by zero." );
02702       //    return;
02703       //  }
02704       //  else
02705       //  {
02706           m_mtx.data[m_col][m_row] /= v.real();
02707           return;
02708       //  }
02709       }
02710       else
02711       {
02712         // This is on the fly conversion to a complex matrix!
02713         if( !MTX_ConvertRealToComplex( &m_mtx ) )
02714         {
02715           MTX_Free( &m_mtx );
02716           Matrix::StaticMatrixError( "Element/=", "Unable to convert matrix from real to complex" );
02717           return;
02718         }
02719       }
02720     }
02721 
02722     double d = v.real()*v.real() + v.imag()*v.imag(); 
02723     //if( d == 0.0 )
02724     //{ 
02725     //  MTX_Free( &m_mtx );
02726     //  Matrix::StaticMatrixError( "Element/=", "Divide by zero." );
02727     //}
02728     //else
02729     {
02730       double r = m_mtx.cplx[m_col][m_row].re;
02731       double i = m_mtx.cplx[m_col][m_row].im;
02732       m_mtx.cplx[m_col][m_row].re = (r * v.real() + i * v.imag()) / d;
02733       m_mtx.cplx[m_col][m_row].im = (i * v.real() - r * v.imag()) / d;
02734     }
02735   }
02736   
02737   void Matrix::Element::operator/= (const Element& v)
02738   {
02739     std::complex<double> cplx = (const std::complex<double>)v;
02740     *this /= cplx;
02741   }
02742 
02743 
02744 
02745 
02746 
02747 
02748   //friend 
02749   const std::complex<double> operator+ (const Matrix::Element& m, double scalar)
02750   {
02751     std::complex<double> v;
02752     v = (const std::complex<double>)m;
02753     v += scalar;
02754     return v;
02755   }
02756 
02757   //friend 
02758   const std::complex<double> operator+ (const Matrix::Element& a, const Matrix::Element& b)
02759   {
02760     std::complex<double> v1;
02761     std::complex<double> v2;
02762     v1 = (const std::complex<double>)a;
02763     v2 = (const std::complex<double>)b;
02764     v1 += v2;
02765     return v1;
02766   }
02767     
02768   //friend 
02769   const std::complex<double> operator+ (const Matrix::Element& a, const std::complex<double>& b)
02770   {
02771     std::complex<double> v;
02772     v = (const std::complex<double>)a;
02773     v += b;
02774     return v;
02775   }
02776 
02777   //friend 
02778   const std::complex<double> operator+ (double scalar, const Matrix::Element& m)
02779   {
02780     return (m+scalar);
02781 
02782   }
02783 
02784   //friend 
02785   const std::complex<double> operator+ (const std::complex<double>& b, const Matrix::Element& a)
02786   {
02787     return (a+b);
02788   }
02789 
02790 
02791   //friend 
02792   const std::complex<double> operator- (const Matrix::Element& m, double scalar)
02793   {
02794     std::complex<double> v;
02795     v = (const std::complex<double>)m;
02796     v -= scalar;
02797     return v;
02798   }
02799 
02800   //friend 
02801   const std::complex<double> operator- (const Matrix::Element& a, const Matrix::Element& b)
02802   {
02803     std::complex<double> v1;
02804     std::complex<double> v2;
02805     v1 = (const std::complex<double>)a;
02806     v2 = (const std::complex<double>)b;
02807     v1 -= v2;
02808     return v1;
02809   }
02810     
02811   //friend 
02812   const std::complex<double> operator- (const Matrix::Element& a, const std::complex<double>& b)
02813   {
02814     std::complex<double> v;
02815     v = (const std::complex<double>)a;
02816     v -= b;
02817     return v;
02818   }
02819 
02820   //friend 
02821   const std::complex<double> operator- (double scalar, const Matrix::Element& m)
02822   {
02823     return (m+(-1.0*scalar));
02824 
02825   }
02826 
02827   //friend 
02828   const std::complex<double> operator- (const std::complex<double>& b, const Matrix::Element& a)
02829   {
02830     std::complex<double> v = b;
02831     v -= (const std::complex<double>)a;
02832     return v;    
02833   }
02834 
02835 
02836   //friend 
02837   const std::complex<double> operator* (const Matrix::Element& m, double scalar)
02838   {
02839     std::complex<double> v;
02840     v = (const std::complex<double>)m;
02841     v *= scalar;
02842     return v;
02843   }
02844 
02845   //friend 
02846   const std::complex<double> operator* (const Matrix::Element& a, const Matrix::Element& b)
02847   {
02848     std::complex<double> v1;
02849     std::complex<double> v2;
02850     v1 = (const std::complex<double>)a;
02851     v2 = (const std::complex<double>)b;
02852     v1 *= v2;
02853     return v1;
02854   }
02855     
02856   //friend 
02857   const std::complex<double> operator* (const Matrix::Element& a, const std::complex<double>& b)
02858   {
02859     std::complex<double> v;
02860     v = (const std::complex<double>)a;
02861     v *= b;
02862     return v;
02863   }
02864 
02865   //friend 
02866   const std::complex<double> operator* (double scalar, const Matrix::Element& m)
02867   {
02868     return (m*scalar);
02869   }
02870       
02871   //friend 
02872   const std::complex<double> operator* (const std::complex<double>& b, const Matrix::Element& a)
02873   {
02874     return (a*b);
02875   }
02876 
02877 
02878   //friend 
02879   const std::complex<double> operator/ (const Matrix::Element& m, double scalar)
02880   {
02881     std::complex<double> v;
02882     v = (const std::complex<double>)m;
02883     v /= scalar;
02884     return v;
02885   }
02886 
02887   //friend 
02888   const std::complex<double> operator/ (const Matrix::Element& a, const Matrix::Element& b)
02889   {
02890     std::complex<double> v1;
02891     std::complex<double> v2;
02892     v1 = (const std::complex<double>)a;
02893     v2 = (const std::complex<double>)b;
02894     v1 /= v2;
02895     return v1;
02896   }
02897     
02898   //friend 
02899   const std::complex<double> operator/ (const Matrix::Element& a, const std::complex<double>& b)
02900   {
02901     std::complex<double> v;
02902     v = (const std::complex<double>)a;
02903     v /= b; 
02904     return v;
02905   }
02906 
02907   //friend 
02908   const std::complex<double> operator/ (double scalar, const Matrix::Element& m)
02909   {
02910     std::complex<double> v(scalar,0.0);
02911     v /= (const std::complex<double>)m;
02912     return v;
02913   }
02914 
02915   //friend 
02916   const std::complex<double> operator/ (const std::complex<double>& b, const Matrix::Element& a)
02917   {
02918     std::complex<double> v(b);
02919     v /= (const std::complex<double>)a;
02920     return v;
02921   }
02922 
02923 
02924   //friend 
02925   const bool operator== (const Matrix::Element& m, double scalar)
02926   {
02927     if( m.m_mtx.isReal )
02928     {
02929       if( m.m_mtx.data[m.m_col][m.m_row] == scalar )
02930         return true;
02931       else
02932         return false;
02933     }
02934     else
02935     {
02936       if( m.m_mtx.cplx[m.m_col][m.m_row].im != 0.0 )
02937         return false;
02938       if( m.m_mtx.cplx[m.m_col][m.m_row].re == scalar )
02939         return true;
02940       else
02941         return false;
02942     }
02943   }
02944   
02945   //friend 
02946   const bool operator== (const Matrix::Element& a, const Matrix::Element& b)
02947   {
02948     if( a.m_mtx.isReal )
02949     {
02950       if( b.m_mtx.isReal )
02951       {
02952         if( a.m_mtx.data[a.m_col][a.m_row] == b.m_mtx.data[b.m_col][b.m_row] )
02953           return true;
02954         else
02955           return false;
02956       }
02957       else
02958       {
02959         if( b.m_mtx.cplx[a.m_col][a.m_row].im != 0.0 )
02960           return false;
02961         if( a.m_mtx.data[a.m_col][a.m_row] == b.m_mtx.cplx[b.m_col][b.m_row].re )
02962           return true;
02963         else
02964           return false;
02965       }
02966     }
02967     else
02968     {
02969       if( b.m_mtx.isReal )
02970       {
02971         if( a.m_mtx.cplx[a.m_col][a.m_row].im != 0.0 )
02972           return false;
02973         if( a.m_mtx.cplx[a.m_col][a.m_row].re == b.m_mtx.data[b.m_col][b.m_row] )
02974           return true;
02975         else
02976           return false;
02977       }
02978       else
02979       {
02980         if( a.m_mtx.cplx[a.m_col][a.m_row].re == b.m_mtx.cplx[b.m_col][b.m_row].re &&
02981           a.m_mtx.cplx[a.m_col][a.m_row].im == b.m_mtx.cplx[b.m_col][b.m_row].im )
02982           return true;
02983         else
02984           return false;
02985       }
02986     }
02987   }
02988 
02989   //friend 
02990   const bool operator== (const Matrix::Element& a, const std::complex<double>& b)
02991   {
02992     if( a.m_mtx.isReal )
02993     {
02994       if( b.imag() != 0.0 )
02995         return false;
02996       if( a.m_mtx.data[a.m_col][a.m_row] == b.real() )
02997         return true;
02998       else
02999         return false;
03000     }
03001     else
03002     {
03003       if( a.m_mtx.cplx[a.m_col][a.m_row].re == b.real() && a.m_mtx.cplx[a.m_col][a.m_row].im == b.imag() )
03004         return true;
03005       else
03006         return false;
03007     }
03008   }
03009 
03010   //friend 
03011   const bool operator== (double scalar, const Matrix::Element& m)
03012   {
03013     return (m==scalar);
03014   }
03015       
03016   //friend 
03017   const bool operator== (const std::complex<double>& b, const Matrix::Element& a)
03018   {
03019     return (a==b);
03020   }
03021 
03022 
03023 
03024   bool Matrix::operator+= (const double scalar)
03025   {
03026     return Inplace_AddScalar( scalar );
03027   }
03028   
03029   bool Matrix::operator+= (const std::complex<double> cplx)
03030   {
03031     return Inplace_AddScalarComplex( cplx );
03032   }
03033 
03034   bool Matrix::operator-= (const double scalar)
03035   {
03036     return Inplace_SubtractScalar( scalar );
03037   }
03038 
03039   bool Matrix::operator-= (const std::complex<double> cplx)
03040   {
03041     return Inplace_SubtractScalarComplex( cplx );
03042   }
03043 
03044   bool Matrix::operator*= (const double scalar)
03045   {
03046     return Inplace_MultiplyScalar( scalar );
03047   }
03048 
03049   bool Matrix::operator*= (const std::complex<double> cplx)
03050   {
03051     return Inplace_MultiplyScalarComplex( cplx );
03052   }
03053 
03054   bool Matrix::operator/= (double scalar)
03055   {
03056     return Inplace_DivideScalar( scalar );
03057   }
03058 
03059   bool Matrix::operator/= (const std::complex<double> cplx)
03060   {
03061     return Inplace_DivideScalarComplex( cplx );
03062   }
03063 
03064   bool Matrix::operator+= (const Matrix& mat)
03065   {
03066     return Inplace_Add( mat );
03067   }
03068 
03069   bool Matrix::operator-= (const Matrix& mat)
03070   {
03071     return Inplace_Subtract( mat );
03072   }
03073 
03074   /* friend */
03075   Matrix operator++ (Matrix& mat, int)
03076   {
03077     if( !mat.Inplace_Increment() )
03078     {
03079       mat.MatrixError( "operator++", "Inplace_Increment() returned false." );
03080       return mat;
03081     }
03082     return mat;
03083   }
03084 
03085   /* friend */
03086   Matrix operator-- (Matrix& mat, int)
03087   {
03088     if( !mat.Inplace_Decrement() )
03089     {
03090       mat.MatrixError( "operator--", "Inplace_Decrement() returned false." );
03091       return mat;
03092     }
03093     return mat;
03094   }
03095 
03096   // matrix multiplication: A = B * C
03097   /* friend */
03098   Matrix operator* (Matrix& mat1, Matrix& mat2)
03099   {
03100     Matrix A;
03101     if( !MTX_Multiply( &A.m_Matrix, &mat1.m_Matrix, &mat2.m_Matrix ) )
03102     {
03103       mat1.Clear();
03104       mat2.MatrixError( "operator*", "MTX_Multiply() returned false." );
03105       return A;
03106     }
03107     return A; // return a copy
03108   }
03109   
03110   Matrix operator* (const Matrix& mat1, const Matrix& mat2)
03111   {
03112     Matrix A;
03113     if( !MTX_Multiply( &A.m_Matrix, &mat1.m_Matrix, &mat2.m_Matrix ) )
03114     {
03115       Matrix::StaticMatrixError( "operator*", "MTX_Multiply() returned false." );
03116       return A;
03117     }
03118     return A; // return a copy
03119   }
03120 
03121 
03122 
03123   // matrix addition: A = B + C
03124   /* friend */ 
03125   Matrix operator+ (Matrix& mat1, Matrix& mat2)
03126   {
03127     Matrix A;
03128     if( !MTX_Add( &A.m_Matrix, &mat1.m_Matrix, &mat2.m_Matrix ) )
03129     {
03130       mat1.Clear();
03131       mat2.MatrixError( "operator+", "MTX_Add() returned false." );
03132       return A;
03133     }
03134     return A; // return a copy
03135   }
03136   
03137   Matrix operator+ (const Matrix& mat1, const Matrix& mat2)
03138   {
03139     Matrix A;
03140     if( !MTX_Add( &A.m_Matrix, &mat1.m_Matrix, &mat2.m_Matrix ) )
03141     {
03142       Matrix::StaticMatrixError( "operator+", "MTX_Add() returned false." );
03143       return A;
03144     }
03145     return A; // return a copy
03146   }
03147 
03148 
03149 
03150   // matrix subtraction: A = B - C
03151   /* friend */ 
03152   Matrix operator- (Matrix& mat1, Matrix& mat2)
03153   {
03154     Matrix A;
03155     if( !MTX_Subtract( &A.m_Matrix, &mat1.m_Matrix, &mat2.m_Matrix ) )
03156     {
03157       mat1.Clear();
03158       mat2.MatrixError( "operator-", "MTX_Subtract() returned false." );
03159       return A;
03160     }
03161 
03162     return A; // return a copy
03163   }
03164   
03165   Matrix operator- (const Matrix& mat1, const Matrix& mat2)
03166   {
03167     Matrix A;
03168     if( !MTX_Subtract( &A.m_Matrix, &mat1.m_Matrix, &mat2.m_Matrix ) )
03169     {
03170       Matrix::StaticMatrixError( "operator-", "MTX_Subtract() returned false." );
03171       return A;
03172     }
03173 
03174     return A; // return a copy
03175   }
03176 
03177 
03178   // raise each element to a power
03179   /* friend */ 
03180   Matrix operator^ (Matrix& mat, const double scalar)
03181   {
03182     Matrix A;
03183     if( !MTX_Pow( &mat.m_Matrix, &A.m_Matrix, scalar, 0.0 ) )
03184     {
03185       mat.MatrixError( "operator^", "MTX_Pow() returned false." );
03186       return A;
03187     }
03188 
03189     return A; // return a copy
03190   }
03191 
03192   /* friend */ 
03193   Matrix operator+ (const double scalar, Matrix& mat)
03194   {
03195     Matrix A;
03196     if( !MTX_Copy( &mat.m_Matrix, &A.m_Matrix ) )
03197     {
03198       mat.MatrixError( "operator+", "MTX_Copy() returned false." );
03199       return A;
03200     }
03201 
03202     if( !A.Inplace_AddScalar( scalar ) )
03203     {
03204       mat.MatrixError( "Matrix operator+", "Inplace_AddScalar() returned false" );
03205       return A;
03206     }
03207 
03208     return A; // return a copy
03209   }
03210 
03211   /* friend */ 
03212   Matrix operator- (const double scalar, Matrix& mat)
03213   {
03214     Matrix A;
03215 
03216     if( !A.Redim( mat.GetNrRows(), mat.GetNrCols() ) )
03217     {
03218       mat.MatrixError( "operator-", "Redim() returned false." );
03219       return A;
03220     }
03221 
03222     if( !A.Fill( scalar ) )
03223     {
03224       mat.MatrixError( "operator-", "Fill() returned false." );
03225       return A;
03226     }
03227 
03228     if( !A.Inplace_Subtract( mat ) )
03229     {
03230       mat.MatrixError( "operator-", "Fill() returned false." );
03231       return A;
03232     }
03233 
03234     return A; // return a copy
03235   }
03236 
03237 
03238   /* friend */ 
03239   Matrix operator* (const double scalar, Matrix& mat)
03240   {
03241     Matrix A;
03242     if( !MTX_Copy( &mat.m_Matrix, &A.m_Matrix ) )
03243     {
03244       mat.MatrixError( "operator*", "MTX_Copy() returned false." );
03245       return A;
03246     }
03247 
03248     if( !A.Inplace_MultiplyScalar( scalar ) )
03249     {
03250       mat.MatrixError( "operator*", "Inplace_MultiplyScalar() returned false." );
03251       return A;
03252     }
03253 
03254     return A;
03255   }
03256 
03257   /* friend */ 
03258   Matrix operator/ (Matrix& mat, const double scalar)
03259   {
03260     Matrix A;
03261     if( !MTX_Copy( &mat.m_Matrix, &A.m_Matrix ) )
03262     {
03263       mat.MatrixError( "operator/", "MTX_Copy() returned false." );
03264       return A;
03265     }
03266 
03267     if( !A.Inplace_DivideScalar( scalar ) )
03268     {
03269       mat.MatrixError( "operator/", "Inplace_DivideScalar() returned false." );
03270       return A;
03271     }
03272 
03273     return A;
03274   }
03275 
03276   /* friend */ 
03277   Matrix operator/ (const double scalar, Matrix& mat)
03278   {
03279     Matrix A;
03280     if( !A.Redim( mat.GetNrRows(), mat.GetNrCols() ) )
03281     {
03282       mat.MatrixError( "operator/", "Redim() returned false." );
03283       return A;
03284     }
03285 
03286     if( !A.Fill( scalar ) )
03287     {
03288       mat.MatrixError( "operator/", "Fill() returned false." );
03289       return A;
03290     }
03291 
03292     if( !A.Inplace_DotDivide( mat ) )
03293     {
03294       mat.MatrixError( "operator/", "Inplace_DotDivide() returned false." );
03295       return A;
03296     }
03297 
03298     return A; // return a copy
03299   }
03300 
03301 
03302 
03303 
03304 
03305   //==========================
03306   //
03307 #ifdef MATRIX_STREAM_SUPPORT
03308 
03309   // output of a matrix: cout << A;
03310   /* friend */ 
03311   ostream& operator<< (ostream& strm, const Matrix& mat)
03312   {
03313     mat.Print( strm, strm.precision(), strm.width() );
03314     return strm;
03315   }
03316 
03317 #endif
03318   //
03319   //==========================
03320 
03321 
03322   bool Matrix::IndexCheck( const unsigned row, const unsigned col )
03323   {
03324     if( MTX_isNull(&m_Matrix) || row >= m_Matrix.nrows || col >= m_Matrix.ncols )
03325     {
03326       char msga[128];
03327 #ifndef _CRT_SECURE_NO_DEPRECATE
03328       sprintf_s( msga, 128, "Matrix access violation (%d,%d) out of bounds (%d,%d).\n", row, col, m_Matrix.nrows, m_Matrix.ncols );
03329 #else
03330       sprintf( msga, "Matrix access violation (%d,%d) out of bounds (%d,%d).\n", row, col, m_Matrix.nrows, m_Matrix.ncols );
03331 #endif
03332       MatrixError( "IndexCheck", msga );
03333       return false;
03334     }
03335     return true;
03336   }
03337 
03338   bool Matrix::IndexCheck( const unsigned index )
03339   {
03340     unsigned n = 0; // The number of elements as a vector.
03341     if( MTX_isNull(&m_Matrix) )
03342       n = 0;
03343     else
03344       n = m_Matrix.nrows*m_Matrix.ncols;
03345 
03346     if( index >= n )
03347     {
03348       char msga[128];
03349 #ifndef _CRT_SECURE_NO_DEPRECATE
03350       sprintf_s( msga, 128, "Matrix access violation (%d) out of bounds (%dx%d).\n", index, m_Matrix.nrows, m_Matrix.ncols );
03351 #else
03352       sprintf( msga, "Matrix access violation (%d) out of bounds (%dx%d).\n", index, m_Matrix.nrows, m_Matrix.ncols );
03353 #endif
03354       MatrixError( "IndexCheck", msga );
03355       return false;
03356     }
03357     return true;
03358   }
03359 
03360 
03361 
03362 
03363   Matrix::RealOnlyAccess::RealOnlyAccess( MTX& mtx, const unsigned row ) 
03364     : m_Matrix( mtx ), m_row( row ) 
03365   {}
03366 
03367   Matrix::RealOnlyAccess::~RealOnlyAccess()
03368   {}
03369 
03370   bool Matrix::RealOnlyAccess::IndexCheck( const unsigned row, const unsigned col )
03371   {
03372     if( MTX_isNull(&m_Matrix) || row >= m_Matrix.nrows || col >= m_Matrix.ncols )
03373     {
03374       char msga[128];
03375 #ifndef _CRT_SECURE_NO_DEPRECATE
03376       sprintf_s( msga, 128, "Matrix access violation [%d][%d] out of bounds (%d,%d).\n", row, col, m_Matrix.nrows, m_Matrix.ncols );
03377 #else
03378       sprintf( msga, "Matrix access violation (%d,%d) out of bounds (%d,%d).\n", row, col, m_Matrix.nrows, m_Matrix.ncols );
03379 #endif
03380       StaticMatrixError( "IndexCheck", msga );
03381       return false;
03382     }
03383     return true;
03384   }
03385 
03386   bool Matrix::RealOnlyAccess::IndexCheck( const unsigned index )
03387   {
03388     unsigned n = 0; // The number of elements as a vector.
03389     if( MTX_isNull(&m_Matrix) )
03390       n = 0;
03391     else
03392       n = m_Matrix.nrows*m_Matrix.ncols;
03393 
03394     if( index >= n )
03395     {
03396       char msga[128];
03397 #ifndef _CRT_SECURE_NO_DEPRECATE
03398       sprintf_s( msga, 128, "Matrix access violation [%d] out of bounds (%dx%d).\n", index, m_Matrix.nrows, m_Matrix.ncols );
03399 #else
03400       sprintf( msga, "Matrix access violation (%d) out of bounds (%dx%d).\n", index, m_Matrix.nrows, m_Matrix.ncols );
03401 #endif
03402       StaticMatrixError( "IndexCheck", msga );
03403       return false;
03404     }
03405     return true;
03406   }
03407 
03408   double& Matrix::RealOnlyAccess::operator [] (const unsigned col)
03409   { 
03410     if( IndexCheck( m_row, col ) )
03411     {
03412       if( m_Matrix.isReal )
03413       {
03414         return m_Matrix.data[col][m_row];
03415       }
03416       else
03417       {
03418         return m_Matrix.cplx[col][m_row].re;
03419       }
03420     }
03421     else
03422     {
03423       staticglobal_BadDouble = 0.0;
03424       return staticglobal_BadDouble;
03425     }    
03426   }
03427 
03428   Matrix::RealOnlyAccess Matrix::operator[] (const unsigned row)
03429   {
03430     return RealOnlyAccess( m_Matrix, row );
03431   }
03432 
03433   Matrix::RealOnlyAccess& Matrix::RealOnlyAccess::operator=(const double value)
03434   {
03435     // This is indexing the matrix as a vector.
03436     const unsigned index = m_row;
03437     if( IndexCheck(index) )
03438     {
03439       if( m_Matrix.ncols == 1 ) // column array
03440       {
03441         if( m_Matrix.isReal )
03442         {
03443           m_Matrix.data[0][index] = value;
03444         }
03445         else
03446         {
03447           m_Matrix.cplx[0][index].re = value;
03448           m_Matrix.cplx[0][index].im = 0.0;
03449         }
03450       }
03451       else if( m_Matrix.nrows == 1 ) // row array
03452       {
03453         if( m_Matrix.isReal )
03454         {
03455           m_Matrix.data[index][0] = value;
03456         }
03457         else
03458         {
03459           m_Matrix.cplx[index][0].re = value;
03460           m_Matrix.cplx[index][0].im = 0.0;
03461         }
03462       }
03463       else
03464       {
03465         // access the matrix as a singular column array
03466         unsigned col = index / m_Matrix.nrows;
03467         unsigned row = index - col*m_Matrix.nrows;
03468 
03469         if( m_Matrix.isReal )
03470         {
03471           m_Matrix.data[col][row] = value;
03472         }
03473         else
03474         {
03475           m_Matrix.cplx[col][row].re = value;
03476           m_Matrix.cplx[col][row].im = 0.0;
03477         }
03478       }
03479     }
03480     return *this;
03481   }
03482 
03483   Matrix::RealOnlyAccess& Matrix::RealOnlyAccess::operator=(RealOnlyAccess& rhs)
03484   {
03485     // Matrix A(1); Matrix B(1);
03486     // A[0] = B[0];
03487 
03488     // Get the value of the rhs.
03489     double val = (const double)rhs;
03490 
03491     // Use the operator= double overload.
03492     *this = val;
03493     return *this;
03494   }
03495 
03496   Matrix::RealOnlyAccess& Matrix::RealOnlyAccess::operator=(Matrix::Element& rhs)
03497   {
03498     // Matrix A(1); Matrix B(1);
03499     // A[0] = B(0);
03500     *this = rhs.real();
03501     return *this;
03502   }
03503 
03504 
03505   Matrix::RealOnlyAccess::operator const double()
03506   {
03507     // This is indexing the matrix as a vector.
03508     const unsigned index = m_row;
03509     if( IndexCheck(index) )
03510     {
03511       if( m_Matrix.ncols == 1 ) // column array
03512       {
03513         if( m_Matrix.isReal )
03514         {
03515           return m_Matrix.data[0][index];
03516         }
03517         else
03518         {
03519           return m_Matrix.cplx[0][index].re;
03520         }
03521       }
03522       else if( m_Matrix.nrows == 1 ) // row array
03523       {
03524         if( m_Matrix.isReal )
03525         {
03526           return m_Matrix.data[index][0];
03527         }
03528         else
03529         {
03530           return m_Matrix.cplx[index][0].re;
03531         }
03532       }
03533       else
03534       {
03535         // access the matrix as a singular column array
03536         unsigned col = index / m_Matrix.nrows;
03537         unsigned row = index - col*m_Matrix.nrows;
03538 
03539         if( m_Matrix.isReal )
03540         {
03541           return m_Matrix.data[col][row];
03542         }
03543         else
03544         {
03545           return m_Matrix.cplx[col][row].re;
03546         }
03547       }
03548     }
03549     return 0.0; // Should not be reached!
03550   }
03551 
03552   bool Matrix::RealOnlyAccess::operator+= (const double scalar)
03553   {
03554     // This is indexing the matrix as a vector.
03555     const unsigned index = m_row;
03556     if( IndexCheck(index) )
03557     {
03558       if( m_Matrix.ncols == 1 ) // column array
03559       {
03560         if( m_Matrix.isReal )
03561         {
03562           m_Matrix.data[0][index] += scalar;
03563           return true;
03564         }
03565         else
03566         {
03567           m_Matrix.cplx[0][index].re += scalar;
03568           return true;
03569         }
03570       }
03571       else if( m_Matrix.nrows == 1 ) // row array
03572       {
03573         if( m_Matrix.isReal )
03574         {
03575           m_Matrix.data[index][0] += scalar;
03576           return true;
03577         }
03578         else
03579         {
03580           m_Matrix.cplx[index][0].re += scalar;
03581           return true;
03582         }
03583       }
03584       else
03585       {
03586         // access the matrix as a singular column array
03587         unsigned col = index / m_Matrix.nrows;
03588         unsigned row = index - col*m_Matrix.nrows;
03589 
03590         if( m_Matrix.isReal )
03591         {
03592           m_Matrix.data[col][row] += scalar;
03593           return true;
03594         }
03595         else
03596         {
03597           m_Matrix.cplx[col][row].re += scalar;
03598           return true;
03599         }
03600       }
03601     }
03602     return false; // Should not be reached!
03603   }
03604   
03605   bool Matrix::RealOnlyAccess::operator-= (const double scalar)
03606   {
03607     // This is indexing the matrix as a vector.
03608     const unsigned index = m_row;
03609     if( IndexCheck(index) )
03610     {
03611       if( m_Matrix.ncols == 1 ) // column array
03612       {
03613         if( m_Matrix.isReal )
03614         {
03615           m_Matrix.data[0][index] -= scalar;
03616           return true;
03617         }
03618         else
03619         {
03620           m_Matrix.cplx[0][index].re -= scalar;
03621           return true;
03622         }
03623       }
03624       else if( m_Matrix.nrows == 1 ) // row array
03625       {
03626         if( m_Matrix.isReal )
03627         {
03628           m_Matrix.data[index][0] -= scalar;
03629           return true;
03630         }
03631         else
03632         {
03633           m_Matrix.cplx[index][0].re -= scalar;
03634           return true;
03635         }
03636       }
03637       else
03638       {
03639         // access the matrix as a singular column array
03640         unsigned col = index / m_Matrix.nrows;
03641         unsigned row = index - col*m_Matrix.nrows;
03642 
03643         if( m_Matrix.isReal )
03644         {
03645           m_Matrix.data[col][row] -= scalar;
03646           return true;
03647         }
03648         else
03649         {
03650           m_Matrix.cplx[col][row].re -= scalar;
03651           return true;
03652         }
03653       }
03654     }
03655     return false; // Should not be reached!
03656   }
03657 
03658   bool Matrix::RealOnlyAccess::operator*= (const double scalar)
03659   {
03660     // This is indexing the matrix as a vector.
03661     const unsigned index = m_row;
03662     if( IndexCheck(index) )
03663     {
03664       if( m_Matrix.ncols == 1 ) // column array
03665       {
03666         if( m_Matrix.isReal )
03667         {
03668           m_Matrix.data[0][index] *= scalar;
03669           return true;
03670         }
03671         else
03672         {
03673           m_Matrix.cplx[0][index].re *= scalar;
03674           return true;
03675         }
03676       }
03677       else if( m_Matrix.nrows == 1 ) // row array
03678       {
03679         if( m_Matrix.isReal )
03680         {
03681           m_Matrix.data[index][0] *= scalar;
03682           return true;
03683         }
03684         else
03685         {
03686           m_Matrix.cplx[index][0].re *= scalar;
03687           return true;
03688         }
03689       }
03690       else
03691       {
03692         // access the matrix as a singular column array
03693         unsigned col = index / m_Matrix.nrows;
03694         unsigned row = index - col*m_Matrix.nrows;
03695 
03696         if( m_Matrix.isReal )
03697         {
03698           m_Matrix.data[col][row] *= scalar;
03699           return true;
03700         }
03701         else
03702         {
03703           m_Matrix.cplx[col][row].re *= scalar;
03704           return true;
03705         }
03706       }
03707     }
03708     return false; // Should not be reached!
03709   }
03710   
03711   bool Matrix::RealOnlyAccess::operator/= (double scalar)
03712   {
03713     //if( scalar == 0.0 )
03714     //{
03715     //  StaticMatrixError( "Divide by zero not allowed (real vector element division). Matrix X(10); X[0]/0.0!" );
03716     //  return false; // should not reach this code.
03717     //}
03718       
03719     // This is indexing the matrix as a vector.
03720     const unsigned index = m_row;
03721     if( IndexCheck(index) )
03722     {
03723       if( m_Matrix.ncols == 1 ) // column array
03724       {
03725         if( m_Matrix.isReal )
03726         {
03727           m_Matrix.data[0][index] /= scalar;
03728           return true;
03729         }
03730         else
03731         {
03732           m_Matrix.cplx[0][index].re /= scalar;
03733           return true;
03734         }
03735       }
03736       else if( m_Matrix.nrows == 1 ) // row array
03737       {
03738         if( m_Matrix.isReal )
03739         {
03740           m_Matrix.data[index][0] /= scalar;
03741           return true;
03742         }
03743         else
03744         {
03745           m_Matrix.cplx[index][0].re /= scalar;
03746           return true;
03747         }
03748       }
03749       else
03750       {
03751         // access the matrix as a singular column array
03752         unsigned col = index / m_Matrix.nrows;
03753         unsigned row = index - col*m_Matrix.nrows;
03754 
03755         if( m_Matrix.isReal )
03756         {
03757           m_Matrix.data[col][row] /= scalar;
03758           return true;
03759         }
03760         else
03761         {
03762           m_Matrix.cplx[col][row].re /= scalar;
03763           return true;
03764         }
03765       }
03766     }
03767     return false; // Should not be reached!
03768   }
03769   
03770 
03771 }
03772