Click here to Skip to main content
11,703,438 members (72,640 online)
Click here to Skip to main content

Tagged as

MaNet: A matrix library for .NET (Rational Computing 2)

, 8 Jul 2010 CPOL 27.4K 2.7K 72
Rate this:
Please Sign up or sign in to vote.
A translation of the Java matrix library JAMA with LU, QR, Eigenvalue, and Cholesky decompositions.


This article presents a reasonably full featured linear algebra library for .NET. It is a translation of the Java matrix package JAMA. All of the matrix operations were successfully translated, but the IO methods had too much of a Java flavor and so were replaced. The library provides the standard linear algebra features one would expect, such as multiplying and inverting matrices. The following decompositions are also provided:

  • Cholesky Decomposition of symmetric, positive definite matrices
  • LU Decomposition (Gaussian elimination) of rectangular matrices
  • QR Decomposition of rectangular matrices
  • Eigenvalue Decomposition of both symmetric and non-symmetric square matrices

This should be sufficient for many of one's matrix needs. There was also some Java testing code, but while it may have been sufficient for the original creators, it was not enough for a translator lacking intimate knowledge of why certain choices were made. The unit tests used on this project are included, and are at 97% code coverage, so you can have reasonable confidence in this software. I have purposely decided to limit the amount of code shown in this article. My goal is to allow you to use some of the power inherent in linear algebra as a black box. I want you to be able to just use the fact that you can solve systems of equations (not so hard) or perform least squares (a bit harder) or find Eigenvalues or singular values (really hard) without needing to understand the intricate mathematical details.


I strongly advise going to Stanford Engineering Everywhere and watching the first lecture on linear dynamical systems. Unlike the lectures further on, this one does not require significant mathematical understanding to appreciate. Dr. Boyd does a brilliant job of illustrating the immense power that linear algebra can bring to your applications. If you are more mathematically inclined, the entire course is certainly worth watching, and it was also one of the major motivators for my translating JAMA and writing this article.

This is certainly not the only .NET linear algebra software on the web.

  • A very interesting project from Microsoft in the UK.
  • A list of numerical libraries is available on Wikipedia. This includes both free and commercial libraries.
  • DotNumerics: This is a translation of LAPACK from Fortran.
  • DotNetMatrix: A previous translation of JAMA that I just recently found out about and you might like.


This is the second article in a series on computing with Rational numbers. This may seem a bit odd as this project does not use Rational numbers, but I felt it better to separate things. The next article will then be able to focus on Rational matrices and their performance characteristics.

As can be seen, there is a lot of work to do, enough to dominate my free time for quite a while. If anyone is inspired, I would be delighted to work with them on the advancement of rational computing on the .NET platform.


This code has been sitting on my computer for over a year, and only now is it finally being released. You could reasonably wonder why what appears to be such a useful library was kept under wraps for so long after completion. There are two main reasons. The first is that this is a translation and so not fully original to me. It should be noted that linear algebra packages are, in general, not created from scratch. Pretty much everything is an outgrowth of some earlier Fortran routines such as LAPACK. On account of this, I have preserved the vast majority of the original comments, so one may see references to Java here and there. I would also note that though I deserve some credit for the effort I put into the translation and unit tests, much greater credit should be awarded to the original creators: Ronald F. Boisvert, Joe Hicklin, Bruce Miller, Cleve Moler, Roldan Pozo, Karin Remington, and Peter Webb.

My second concern is more serious. Some of the code in this library is very hard to understand. In particular, I speak of the EigenvalueDecomposition and SingularValueDecomposition constructors. To be honest, I do not understand those two massive routines. Since I believe that one should understand the code one presents, this is a bit of a quandary. However, solving this problem is one of the main problems unit testing was meant to solve. With sufficient unit tests, you can modify code that you do not understand and still have a reasonable expectation that if the tests pass, you will have working code.

Sample usage

Linear algebra is extremely useful. Solving systems of linear equations is a basic task that a linear algebra library ought to perform. Here is an example from the unit tests:

// For equations
// 2x  +  y + z  = 5
// 4x  - 6y      = 2
//-2x  + 7y + 2  = 9
// with solution x = 1, y = 1, z = 2

String strMat = @"2  1  1
                  4 -6  0
                 -2  7  2";

String strVals = @"5

String strExpectedSoln = @"1

Matrix mat = Matrix.Parse(strMat);
Matrix vals = Matrix.Parse(strVals);

Matrix expectedSoln = Matrix.Parse(strExpectedSoln);

Matrix soln = mat.Solve(vals);
//Checks that solution solves matrix equation. 
//Note that I can do this even if I don't know the solution.
Assert.That(mat.Times(soln), Is.EqualTo(vals)); 

//Check against expected solution
Assert.That (soln ,Is.EqualTo(expectedSoln));

