|
Boost : |
From: Jason Hise (0xchaos_at_[hidden])
Date: 2006-11-09 15:00:50
On 11/9/06, Jason Kraftcheck <kraftche_at_[hidden]> wrote:
>
> I fail to see how row operations make the implementation cleaner or easier.
> Most operators can be implemented with a single loop in both cases. For example:
> private:
> Type data[R*C];
> public:
> matrix<R,C,Type>& operator+=( const matrix<R,C,Type>& other ) {
> for (unsigned i = 0; i < R*C; ++i)
> data[i] += other.data[i];
> return *this;
> }
>
I was thinking of the inverse algorithm specifically, and other
algorithms in general. I'd like to distinguish here between a
function which is a necessary part of the interface to the type, and
algorithms which are separate extensions that operate on that type.
Being able to perform elementary row operations on matricees is
important (I just had to implement the simplex algorithm for a class I
am taking). However, it may be more important to provide for
matricees which do not have fixed sizes at compile time than for those
that do (simplex required me to be able to insert rows and columns at
run time).
> >
> > There are two usability features that my implementation provides which
> > yours does not. The first is being able to index a vector by name
> > (_x, _y, _z, _w). This is easily implemented using a properly scoped
> > enum. I used leading underscores for my component names as a
> > convention to indicate that they were property names, though
> > admittedly this naming convention could be debated.
> >
> > vector <float, 3> up;
> > up[_x] = 0;
> > up[_y] = 1;
> > up[_z] = 0;
> >
>
> I've never found such a convention very useful. It is a trivial thing to add if
> others do.
I think it falls into the same category as not using magic numbers.
To give another example, if you use a vector to store a color, being
able to refer to the components as r, g, b, and a channels instead of
by number improves readability. But perhaps enumerating these
constants is better left to client code.
>
> > Another thing that my code allows that yours does not is explicit
> > construction of a vector from the number of parameters that matches
> > the size (at least from 1 through 4), using the SFINAE techniques of
> > boost.enable_if. It can be much nicer for client code to be able to
> > write:
> >
> > vector <float, 3> up (0, 1, 0);
> >
> > than to have to write the code segment I used for my previous example.
>
> That is a useful feature. I had considered several ways of implementing it.
> However, I had doubts about all of them, so I didn't provide any.
>
> 1) varargs
> o matrix( Type ii, ... );
> o no type checking on arguments
> 2) multiple constructors with different numbers of args
> o what you have implemented
> o seems conceptually wrong to have a four-arg constructor
> for a 2-element vector, or visa versa.
> o doesn't work for larger matrices
This is why I used boost::enable_if... it makes it impossible to call
a 4 arg constructor on a two component vector and vice versa. The
functions can never be instantiated if the dimensions don't match.
The code could probably be further improved using BOOST_PP to
automatically generate an arbitrary number of constructors to match
larger numbers of initializers.
> 3) one constructor with unrolled assignment
> o most of the same limitations as 2)
> o one function
> o safe (will never write off the end of the array)
> o matrix( Type a, Type b , Type c = 0, Type d = 0,
> Type e = 0, Type f = 0, Type g = 0, Type h = 0,
> Type i = 0, Type j = 0, Type k = 0, Type l = 0,
> Type m = 0, Type n = 0, Type o = 0, Type p = 0 ) {
> switch (R*C) {
> case 16: data[15] = p;
> case 15: data[14] = o;
> ...
> case 1: data[ 0] = a;
> }
> o excessively large argument list for e.g. a 2x1 matrix
>
> - jason
Another alternative is to use creative operator overloading:
vector<float, 3> up ((vec_builder<float>, 0, 1, 0));
or:
vector<float, 3> up (vec_builder<float>(0)(1)(0));
or maybe:
vector<float, 3> up;
up << 0 << 1 << 0;
though I do happen to prefer my former solution, which looks and acts
like a constructor call.
-Jason
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk