Boost logo

Boost :

From: Jason Kraftcheck (kraftche_at_[hidden])
Date: 2006-11-10 18:23:28


Jason Hise wrote:
> On 11/10/06, Jason Kraftcheck <kraftche_at_[hidden]> wrote:
...
>> 2) Should a vector be defined as a column matrix or a separate template.
>>
>> This is the principal differentiator between your implementation and mine. The
>> other issues are just simple features that can be added to one or the other.
>>
>> My argument for a column matrix definition of a vector is that it is closer to
>> the mathematical concept we are trying to model. All matrix operations
>> (multiplication between vectors and matrices, transpose, etc) work for vectors
>> as well as matrices w/out needing special vector forms of the operations.
>
> Although I understand the desire to merge the matrix and vector into a
> single type in order to shrink the interface that must be implemented,
> and though it may make sense from a mathematical and/or efficiency
> standpoint, I do not think that it makes sense from a design or
> extensibility standpoint. Good designs tend to compose more complex
> concepts from simpler ones, rather than defining simpler concepts as
> special cases of more complex ones. Generally, programmers do not
> tend to view floats as complex numbers that happen to have a zero
> imaginary component, or view ints as floats that have nothing
> following the decimal point, even though that is the mathematic
> concept being modeled. If I were defining a color class based on a
> vector, I don't think that it would occur to me that I was defining a
> specialized matrix that only had one row.

There are obvious performance, storage, and implementation issues for the
analogies you give. If these issues didn't exist, I don't think we'd have the
distinct types. Defining a vector as 1-column matrix doesn't have any such
issues. If the vector-as-matrix is implemented correctly, you should never need
to know that the vector is a matrix unless you're using it with matrices.

>
> Also, consider the library from a dependency standpoint. People that
> need vectors may well not need matricees. But people that are using
> matricees are very likely to need vectors as well.
>

If all the linear-algebra type algorithms such as matrix factorizations,
inversion, etc. were moved to a separate file, the number of operations that
apply to matrices other than vectors is trivially small. Addition, subtraction,
scalar operators, etc. all share a single implementation for vectors and
matrices. The 'extra' dependency on matrices is only the multiplication
implementation and some methods for accessing data.

>> My understanding of your argument for vectors as a separate class is that it
>> allows the matrix class to be defined as an array of vectors, where each vector
>> is a row of the matrix. This, in turn, allows for simpler coding of matrix row
>> operations for algorithms such as Gauss-Jordan elimination.
>
> Yes, but it is more than that. It seems to me that a vector is not
> just a specialized matrix, but is a type in its own right which
> supports its own operations. Matrix multiplication is not defined
> between two vectors of the same orientation, and vector multiplication
> does not apply to matricees.

Matrix multiplication is still applicable for vectors.
matrix<double,3,1> v1, v2;
matrix<double,3,3> M;
...
v2 = M * v1; // matrix multiplication
v2 = transpose(v1) * M; // same as above
M = v1 * transpose(v2); // outer product

There are a few special cases for vector multiplication:
 - vector (cross) products
 - inner (dot) product returns a scalar rather than a 1x1 matrix:
     double d = v1 % v1;
   is much more convenient and readable than
     double d = (transpose(v1) * v2)(0,0);

But this implies that the definition of vectors requires additional operations
beyond those of a matrix, not the other way around. I think that defining
matrices in terms of vectors introduces a lot more junk into the matrix
definition than defining vectors as matrices does for the vector definition.

Anyway, multiplication is the only special case. All the other operations apply
to both (addition, scalar multiply, etc.)

>
>> My implementation also provides row access to matrices as 1xC matrices, and
>> provides vector specific operations (vector product, dot product) for both Rx1
>> and 1xC matrices.
>
> This means that you are supporting two different types of vectors. So
> which type should be used as the foundation for vector based types,
> like complex numbers and colors?

Column matrices:
 template<Typename T, unsigned l> class svector : public smatrix<T,l,1>
 {
  ...
  T& operator()( unsigned i } { return smatrix<T,l,1>::operator()(i,0); }
  ...
 }

I provide the other because sometimes it is useful to have "row" vectors rather
than "column" vectors. Why impose artificial limitations? Anyway, for the
specific case of row operations for elimination, why does it matter if the rows
are vectors or matrices. Operations like scalar multiply and addition are the
same for either.

>
>> The only drawback to my approach is that a reinterpret_cast
>> is required to return a reference to a row as a 1xC matrix. It is portable to
>> do so, as the underlying cast is just operating on array data (no alignment
>> issues for individual members, no vtable, etc.) But it is ugly.
>
> This issue arises directly because of the fact that a matrix
> conceptually is a compound type, whose components should be acessible
> to client code. But a matrix is not just a compound type composed of
> elements. A matrix is composed of rows of elements.

Or columns of elements, or submatrices, or whatever... I don't think there's
anything special about rows of elements. I had a bit of trouble deciding if I
should define my matrix in row-major or column-major order. The former
corresponds to the normal C array layout and allows for easier row operations,
but for my work I often need to work with the columns of matrices.

- jason


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk