Low dimensional matrices, vectors, quaternions and a cubic equation solver

Lars T. Kyllingstad public at kyllingen.NOSPAMnet
Mon Apr 19 03:43:25 PDT 2010


Gareth Charnock wrote:
> Andrei Alexandrescu wrote:
>> On 04/16/2010 04:25 PM, Gareth Charnock wrote:
>>> Okay, here goes. I've collected together the basic functionality that
>>> would probably make a good starting point. As I've mentioned my code is
>>> very messy and has bits missing (e.g. I never had a use for the cross
>>> product but it's pretty important in general). I guess a good way to
>>> begin would be to write the pubic interfaces then start on the
>>> implementation.
>>>
>>> Cubic Solvers:
>>> General complex cubic solver with two algorithms (one requiring a
>>> complex cosine and and arcosine one using only +-*/ and roots). A
>>> special case cubic solver for the reduced cubic x^^3 + px - q = 0.
>>
>> This sounds a candidate for std.numeric. How popular/needed are cubic 
>> solvers?
> 
> They're probably don't come up that frequently but they do they're 
> rather fiddly. Lots of operations to get right. But the solution doesn't 
> depend on anything but basic math operators so once it's written, it's 
> written. I guess the question is whether Phobos is meant to be a small 
> library or a kitchen sink library.
> 
>>> Quaternions:
>>> opAdd, opSub, opMult(quaternion), opMult(vector), opDiv, Normalise,
>>> Normalized, conjugate, conjugated, toEulerAngles*, fromEulerAngles,
>>> this(real,i,j,k), this(angle,axis), getAngle(), getAxis()
>>
>> Sounds good, but you'd need to convert the code to the new overloaded 
>> operators approach.
> 
> Fair enough, and this will be a good opportunity to show off why the new 
> overloading scheme is more powerful (e.g. opAdd and opSub can be combined).
> 
>>> *Currently I've only got a quaternion->euler angles routine that works
>>> in the ZYZ convention but I have read a paper that generalises my method
>>> to all valid axis conventions. Will probably impliment as something 
>>> like:
>>> toEulerAngles(string convention="XYZ")()
>>>
>>> Vectors:
>>> opAdd, opSub, opMult(scalar), opMult(vector)*, cross**, Normalise,
>>> Normalized, Length
>>
>> What is the representation of vectors? I'm afraid the design above 
>> would be too limited for what we need.
> A fixed sized array where V[0] ~ x, V[1] ~ y and V[2] ~ z. The field the 
> vector is defined over is templated.
> 
> What other operators are needed? I'd defiantly want to add swizzling. 
> http://www.ogre3d.org/docs/api/html/classOgre_1_1Vector3.html looks like 
> it could be a good source of ideas.
> 
>>> * dot product. Would this be better named as dot()?
> 
>> We already have dot product and normalization routines that work with 
>> general ranges.
>>
>> http://www.digitalmars.com/d/2.0/phobos/std_numeric.html#dotProduct
>> http://www.digitalmars.com/d/2.0/phobos/std_numeric.html#normalize
>>
>> Generally I'd strongly suggest making operations free generic 
>> functions instead of members.
> 
> I've not really thought about operators as members vs operators as free 
> functions. I just tend to put them as members because it feels more 
> organised. But looking at other implementations, I seem to be in the 
> minority.
> 
>>> ** 3D vectors only. Perhaps defining a cross product on the
>>>
>>> Matrices:
>>> opAdd, opSub, opMult(scalar), opMult(vector), opMult(matrix)**, Invert,
>>> Inverted, Orthogonalize, Orthogonalized, Reorthogonalize***,
>>> Reorthogonalized***, Det, Transpose, Transposed, Dagger*, Daggered*,
>>> Eigenvalues****, Eigenvectors****
>>
>> What is the representation of matrices?
> private:
>   F[n*n] mat;
> where F is the type of the field and n is the dimension of the matrix.
> 
>>> *The hermitian conjugate/conjugate transpose. Reduces to the transpose
>>> for a real matrix
>>
>> Transposition should also be handled in a static manner, e.g. define a 
>> transposed view of a matrix that doesn't actually move elements.
> 
> Do you mean that a bool should be stored to count the number of 
> transpositions or that there is a type that behaves like a matrix but 
> actually just presents a view of another matrix e.g.
> 
> Matrix A;
> ...
> Matrix B = A.Transposed();
> //Changes to B now affect A
> 
>>> ** Matrix-matrix multiplication doesn't commute. Could this be a problem
>>> when using operator notation?
>>
>> Should be fine.
>>
>>> *** Othogonalize assuming the matrix is nearly orthogonal already
>>> (possibly using some quick, approximate method such as a Taylor series)
>>> **** I have a eigenvalue/vector solver for 3x3 matrices which seems
>>> reasonably stable but needs more testing.
>>>
>>> Free functions:
>>> MatrixToQuaternion
>>> QuaternionToMatrix
>>> + code to allow easy printing to stdout/streams and such.
>>
>> Sounds encouraging.
>>
>> I think a good next step is to go through a community scrutiny process 
>> by dropping the code somewhere on the Web so people can review it.
> Couldn't agree more because I'm sure I'll miss tricks and conventions. I 
> would have never thought of that funky swizzling idea.
> 
> I've also got another question: should matrices, vectors and quaternions 
> be classes or structs? My gut reaction is that they should be structs 
> and thus act like value types. But matrices might be too big and should 
> be passed by reference which would imply they should be a class. Anyone 
> know any rules of thumb that might apply?

IMO, general vectors/matrices should be structs wrapping a pointer to 
the data:

   struct Vector(T)
   {
      T* ptr;
      size_t length;
      size_t stride;
   }

Low-dimensional fixed-size vectors should probably be value types.

-Lars



More information about the Digitalmars-d mailing list