This is pretty easy to do. You might notice that almost the entirety of the work involved is in setting up the input in a human readable format. This type of situation where we have the same number of unknowns and equations does come up; however, a much more interesting situation occurs when the number of equations exceeds the number of variables. In these types of problems, you try to find the best approximation to a solution given your equations. This can easily occur when the equations are based on error prone measurements. These problems are referred to as "least squares" problems, and you can do a remarkable amount of mathematical modeling with this technique.

// For equations
// a +  b =  6
// a + 2b =  5
// a + 3b =  7
// a + 4b = 10
// with leastsqure approximate solution a=3.5 , b=1.4

String strMat = @"1  1  
                  1  2   
                  1  3  
                  1  4";

String strVals = @"6

String strExpectedSoln = @"3.5

Matrix mat = Matrix.Parse(strMat);
Matrix vals = Matrix.Parse(strVals);

Matrix expectedSoln = Matrix.Parse(strExpectedSoln);

Matrix soln = mat.Solve(vals);

//Check against expected solution
Assert.That(soln, Is.EqualTo(expectedSoln).Within(.001));

It is no harder from a programming standpoint to solve a least squares problem than it is to solve a more matched set of linear equations. Though there are many potential uses for this library, I will assume that you want to either solve linear systems of equations or calculate least squares approximate solutions. If we have two matrices A and B such that Ax=B, they can be solved or least square solved by the following:

Matrix solution = A.Solve(B);

The majority of the work is involved in creating the matrices. Note that numerous IO samples can be found in the Matrix_IOTests unit test file.

Making matrices

There are three main methods for the creation of matrices. You can create a matrix of zeros and then set the values.

Matrix A = new Matrix(3,2); //Creates matrix of zeros with 3 rows and 2 columns
A.Set(0,1,7);  //Sets element at row 0, column 1 to 7
A.Array[0,1] = 7; //Sets element at row 0, column 1 to 7

A matrix can also be created directly from a one or two dimensional array.

double[] valArray = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 };
Matrix A = new Matrix(valArray,4);// Creates matrix with 4 rows using valArray;
double[][] valTwoD= new double[3][] { new double[4] { 1.0, 0.0, 0.0, 0.0 }, 
                                      new double[4] { 0.0, 1.0, 0.0, 0.0 }, 
                                      new double[4] { 0.0, 0.0, 1.0, 0.0 } };
Matrix B = new Matrix(valTwoD);
//creates a new matrix  with 3 rows and 4 columns from valTwoD

There are also several ways of parsing text to create a matrix. It is assumed that there are three likely formats that matrices are likely to come in. These are strings where rows are delimited by lines, and columns by spaces, the format used by MATLAB or the format used by Mathematica.

Matrix A = Matrix.Parse("1 2\n3 4"); // standard format
A = Matrix.Parse("[1 2;3 4]"); // matlab format
A = Matrix.Parse("{{1, 2}, {3, 4}}"); // mathematica format

A = Matrix.ParseMatLab("[1 2;3 4]"); 
A = Matrix.ParseMathematica("{{1, 2}, {3, 4}}]");

If your string is in another format, there is also a version with many parameters.

public static Matrix Parse(string str, string matrixFrontCap, string rowFrontCap, 
       string rowDelimiter, string columnDelimiter, 
       string rowEndCap, string matrixEndCap){..}

There is also a FromDataTable and a Load that takes a file path. There is also a Generators assembly that has more specialized methods to produce Toeplitz and some other matrices.

Unit tests

This project includes a large number of unit tests. In fact, the vast majority of time spent on this project was on writing and devising unit tests. Getting high levels of code coverage on preexisting code can be astonishingly difficult. Some of the unit tests use random numbers, and will on occasionally fail. This is due to the degree of numerical precision expected of the answers. All of these tests have random in their names.


My hope is that this library will make it significantly easier to write software that takes advantage of the power of linear algebra. It is also another step in my exploration of computing with Rational numbers. The third article in this series, where Rational matrices appear, is coming soon. Stay tuned.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Software Developer (Senior)
United States United States
Written software for what seems like forever. I'm currenly infatuated with WPF. Hopefully my affections are returned.

You may also be interested in...

Comments and Discussions

