Boost logo

Boost :

Subject: Re: [boost] different matrix library?
From: DE (satan66613_at_[hidden])
Date: 2009-08-16 17:10:56


<WARNING! LOT OF LETTERS!>
to all

on 15.08.2009 at 13:14
 joel wrote :
>> till now i actually don't see any critical flaws in the design
>> implementation will be altered in any way of course
> Well, the problem is not the design per itself. What usually happens
> with such lib is that you have tons of different user types
> that all want disjoint set of features.
about tons of user types
here is a train of thought (great album by Dream Theater by the way)

(general case) consider there are a matrix_expression class and a
matrix class which derives from matrix_expression<matrix<type> > (CRTP)
we can now write stuff like

    matrix<type> m = m1*m2 + m3*a; //a is a scalar

then one must think that allocating matrix on the stack is a good idea
since such (compile time) decision must be implemented somewhere, why
not in a distinct type?
no problem!

    static_matrix<type, 3, 3> m /*= m1*m2 + m3*a*/;
                      //^^here goes size of matrix
it derives from matrix_expression<static_matrix<type, 3, 3> > so all
operations fall to general case
it could actually be 'matrix<type, 3, 3>' but either it is perfectly
readable, easy to understand, easy to implement
you are welcome...

and also one can write

    void foo(const static_matrix<type, 3, 3> &m);

clearly stating that "i really wanna get a 3 by 3 matrix specifically
of that type!"
of course he (the one) meant 'static_matrix' type

"but hey! i also have a symmetric matrix which must be handled a bit
special" the one may say
again, not a problem
lets define 'symmetric_matrix_expression' which derives from
matrix_expression
we can do this because actually they are connected with 'is-a'
relationship, in other words symmetric matrix is a matrix (but not vice
versa)
so we deliver 'symmetric_matrix' (which derives from
symmetric_matrix_expression) and now can optimize some operations:

    symmetric_matrix<type> m = m1*m2 + m3*a; //m1, m2 & m3 are symmetric

now one can clearly state that he

    void need_symmetric(const symmetric_matrix<type> &m);

for a particular operation
and if another user write

    matrix<type> m;
    //...
    need_symmetric(m); //need to explicitly turn m to symmetric

it won't compile because 'm' is not necessarily symmetric
but in an expression

    m = m1 + symmetric1*symmetric2;

operations will fall back to general case
isn't it nice?

why stopping? then one can define diagonal_matrix_expression which is
actually symmetric so it derives from symmetric_matrix_expression
bla bla bla... define diagonal_matrix... bla bla bla...
(by the way an identity matrix is diagonal)
then one can write

    diagonal_matrix<type> d = identity<type>(v.size()) + diag(v); //v is a vector

while

    symmetric1 - a*identity<type>(N)

is still a symmetric expression (and can be handled acordingly)

resume: in my opinion this all is convinient, delivers clarity of user
code, easy to understand and implement, easy to customize and extend

what do you think about it?

-- 
Pavel

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