For decades, Jack has wanted a language that would let him do arithmetic with vectors and matrices. Now he has it. Here's a summation of his work on vector and matrix classes.
By Jack W. Crenshaw
I learned my lesson then. Today, I'm a fervent followed of the P.J. Plauger dictum: "Never put off until tomorrow what you can put off forever." These days, though I try to allow enough flexibility and modularity in my software to meet expected needs, I don't add features that no one has asked for.
The Matrix class I'm going to leave with you this month is a working, serviceable class, that you can use with confidence for quite a number of problems. Over time, I'm sure that both you and I will come across features we wish it had. We can add them then. The structure of the class--the relationship between the mathematical concept of a matrix and the computer implementation of it--is in place. The rest is simply a collection of member functions. If we've done our job correctly, we can always add more member functions without breaking the class itself.
In the remainder of this column, We won't have room for a lot of my usual philosophical ramblings, or even detailed explanations. Instead, I'm going to focus on describing the changes/additions to the files SimpleMat.cpp and Matrices.cpp. The code for the whole collection, including the regression test drivers, will be posted on the web site.
SimpleMat and friends
When I was developing class Vector, I worried about the issue of efficiency vs. ease of use. I wanted to be able to manipulate the vectors using overloaded operators, but sometimes I also wanted efficiency. My solution was to split the functionality into two files and two representations of a vector. The first, which I called SimpleVec, used the same approach we used back in my Fortran days: Vectors are treated as simple arrays of doubles. The user must pass the dimensions of the vector to the functions, and face the consequences if he gets them wrong. I eased the pain where I could by using default values for the dimensions. The only inefficiency in the SimpleVec functions is the overhead of the function call itself--not much of a penalty, these days.
In class Vector, on the other hand, I wanted the convenience and robustness one gets by carrying the vector size along as part of the class. You can't give the wrong dimensions because they're part of the object. In class Vector, I made heavy use of overloaded operators to let me write expressions like
y = (a+2*b)/(a*b); // last term is a dot product
The end result is, I get the efficiency of Fortran-like functions when I need it, but the ease of use of a class with overloaded operators, when I prefer that.
There's a lot of similarity between vector and matrix arithmetic. In fact, from one point of view a matrix can be considered to be an array of vectors. The big difference is that the elements of a vector map nicely onto the computer implementation we call an array. The matrix doesn't map so easily. At least, it doesn't if we want to have variable array dimensions. If you want to do matrix arithmetic in C/C++, it's necessary to store the data in a one-dimensional array, just as for vectors. Then you use simple rules for indexing into the array. To the computer, the "meat" of both data types look like simple one-dimensional arrays.