Questionis EigenvalueDecomposition functionality usable/stable ? Pin
elliot litz10-Mar-15 12:04
memberelliot litz10-Mar-15 12:04 
QuestionGreat stuff. Question about types Pin
cjbreisch13-Mar-13 3:16
membercjbreisch13-Mar-13 3:16 
QuestionHow to perform Matrix column sum. and also Row sum Pin
deghosty24-Oct-12 9:27
memberdeghosty24-Oct-12 9:27 
QuestionNice Pin
CIDev4-Sep-12 10:56
memberCIDev4-Sep-12 10:56 
GeneralMy vote of 4 Pin
Reiss15-Aug-11 1:26
memberReiss15-Aug-11 1:26 
GeneralMy vote of 5 [modified] Pin
César de Souza24-Jul-10 10:22
memberCésar de Souza24-Jul-10 10:22 
GeneralRe: My vote of 5 Pin
KenJohnson1-Aug-10 5:04
memberKenJohnson1-Aug-10 5:04 
GeneralMy vote of 5 Pin
Yves12-Jul-10 14:18
memberYves12-Jul-10 14:18 
QuestionPreviously published? Pin
riskka6-Jul-10 21:58
memberriskka6-Jul-10 21:58 
AnswerRe: Previously published? [modified] Pin
KenJohnson8-Jul-10 17:05
memberKenJohnson8-Jul-10 17:05 
Thank you for your comment. I feel you deserve a reply and I hope you will pardon its length.

I must admit to feeling a bit flat footed in that I was unaware of the existence of the article by Paul Selormey. It is also true that he translated the JAMA library. The question then is whether I simply duplicated what he did or whether this library is indeed makes a contribution to the linear algebra scene. The truth is that there are some significant differences in what we did but before I detail them there are a few philosophic comments I feel obliged to make.

When I began this project my goal was to sharpen up my linear algebra skills, which I certainly did accomplish, so in a sense this project a success in itself. However I would have preferred to have been aware of the other project even though that might have led me not to do it in the first place. Then if I did it I could say that the previous project was wonderful and that I merely added the things I will soon mention as improvements. I would then have said something very similar to what I said regarding the original authors of JAMA.

“I would also note that though I deserve some credit for the effort I put into the translation and unit tests, much greater credit should be awarded to the original creators: Ronald F. Boisvert ,Joe Hicklin , Bruce Miller ,Cleve Moler ,Roldan Pozo ,Karin Remington and Peter Webb.”

But I didn’t and so the differences are likely to read as if they were an argument as to why my translation is better than his translation, which is something that I do not relish doing.

When I translated the library I wanted to make a version that I would be comfortable using. To that end I created numerous parsing and toString methods that were not in the original Java. These allow matrices to be expressed in relatively human readable strings. This turns out to be important for the other major addition to JAMA, unit tests.

JAMA originally came with some tests. By the standards of when they were made, I would like to think that they were perfectly adequate, but by today’s standards they are not. In the article I stated “In fact the vast majority of the time spent on this project was spent writing and devising Unit tests. Getting high levels of code coverage on preexisting code can be astonishingly difficult.” Code that comes with a comprehensive set of unit tests is fundamentally different than code that does not. One can tweak modify and optimize such code much more readily even if one does not fully understand the code in question.

For example, the last unit test I added was the following.

 public void CloseEigenvaluesTest()
            //This should produce two distinct small eigwnvalues that are close together.
            string aBase = @"0   1    0   0 
                             1   0   -d   0
                             0   d    0   1 
                             0   0    1   0";
            Matrix A = Parser.Substitute(aBase, "d", .0000000001);

It covered some code that I had spent an utterly ridiculous amount of time trying to find when it was used. The need to have specific code to deal with close small eigenvalues may be obvious to some, but it certainly was not to me.

I would also like to note that this is not a standalone project. It is part of a chain that began with the rational number class and has quite a ways still to go. Rational matricides which are coming soon (and an outgrowth of this project) will allow one to do some pretty exciting things, assuming math excites you.

modified on Friday, July 9, 2010 1:58 AM

GeneralYou got my 5 but Pin
MeC++5-Jul-10 5:42
memberMeC++5-Jul-10 5:42 
GeneralRe: You got my 5 but Pin
KenJohnson5-Jul-10 9:35
memberKenJohnson5-Jul-10 9:35 
GeneralRe: You got my 5 but Pin
Kevin Drzycimski7-Jul-10 21:38
memberKevin Drzycimski7-Jul-10 21:38 
GeneralRe: You got my 5 but [modified] Pin
KenJohnson8-Jul-10 17:34
memberKenJohnson8-Jul-10 17:34 
GeneralRe: You got my 5 but Pin
Kevin Drzycimski8-Jul-10 21:12
memberKevin Drzycimski8-Jul-10 21:12 
GeneralMy vote of 5 Pin
MeC++5-Jul-10 5:24
memberMeC++5-Jul-10 5:24 
GeneralKeep it up [modified] Pin
JohnWindy4-Jul-10 22:25
memberJohnWindy4-Jul-10 22:25 
GeneralThank you. Pin
Shivamkalra2-Jul-10 23:46
memberShivamkalra2-Jul-10 23:46 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.150819.1 | Last Updated 8 Jul 2010
Article Copyright 2010 by KenJohnson
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid