MatrixClass

A class to handle Matrices

This class is intended for handling float matrices, to re-arrange and perform operations on them, similar to a MATLAB enviroment. I haven't seen something like this for mbed, so I decided I'll make one.

I created this class using <vector>'s. I write it and debugged it in Netbeans so it can be used in any C++ program, tested with gcc. The idea is to be able to work with Neural Networks and Kinematics eventually.

I'm also working on a MatrixMath class, to give basic matrix operations to Matrix objects. So far this class provides TRANSPOSE, DETERMINANT and INVERSE operations over a Matrix object, in a near future (hopefully) I'll add more and more operations.

This is my biggest and best C++ program, any advice or improvement is well recieved.

I hope the documentation is easy to understand, there are a few other functions I didn't cover here, and an example program here to better ilustrate the class. Matrix_Class

Ok so the Class I'm talking about is this:

Import libraryMatrix

Matrix Library. v1.6.4

Creating a Matrix object

To create a Matrix you need to define the number of Rows and Columns. Or use another Matrix to create an exact copy.

 //This will create a 3 by 3 matrix 
//all elements initialized to zero.

Matrix myMatrix(3,3);

 //This will call the Copy constructor
Matrix anotherMatrix( myMatrix );

 //Or just initialize a matrix to later determine its dimmensions
Matrix temp;

Change the dimmensions of a Matrix

Say you want to resize a matrix, add more space or reduce it. In that case you use the function Resize.

But if you want to increment a new Row to the middle of the matrix, or a new column? Then you use the static function AddRow/AddCol and to delete one the functions are DeleteRow/DeleteCol.

myMatrix.Resize( 4,4 )  //Expanded Matrix dimensions

Matrix::AddRow( anotherMatrix, 2 );        // Moves Rows 2,3,...  down and creates a new Row where 2 used to be.
Matrix::DeleteCol( anotherMatrix, 3 );    //  Deletes Column 3.

Filling a Matrix

Now that you have a Matrix with dimensions, you can input data to it using:

  //The fastest way if you know your data is
myMatrix << 1 << 2 <<3
         << 4 << 5 <<6
         << 7 << 8 <<9;

 // Or ask the user to fill it. This function is VIRTUAL
myMatrix.FillMatrix();

 // Or change a specific element
myMatrix.add( 2, 2, 0 );  // Re-writes element at position Row[2]Col[2] to a vlaue of 0
                         // In this case changes 5 to 0

Important

Matrix indexing starts with one, not zero, so to say the first element of Matrix is in position Row[1]Col[1].
Also, FillMatrix() is a virtual function to use with whatever Comunication protocol you want, but take a look at my implementation first for details.


The << operator
You may have noticed that the INPUT (<<) operator fills the Matrix as if it were an array, this is because the Matrix dimensions (Row, Col) have already been defined, this operand will NOT work in declared only matrices[ Matrix obj; ].

If you Resize a Matrix [ objM.Resize( n, m ) ], The operand will point to the first element, so you can refill your entire matrix again. this only works with a recently defined Matrix[ Matrix objM( n,m ) ], a Resized Matrix or a Cleared Matrix[ objM.Clear() ]. If you perform transformations to your matrix the operand will have unexpected behavior. See documentation for more info.

Matrix Operations

Your matrices now have data, let's see what operations you can perform on them.

temp = -myMatrix + 5;                  // Multiplies each element in Matrix by (-1) then adds
                                      // (5) to each one.

anotherMatrix *= myMatrix;           // Performs Cross Product multiplication between itself and myMatrix.

anotherMatrix -= myMatrix;          // Decrements element-by-element. Both matrices must be same dimensions.

if( anotherMatrix == myMatrix ) )                       // Checks element-by-element, returns true if
    printf( "These two matrices are equal!\n" );       //  matrices are identical.


temp.Clear();                                        // Makes all elements in matrix zero.

if( temp.isZero() )                                // Will be true 'cause all elements are zero.
    printf( "This matrix is empty!\n" );

myMatrix.print();                                // This will Oputput the matrix to the default USB RxTx port
                                                //  serial 9600 8,n,1

Information

Operators also support
obj1 = obj2 * obj3;
obj1 = obj2 * 0.5;
obj2 = obj1 - 5;

There are more SATATIC functions to provide more flexibility with the matrix.

WARNING!

If you haven't noticed yet the Assignment operator overwrites a Matrix, that is to say destroys whatever data the old matrix contained and puts new data into it.

So don't rely that because two Matrices are different dimensions the assignment will not occur, it will.

Your code <here>

This covers the basic of matrix handling and operations, but it's time to use all this and create your own programs, and these functions will help you do that.

int lengthX, lenghtY;

lengthX = myMatrix.getCols();    //returns the number of columns.
lengthY = myMatrix.getRows();   //returns the number of rows.

int firstNumber;

firstNumber = myMatrix.getNumber( 1, 1 );              //First element of Matrix.

Matrix vectorM = Matrix::ToPackedArray( myMatrix );  // Flaterns Matrix.

vectorM = Matrix::ExtractRow( myMatrix, 1 );        //Extracts first Row. Similar Function for Column

if( vectorM.isVector() )
    printf( "This is either a SingleRow or SingleColumn Matrix");

Information

As a convention I've been using a Upper case letter for functions that return a Matrix object, and lower case for those whom return floats or ints.

Scope

I'm looking forward to make a classTemplate with similar characteristics but for all sort of data types. I'll write another class on top of these for Kinematics, very simple at first... coding a Jacobian function will be quite a challenge.

API Versions

If you make use of this class let me know, so I can maintain the API and don't break your code with an update. But as version 1.6.2 of this class I will be maintaining the functionality.

Example Program

Import library

