View more

View more

View more

### Image of the Day Submit

IOTD | Top Screenshots

### The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.

# Which do you prefer?

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

9 replies to this topic

### #1Telios  Members

Posted 27 May 2012 - 08:37 AM

Hiya,

I've seen all of these 'styles' used for mathematical operations. Could anyone tell me which you prefer, and why?

class Vector3
{
// This?
// Equivalent to a free function.
void normalise();

// Or this?
Vector3& normalise();

// Or this?
Vector3 normalise() const;
}


The first is limiting as you can't use it as part of an equation, but it's unlikely to be confusing. It seems the second and third varieties are more flexible, but could easily be confused, e.g.

// Should v1 be modified here?
Vector3 v1;
Vector3 v2 = v1.normalise();


Which do you use, or which do you prefer? Thanks for any suggestions!

Edited by Telios, 27 May 2012 - 09:39 AM.

### #2TheUnnamable  Members

Posted 27 May 2012 - 09:40 AM

I'd prefer Vector3& normalise(); as it's part of the class, meaning that it actually changes the instance. Also, this returns a reference to the instance itself, so you can use more functions on it in a row.
For your second line, I'd create a global function outside the class, that would return a new instance, without changing the original one:
class Vector3;
Vector3 Normalise(const Vector3&);

This way it makes sense for me, although that global function is still a bit problematic, spamming the global namespace. An alternative could be this:
class Vector3
{
Vector3& Normalise(void);  //<- Changing the original instance, then returning itself
Vector3  Normalised(void); //<- Returning a normalised copy of the original one
};

Vector3 v1;
Vector3 v2=v1.Normalised();

Ta-dah!

### #3Álvaro  Members

Posted 27 May 2012 - 09:48 AM

I actually think a free function is more clear:

Vector3 normalize(Vector3 const &v);

Vector3 v1;
Vector3 v2 = normalize(v1);


### #4Muzzy A  Members

Posted 27 May 2012 - 10:32 AM

I agree with alvaro, free function with the Correct spelling lol. It's how I do all my linear algebra. But at the same time, I am totally obsessed with optimization that even having that extra copy in there urks me sometimes. But i don't do it just because I have an unknown reason against changing a variable passed in a function by reference.

grah you have me thinking about changing all my code lol.

Edited by Muzzy A, 27 May 2012 - 10:33 AM.

### #5Telios  Members

Posted 27 May 2012 - 11:31 AM

Thanks for that! I think I'm leaning towards free functions too, but then I'd feel I need to make everything a free function for consistency. Some operations sit fine with me as const member functions - the dot product for example, or the determinant of a matrix. So I'll end up with:

float Vector3Dot(const Vector3& v1, const Vector3& v2);
Vector3 Vector3Normalise(const Vector3& v1);

float Matrix3x3Determinant(const Matrix3x3& m);
// etc...


I believe that's how D3DX and it's newer version (XNA Math?) do it. Another alternative is to use free functions which modify the instance passed in rather than return a new one. That way you only pay for a copy if you need it:

void Vector3Normalise(Vector3& v) { /*..*/ }

Vector3 v1;
// Modify the original - no copy.
Vector3Normalise(v1);
// Don't modify the original - copy.
Vector3 v2 = v1;
Vector3Normalise(v2);


Although such copies are unlikely to be a bottleneck.

...free function with the Correct spelling lol.

I'm not even gonna go there

Edited by Telios, 27 May 2012 - 11:33 AM.

### #6Bacterius  Members

Posted 27 May 2012 - 08:17 PM

I like class functions a lot but they tend to make equations messy in code. Free functions with a return value are much more intuitive in my opinion. For instance to calculate 3x^2 + 2:

Free function with no return value:

square(x);
multiply(x, 3);
return x;


Class function:

x.square();
x.multiply(3);
return x;


Or, if the class function returns itself:

return x.square().multiply(3).add(2);

Free function with return value:

return 3 * x * x + 2; // or return 3x**2 + 2 if ** is supported

Of course this is a trivial example considering the free function is in fact a language operator. Slightly more complicated: calculate normalize(cross(v1, v2)):

Free function with no return value:

cross(v1, v2); // modifies v1
normalize(v1);
return v1;


Class function:

return v1.cross(v2).normalize(); // not bad


Free function with return value:

return normalize(cross(v1, v2));

I don't know about you guys but I prefer the last option. Of course, as always, it depends. All those different methods have they strengths and weaknesses, and sometimes there is no clear "best" option. As for performance, unless you are bottlenecking on arithmetic or memory copy (which is highly unlikely), I wouldn't worry about it.

Edited by Bacterius, 27 May 2012 - 08:21 PM.

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

### #7frob  Moderators

Posted 27 May 2012 - 11:34 PM

You can always implement both. :-)

I usually prefer class methods but sometimes free functions are more clear. Giving both is not hard and lets the programmer using it decide the most clear version for that particular bit of code. Implement one in terms of the other to save on work, I'd make the class functions first since they don't need temporary values, use them to provide free versions.

Check out my book, Game Development with Unity, aimed at beginners who want to build fun games fast.

Also check out my personal website at bryanwagstaff.com, where I occasionally write about assorted stuff.

### #8Telios  Members

Posted 28 May 2012 - 11:53 AM

Thanks!

I usually prefer class methods but sometimes free functions are more clear.

Do you prefer the functions (whether class methods or free functions) to modify the original?

For me, I think the following would be confusing:

// modifies the original
Vector3& Vector3::cross(const Vector3&);
Vector3& Vector3::normalise();

// uh oh - v1 and v2 have changed!
return v1.cross(v2).normalise();


So I guess I'd prefer all methods to return a copy, but maybe free functions are the most unambigous. Just interested in what everyone thinks.

### #9SiCrane  Moderators

Posted 28 May 2012 - 01:41 PM

I generally expect to be able to tell if a function will modify its arguments from the name of the function. If the function is called normalize() I'd expect it to modify the vector so that it's a unit vector. If the function is called something like normalized_vector() I'd expect it to return a normalized copy. I certainly wouldn't expect a function called cross() to modify either of its arguments.

### #10Dawoodoz  Members

Posted 29 May 2012 - 12:02 PM

I want all vector arguments to be taken as values so that I can easily see where the variable's last assignment was made.
v = normalize(v);


I prefer vectors to be plain structs so that different math libraries can be combined without too much work.
When integrating a physics engine with a graphics engine, you get 2 types of vectors that have the same data inside but they don't want to work together.
It would be great if all languages would have a standard datatype for vectors and matrices that everyone can use with their own math functions.

"App". is an acronym and must always be followed by a dot.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.