Thread: Judge my vector math library

  1. #1
    l'Anziano DavidP's Avatar
    Join Date
    Aug 2001
    Location
    Plano, Texas, United States
    Posts
    2,743

    Judge my vector math library

    I just created a library for doing vector/matrix math. I whipped it up in about 2 hours.

    Just take a look at it and tell me what you think! oh and you can use it too if you want.

    (oh I had to change the extension to .cpp because the board doesn't like .cs files from C#)

    Attachment 8287
    My Website

    "Circular logic is good because it is."

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Comments from bottom to top (just because):
    1. Perhaps its performance-based, but I don't know why you don't do return VectorData/mag in the Normalize4D function.
    2. Ditto for defining != in terms of ==, or vice versa.
    3. This doesn't really matter, but: usually, the reason given for storing matrices in column-major form is that it makes vector*matrix "fast" and matrix*vector "slow" -- but you only provided a matrix*vector operator.

    Otherwise, things look good; one thing you might think about adding is projection (handy for bouncing things off of other things).

  3. #3
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    If you are using Visual Studio 2008 you can turn most of your properties into auto-implemented properties which require no backing store or no associated field in the class.

    Code:
    public int TestValue { get; set; }

    Also you could use lambda expressions for some of your vector operations provided you have a delegate with the same signature.

    I see some temporary heap variables that are not needed. Generally in C# it is not a good idea to have a bunch of temporary heap vars sitting around. It can actually lead to a memory leak believe it or not.

    So do this:

    Code:
    SomeFunc(new Object())
    As opposed to:

    Code:
    Object SomeObject = new Object();
    SomeFunc(SomeObject);
    I also feel you have too many getters and setters for your data. You gain nothing by having your vector data private but then providing tons of getters and setters to manipulate that data. Don't allow others to directly manipulate your data. You could just as easily just return the underlying vector via one getter and set it via one setter which would greatly simplify your class.

    For the matrix class you could have it derive from an interface IMatrix which would specify the generic operations that can be performed on all matrices. This would allow you to implement any type of matrix instead of just a 4x4 should you need to use 3x3's in the future. If you don't like that design then the very least you should do is code the matrix class so that it does not specifically handle a hard-coded number of dimensions. The name Matrix4x4 is fine for an implementation class but not a good name for a base class.

    IMatrix - abstract
    Matrix4x4 - one impl of IMatrix with overrides for functions provided by IMatrix
    Matrix3x3

    OR

    Matrix - class that can handle any size matrix and understands logic for when it's possible to concatenate and when it's not possible.

    Personally I prefer the first design since it allows you to specify an object in terms of its functionality as opposed to how it performs that functionality. Not to mention that one Matrix class that can handle any size matrix would quickly become bloated and hard to maintain.
    Last edited by VirtualAce; 07-25-2008 at 04:38 PM.

  4. #4
    l'Anziano DavidP's Avatar
    Join Date
    Aug 2001
    Location
    Plano, Texas, United States
    Posts
    2,743
    Perhaps its performance-based, but I don't know why you don't do return VectorData/mag in the Normalize4D function.
    I didn't even think about that :-) Thanks. Good idea.

    3. This doesn't really matter, but: usually, the reason given for storing matrices in column-major form is that it makes vector*matrix "fast" and matrix*vector "slow" -- but you only provided a matrix*vector operator.
    I implemented it in column-major because OpenGL uses column-major, and I normally work with OpenGL...so I am just used to doing it that way. Honestly though, I would kind of prefer to work in row-major, because it just makes more sense to me honestly. Plus row-major would definitely be better for the CPU cache (it would provide a LOT more hits and far less misses). I don't understand why they do things in column-major order...but they do, so that's why I implemented my matrix class that way.

    Also you could use lambda expressions for some of your vector operations provided you have a delegate with the same signature.
    hmmm...could you provide some kind of example there?

    I also feel you have too many getters and setters for your data.
    I understand where you are coming from here. Basically my idea was to provide an easy way to access the vector for a variety of needs. For example, if I am using a 4-vector as a color, it makes sense to access it using the R, G, B, and A properties. If I am using the 4-vector for a position, however, it would make sense to access it with the X, Y, Z, and W properties. I did this purely for clarity on the programmer's side of things so that it is obvious to the programmer what that specific 4-vector is. Do you think it's too much?

    For the matrix class you could have it derive from an interface IMatrix which would specify the generic operations that can be performed on all matrices.
    Good idea.
    My Website

    "Circular logic is good because it is."

  5. #5
    l'Anziano DavidP's Avatar
    Join Date
    Aug 2001
    Location
    Plano, Texas, United States
    Posts
    2,743
    Actually my main problem with my own code is my "MatrixDataArray" property in the Matrix4x4 class.

    Reasons:

    Every time "MatrixDataArray" is accessed, column major form of the array has to be restructured element by element. I wish I knew a better way to do this.

    Also, because of the way in which I construct the array form of the 4x4 matrix, if I were to use the "indexer" and do this:

    Code:
    Matrix4x4 myMatrix = new Matrix4x4();
    myMatrix[5] = 3;
    This change would not be reflected in the matrix itself....because the indexer accesses "MatrixDataArray", and "MatrixDataArray" is a separately constructed array not using the same memory as the real matrix data....and in this case as far as I know it will only be using the "getter"...the "setter" would never be called in that code snippet. So it would be cool if I had a way to do that last code snippet. In C++ I could do something like the following in my getter for "MatrixDataArray":

    Code:
    float **retArray = new (float*)[16];
    
    for (int x = 0, i = 0; x < 4; x++)
    {
    	for (int y = 0; y < 4; y++, i++)
    	{
    		retArray[i] = &_mat[y][x];
    	}
    }
    
    return retArray;
    And that would provide me access to the actual data instead of a copy of the data...but that is C++ and not C#. I should research how to do something similar in C#
    My Website

    "Circular logic is good because it is."

  6. #6
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    You can do that in C# via the ref keyword.

    Optionally you could just use the code in an 'unsafe' block which turns off all the managed portion of the compiler for the duration of the block. However since objects in memory move around in C# you will want to use either fixed or stackalloc when declaring the array. Fixed is an indication to the GC to keep your object at it's address regardless if it is moving all other objects. Obviously doing this a lot will result in a fragmented heap which is why the second option is to use stackalloc. This tells the compiler to allocate the object/array on the stack instead of the heap. Then your object's address will not change and you also do not fragment the heap.

    Everyone claims C# is easy and anyone can program in it but there are just as many gotchas in it as other languages. You still have to be aware of what is going on under the hood in order to use it correctly. It's syntax is far easier and lack of memory management is a plus except for the fact that this means people will create objects anywhere and expect the GC to clean it all up. Everything is guaranteed to be cleaned up but there is no guarantee as to when it will be cleaned up. Because of this it is possible to create leaks during runtime that may not be cleaned up for quite some time.
    Last edited by VirtualAce; 07-25-2008 at 07:47 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. What's an import library?
    By chiefmonkey in forum C++ Programming
    Replies: 1
    Last Post: 06-19-2009, 05:00 PM
  2. Property Set Library (PSL) - Announcement
    By vultur_gryphus in forum Projects and Job Recruitment
    Replies: 0
    Last Post: 05-29-2008, 06:04 AM
  3. Makefile for a library
    By sirmoreno in forum Linux Programming
    Replies: 5
    Last Post: 06-04-2006, 04:52 AM
  4. very weird .h problem
    By royuco77 in forum C++ Programming
    Replies: 1
    Last Post: 09-11-2005, 07:55 AM
  5. better c string functions
    By samps005 in forum C Programming
    Replies: 8
    Last Post: 11-04-2003, 01:28 PM