00001 #include "mbed.h"
00002 #include "Matrix.h"
00003 #include "MatrixMath.h"
00004 
00005 int main() {
00006 
00007     DigitalOut myled(LED1);
00008     Timer t,t2;
00009     
00010     t.start();
00011  
00012 //---
00013     Matrix myMatrix(3,3);
00014     Matrix anotherMatrix;
00015 
00016     // Fill Matrix with data.
00017     myMatrix << 1  << 2  << 3
00018              << 4  << 5  << 6
00019              << 7  << 8  << 9;
00020 
00021     printf( "\nmyMatrix:\n\n");
00022     myMatrix.print();
00023     printf( "\n" );
00024 
00025     
00026     // Matrix operations //
00027 
00028     // Add 5 to negative Matrix 
00029     anotherMatrix = - myMatrix + 5;
00030 
00031     printf( "Result Matrix: anotherMatrix = - myMatrix + 5\n\n" );
00032     anotherMatrix.print();
00033     printf( "\n" );
00034     
00035     // Matrix Multiplication *
00036     anotherMatrix *=  myMatrix;
00037 
00038     printf( "\nanotherMatrix = anotherMatrix * myMatrix\n\n" );
00039     anotherMatrix.print();
00040     printf( "\n" );
00041     
00042     // Scalar Matrix Multiplication anotherMatrix *= 0.5
00043     anotherMatrix *= 0.5;
00044 
00045     printf( "\nResult Matrix *= 0.5:\n\n" );
00046     anotherMatrix.print();
00047     printf( "    _______________________________ \n" );
00048 
00049 
00050     printf("\n\n *** MEMBER OPERATIONS *** \n\n");
00051 
00052     //Copy myMatrix
00053     Matrix temp( myMatrix );
00054 
00055     // Resize Matrix
00056     temp.Resize(4,4);
00057     printf("\nAdded one Column, one Row to the limits of myMatrix saved in temp Matrix\n");
00058     temp.print();
00059 
00060     //Delete those new elements, we don't need them anyway.
00061     Matrix::DeleteRow( temp, 4 );
00062     Matrix::DeleteCol( temp, 4 );
00063 
00064     printf("\nBack to normal\n");
00065     temp.print();
00066 
00067     
00068     // Make room at the begining of Matrix
00069     Matrix::AddRow( temp, 1 );
00070     Matrix::AddCol( temp, 1 );
00071     
00072     printf("\nAdded Just one Row and column to the beginning\n");
00073     temp.print();
00074 
00075     // Take the second Row as a new Matrix
00076     anotherMatrix = Matrix::ExportRow( temp, 2 );
00077     printf("\nExport Second Row \n");
00078     anotherMatrix.print();
00079 
00080     // The second Column as a new Matrix, then transpose it to make it a Row
00081     anotherMatrix = Matrix::ExportCol( temp, 2 );
00082     anotherMatrix = MatrixMath::Transpose( anotherMatrix );
00083     printf("\nAnd Export Second Column and Transpose it \n");
00084     anotherMatrix.print();
00085 
00086     // This will Check to see if your are reduce to a single Row or Column
00087     temp = Matrix::ToPackedVector( myMatrix );
00088     printf("\nInitial Matrix turned into a single Row\n");
00089     temp.print();
00090            
00091     //  Matrix Math  //
00092     printf("\n\n *** Matrix Inverse and Determinant ***\n");
00093     
00094     Matrix BigMat( 8, 8 );
00095     
00096     BigMat   << 1 << 0.3 << 1.0 << 1 << 3 << 0.5 << 7.12 << 899
00097              << 2 << 3.2 << 4.1 << 0 << 4 << 0.8 << 9.26 << 321
00098              << 5 << 6.0 << 1   << 1 << 2 << 7.4 << 3.87 << 562
00099              << 1 << 0.0 << 2.7 << 1 << 1 << 4.6 << 1.21 << 478
00100              << 2 << 3.7 << 48  << 2 << 0 << 77  << 0.19 << 147
00101              << 1 << 1.0 << 3.8 << 7 << 1 << 9.9 << 7.25 << 365
00102              << 9 << 0.9 << 2.7 << 8 << 0 << 13  << 4.16 << 145
00103              << 7 << 23  << 28  << 9 << 9 << 1.7 << 9.16 << 156;
00104 
00105     printf( "\nBigMat:\n");
00106     BigMat.print();
00107     printf( "\n" );
00108 
00109     t2.start();
00110     float determ = MatrixMath::det( BigMat );
00111 
00112     Matrix myInv = MatrixMath::Inv( BigMat );
00113     t2.stop();
00114 
00115     printf( "\nBigMat's Determinant is: %f \n", determ);
00116     printf( "\n" );
00117     
00118     printf( "\nBigMat's Inverse is:\n");
00119     myInv.print();
00120     printf( "\n" );
00121 
00122     //***  Homogenous Transformations **//
00123     
00124     printf( "\n\n *** TRANSFORMATIONS *** \n\n");
00125 
00126     Matrix rot;
00127 
00128     printf( " RotX  0.5 rad \n" );
00129     rot = MatrixMath::RotX(0.5);
00130     rot.print();
00131     printf( "    _______________________________ \n\n" );
00132 
00133     printf( " RotY  0.5 rad \n" );
00134     rot = MatrixMath::RotY(0.5);
00135     rot.print();
00136     printf( "    _______________________________ \n\n" );
00137 
00138     printf( " RotZ  0.5 rad \n" );
00139     rot = MatrixMath::RotZ(0.5);
00140     rot.print();
00141     printf( "    _______________________________ \n\n" );
00142 
00143     printf( " Transl  5x 3y 4z\n" );
00144     rot = MatrixMath::Transl( 5, 3, 4 );
00145     rot.print();
00146     printf( "    _______________________________ \n\n" );
00147 
00148  //---
00149  
00150     t.stop();
00151     
00152     float bigtime = t2.read();
00153     float average = 12.149647 - bigtime;
00154         
00155     printf( "\n\nThe time for all those operations in mbed was : %f seconds\n", t.read() );
00156     printf( "\nOnly operations witout any print takes: 12.149647 seconds\n" );
00157     printf( "\nDue to the 8x8 matrix alone takes: %f \n",bigtime );
00158     printf( "\nSo normal 4x4 matrix ops: %f\n", average );
00159            
00160     while(1) {
00161         myled = 1;
00162         wait(0.2);
00163         myled = 0;
00164         wait(0.2);
00165     }
00166 }