PDA

View Full Version : More Math related question



powerpad
09-18-2002, 09:00 AM
i am currently facing the following question and wanted to receive some more opinions on it....

i want to implement some math classes like a vector, is it better to implement a 3d vector
as:

a)
an array with 3dimensions and do the necessary operations as operations operating on that array
e.g. typedef float Vct3d[3]
Vct3d addVec(Vct3d a, Vct3d b);
b)
a class with 3 float members, and do the necessary operations with overloaded operators that operate on my class
e.g class Vct3d{..};
Vct3d a,b,c; c = a + b; //+ overloaded op.

i do not have the necessary insight in this topic to know which kind'a implementation is more efficient in speed concern etc...
so please tell me about your ideas on this topic.
tnx

coredump
09-18-2002, 09:07 AM
this has been a topic of much discussion and
overeall, it's up to what you're comfortable with. everyone has reasons why their way is better or faster, but in the end, it's all a matter of what's easiest for you. i have a vector class with an array of floats. i use the array of floats because it's easy to pass to opengl. i overload operators for addition/subtraction/multiplication and also dot(|) and cross(^) product. just remember if you use classes, no virtual functions! this adds 4 bytes to the value of the sizeof() macro.

b

powerpad
09-18-2002, 11:50 PM
okay tnx for your statement
in the beginning i thought maybe the clases with the overloaded operators would be better since functions add function overhead, but on the otherhead i think arrays are stored more efficient in memory.
Maybe i will do some tests on that

ioquan
09-19-2002, 08:10 AM
If your class only has 3 floating point data members, and no virtual functions, it will be stored in memory exactly as an array of 3 floats. In my opinion, it is VERY nice to use overloaded operators for vectors and points.

*Aaron*
09-19-2002, 09:36 AM
in the beginning i thought maybe the clases with the overloaded operators would be better since functions add function overhead

Overloaded operators ARE functions. The code

Vct3d a,b,c; c = a + b is actually executing the function Vct3d& operator+(Vct3d& v1,Vct3d& v2), or however it is defined. If speed is a concern, you shouldn't use operators because an extra copy operation is executed when the function returns.

Bob
09-19-2002, 12:25 PM
If speed is a concern, you shouldn't use operators because an extra copy operation is executed when the function returns.

I have to disagree. If you implement and use your class properly, and use a good compiler, the overhead can be close to, if not even equal to, zero.

Just take a look at this example I made in a few minutes. It may not be a completely correct implementation, but at least it's not a bad one.



class vector3
{
public:
vector3() {return;}
vector3(const vector3 &v)
{
operator()(0) = v(0);
operator()(1) = v(1);
operator()(2) = v(2);
}

inline float &operator()(int n) {return _data[n];}
inline const float &operator()(int n) const {return _data[n];}

inline const vector3 operator +(const vector3 &rhs) const
{
vector3 tmp;
tmp(0) = operator()(0) + rhs(0);
tmp(1) = operator()(1) + rhs(1);
tmp(2) = operator()(2) + rhs(2);
return tmp;
}

inline const vector3 &operator =(const vector3 &rhs)
{
operator()(0) = rhs(0);
operator()(1) = rhs(1);
operator()(2) = rhs(2);
}

public:
float _data[3];
};

Just notice the use of function call operators instead of direct accsess to the data. Also notice the temporary vector in operator +, which is returned by value (which it have to).

I then made two functions to add two vectors and store the result in another vector. One which uses the operator +, and one which makes the componentwise addition manually (this is why I had to make the data public by the way, normally I would make it private).



void addVectorsOperator(vector3 &c, const vector3 &a, const vector3 &b)
{
c = a + b;
}

void addVectorsManual(vector3 &c, const vector3 &a, const vector3 &b)
{
c._data[0] = a._data[0] + b._data[0];
c._data[1] = a._data[1] + b._data[1];
c._data[2] = a._data[2] + b._data[2];
}

Here's the assembly output from MSVC 6.



; 38 : c = a + b;

mov eax, DWORD PTR _a$[esp+8]
mov ecx, DWORD PTR _b$[esp+8]
fld DWORD PTR [eax]
fadd DWORD PTR [ecx]
fld DWORD PTR [eax+4]
fadd DWORD PTR [ecx+4]
fld DWORD PTR [eax+8]
fadd DWORD PTR [ecx+8]
mov eax, DWORD PTR _c$[esp+8]
fstp DWORD PTR _tmp$340[esp+20]
mov ecx, DWORD PTR _tmp$340[esp+20]
fxch ST(1)
fstp DWORD PTR [eax]
fstp DWORD PTR [eax+4]
mov DWORD PTR [eax+8], ecx

Notice how all the operator calls and the temporary copy are effectively optimized away by the compiler.

Here's the manual way.



; 43 : c._data[0] = a._data[0] + b._data[0];

mov eax, DWORD PTR _a$[esp-4]
mov ecx, DWORD PTR _b$[esp-4]
mov edx, DWORD PTR _c$[esp-4]
fld DWORD PTR [eax]
fadd DWORD PTR [ecx]
fstp DWORD PTR [edx]

; 44 : c._data[1] = a._data[1] + b._data[1];

fld DWORD PTR [eax+4]
fadd DWORD PTR [ecx+4]
fstp DWORD PTR [edx+4]

; 45 : c._data[2] = a._data[2] + b._data[2];

fld DWORD PTR [eax+8]
fadd DWORD PTR [ecx+8]
fstp DWORD PTR [edx+8]


Sure, there is a little difference, but in my personal oppinion, the difference is so small that I would go for the operator + because it's cleaner code.

If speed is a concern, I really recomend an algorithmic optimization instead of hunting a few cycles here and there.

powerpad
09-19-2002, 11:43 PM
tnx for all your statements, looks like i found some real Pro' informations on that topic

*Aaron*
09-20-2002, 04:09 AM
Yeah, thanks for the info Bob. It's good to see that MSVC can optimize code like this. But one can't assume that all compilers will do so. And one small point: when you include the implementation for a member function inside a class declaration, it is automatically inline, so the keyword is redundant.

powerpad
09-20-2002, 06:29 AM
yeah that inline function thing i wanted to mention also, inline though is just a recommendation for the compiler, it is not like the compiler is forced to optimization with that keyword

Bob
09-20-2002, 06:32 AM
Of course not all compilers can handle this, that's why I said you needed a good compiler too, not only a code class design. I don't know how many compilers actually can handle this, nor do I know how difficult it is for the compiler, but I believe the major compilers should handle it.

As for inline, I've heard that before, but I don't know what the C++ specificaiton says about it. I just put the inline there to be on the safe side.

powerpad
09-21-2002, 09:39 AM
yeah better then feeling the bottleneck http://www.opengl.org/discussion_boards/ubb/biggrin.gif

MrShoe
09-22-2002, 05:04 PM
I use a vector structure and use good ole functions for dot product and cross product and stuff...