This is going to be a different kind of column for me. As I was planning it, I considered several possible topics. I couldn't decide which one to cover, so I decided to cover them all. You may find some of them incomplete--I'm giving you my thoughts as I'm having them. I welcome your thoughts and comments.
Vector/Matrix class redux
Whenever I set out to (re)create a vector/matrix math package, I always wrestle with the decision: should I include separate functions for the special case where the vectors are dimensioned 3, and the matrices, 3×3? Clearly, classes that can handle general, n-dimensional vectors and m × n matrices can also handle the case m = n = 3. On the other hand, it's certain that if we know in advance the dimensions of the objects, the code will be a little faster and more compact.
While it's important to be able to deal with general forms of the mathematical entities called vectors and matrices, there's a good argument for the specialized functions as well.
We live, after all, in a three-dimensional universe (unless your field is String Theory). Most of the computations I do--space mechanics, rocket and aircraft dynamics, robotics, dynamic simulations--involve the motions of real, physical bodies in this three-dimensional space. It's the discipline called dynamics, whose math is defined by Newton's laws of motion.
The mathematical entities called vectors and matrices weren't exactly invented specifically to deal with physics problems, but they might as well have been. The simplifications that result from their use in physical problems is so profound, it's hard to over-emphasize the point.
That being the case, I'm always tempted to define special computer functions to process 3-d vectors and matrices. Usually I succumb to the temptation. When I was developing the C++ classes called Vector and Matrix, I wrestled with the same decision. For the sake of brevity, I chose to omit the special 3-d case. For the column, I was focused more on showing you the principles rather than defining a production-quality library of functions.
However, the argument for the special case is even stronger than usual, when defining C++ classes. That's because my general-case solutions required dynamic memory allocation.
Any time we declare a new object of a certain class, whether it be a named variable or an anonymous temporary, the compiler is going to have to invoke the memory manager. That's a given. But in my general-purpose functions, I also had to dynamically allocate the storage for the object's member data, because we don't know the size of the data until the constructor is invoked. So with every declaration of one of the general-purpose objects, we get a double dose of memory allocation.
If you declare all named objects statically, you can move most of the memory allocations to the initialization phase of the programs. We might do this, for example, when writing flight software for a satellite or missile.
But if you make use of those lovely overloaded operators, you can't avoid the creation of temporary objects, and the overhead to construct and destruct them.
Finally, there's the issue of the vector cross product, which only works for 3-vectors. In our n-vector class, I had to include tests to make sure that both vectors were, in fact, dimensioned 3. That's not a problem in the special case. (Optional for extra credit: some of us gurus in the know, know that the cross product isn't really limited to 3-vectors. There's a 4-d cross product as well. If you're "one of us," drop me a line. Say the magic word, "quaternion," and I'll send you the Secret Decoder Ring Tone.)
If we know in advance that all the vectors will be dimensioned 3, and matrices, 3×3, the double dose of dynamic allocation goes away.