Quite some time ago I started this question: Mathematical Vector2 class implementation and have since improved on it. I've been using it and it seems to work fine, but I'm always looking for ways to improve on code. I also have a question, should I force inline for all my operator overloads or should i just leave them as inline and hope they inline?
Edit 1: Ok, so I don't need inline it looks like. Also I see the benefit of related operations now and have changed my operations and functions to reflect that principle. Did not know that the compiler had better routines for handling assignment operators (though the more I think about it the more it makes sense).
I don't think its a vary good idea to rid my code of const return types, and here is the reason why.
//this operator format
Vector2 Vector2::operator + (Vector2 const & v) const { Vector2 r(*this); return r +=v; }
//allows this
(v1 + v2) = v3
//tested it to be safe
//this operator format
const Vector2 Vector2::operator + (const Vector2 & v) const { Vector2 r(*this); return r += v; }
//does not allow this
(v1 + v2) = v3
//also tested
//this made me realize that, in fact, these are valid as well
Vector2::Add(v1, v2) = v3;
Vector2::Max(v1, v2) = v3;
//But not this
Vector2::Dot(v1, v2) = fval;
//to be on the safe side I changed some more functions return to const
//when I change them to const its true, the qualifer gets thrown out
//but only after the assignment, which is what I want.
Your advice was extremely helpful. Thank you Loki!
Edit 2: Fixed bad operator> code.
fogbit pointed out that I needed to check for division by zero in my Normalize method. But doesn't checking that 'len < FLT_EPSILON' prevent such mishap already?
Second Edit: dsrVector2.hpp
//namespace
namespace dsr
{
//vector2
class Vector2
{
public:
//members
float32 x, y;
//ctor
Vector2(float32 xVal = 0.0, float32 yVal = 0.0);
//methods
float32 LengthSq() const;
float32 Length() const;
const Vector2 & Skew();
const Vector2 & Normalize();
//assingment operators
Vector2 & Vector2::operator = (const Vector2 & v) { x = v.x; y = v.y; return *this; }
Vector2 & Vector2::operator = (const float32 & s) { x = s; y = s; return *this; }
Vector2 & Vector2::operator - (void) { x = -x; y = -y; return *this; }
//equality operators
bool Vector2::operator == (const Vector2 & v) const { return (x == v.x) && (y == v.y); }
bool Vector2::operator != (const Vector2 & v) const { return !(*this == v); }
//comparison operators
bool Vector2::operator < (const Vector2 & v) const { return (x < v.x) || ((x == v.x) && (y < v.y)); }
bool Vector2::operator > (const Vector2 & v) const { return !(*this < v) && !(*this == v); }
//vector2 to this operators
Vector2 & Vector2::operator += (const Vector2 & v) { x += v.x; y += v.y; return *this; }
Vector2 & Vector2::operator -= (const Vector2 & v) { x -= v.x; y -= v.y; return *this; }
Vector2 & Vector2::operator *= (const Vector2 & v) { x *= v.x; y *= v.y; return *this; }
Vector2 & Vector2::operator /= (const Vector2 & v) { x /= v.x; y /= v.y; return *this; }
//vector2 to vector2 operators
const Vector2 Vector2::operator + (const Vector2 & v) const { Vector2 r(*this); return r += v; }
const Vector2 Vector2::operator - (const Vector2 & v) const { Vector2 r(*this); return r -= v; }
const Vector2 Vector2::operator * (const Vector2 & v) const { Vector2 r(*this); return r *= v; }
const Vector2 Vector2::operator / (const Vector2 & v) const { Vector2 r(*this); return r /= v; }
//scaler to this operators
Vector2 & Vector2::operator += (float32 s) { x += s; y += s; return *this; }
Vector2 & Vector2::operator -= (float32 s) { x -= s; y -= s; return *this; }
Vector2 & Vector2::operator *= (float32 s) { x *= s; y *= s; return *this; }
Vector2 & Vector2::operator /= (float32 s) { x /= s; y /= s; return *this; }
//scaler to vector2 operators
const Vector2 Vector2::operator + (float32 s) const { Vector2 r(*this); return r += s; }
const Vector2 Vector2::operator - (float32 s) const { Vector2 r(*this); return r -= s; }
const Vector2 Vector2::operator * (float32 s) const { Vector2 r(*this); return r *= s; }
const Vector2 Vector2::operator / (float32 s) const { Vector2 r(*this); return r /= s; }
//static arithmetic
static const Vector2 Add (const Vector2 & v1, const Vector2 & v2) { return v1 + v2; }
static const Vector2 Sub (const Vector2 & v1, const Vector2 & v2) { return v1 - v2; }
static const Vector2 Mul (const Vector2 & v1, const Vector2 & v2) { return v1 * v2; }
static const Vector2 Div (const Vector2 & v1, const Vector2 & v2) { return v1 / v2; }
//static methods
static float32 DistanceSq (const Vector2 & v1, const Vector2 & v2)
{ return ((v1.x - v2.x) * (v1.x - v2.x)) + ((v1.y - v2.y) * (v1.y - v2.y)); }
static float32 Distance (const Vector2 & v1, const Vector2 & v2)
{ return sqrt(DistanceSq(v1, v2)); }
static float32 Dot (const Vector2 & v1, const Vector2 & v2)
{ return ((v1.x * v2.x) + (v1.y * v2.y)); }
static const Vector2 Min (const Vector2 & v1, const Vector2 & v2)
{ return Vector2(v1.x < v2.x ? v1.x : v2.x, v1.y < v2.y ? v1.y : v2.y); }
static const Vector2 Max (const Vector2 & v1, const Vector2 & v2)
{ return Vector2(v1.x > v2.x ? v1.x : v2.x, v1.y > v2.y ? v1.y : v2.y); }
static const Vector2 Clamp (const Vector2 & v, const Vector2 & min, const Vector2 & max)
{ return Min(Max(v, min), max); /*because lifes too short*/ }
//friend operators
friend std::ostream & Vector2::operator << (std::ostream & os, const Vector2 & v) { return os << "{" << v.x << ", " << v.y << "}"; }
}; //end vector2
//prototype
void TestVector2();
}//end namespace
Second Edit: dsrVector2.cpp
//namespace
namespace dsr
{
//vector2 ctor
Vector2::Vector2(float32 xVal, float32 yVal) : x(xVal), y(yVal) { }
//vector2 methods
float32 Vector2::LengthSq() const { return x * x + y * y; }
float32 Vector2::Length() const { return sqrt(LengthSq()); }
const Vector2 & Vector2::Skew() { x -= y; y += x; x -= y; return *this; }
const Vector2 & Vector2::Normalize()
{
float32 len = Length();
if(len < FLT_EPSILON)
{
x = y = 0;
return *this;
}
else
{
float32 invLen = 1.0f / len;
x *= invLen;
y *= invLen;
return *this;
}
}
//test vector2
void TestVector2()
{
//using
using std::cout;
using std::endl;
//locals
Vector2 v1 = Vector2(20, 20);
Vector2 v2 = Vector2(10, 10);
Vector2 v3 = Vector2();
//test
cout << "-> Vector2 Class Testing" << endl << endl;
//value
cout << "-> Testing Vector2 Starting Values" << endl;
cout << "v1 = " << v1 << endl;
cout << "v2 = " << v2 << endl;
cout << "v3 = " << v3 << endl;
cout << endl;
//vector2 arithmetic
cout << "-> Testing Vector2 Arithmetic" << endl;
cout << "v1 + v2 = " << v1 + v2 << endl;
cout << "v1 - v2 = " << v1 - v2 << endl;
cout << "v1 * v2 = " << v1 * v2 << endl;
cout << "v1 / v2 = " << v1 / v2 << endl;
cout << endl;
//vector2 assingment arithmetic
cout << "-> Testing Vector2 Arithmetic to Assingment" << endl;
v3 += v1; cout << "v3 += v1; v3 = " << v3 << endl;
v3 -= v2; cout << "v3 -= v2; v3 = " << v3 << endl;
v3 *= v1; cout << "v3 *= v1; v3 = " << v3 << endl;
v3 /= v2; cout << "v3 /= v2; v3 = " << v3 << endl;
cout << endl;
//vector2 assingment
cout << "-> Testing Vector2 Assingment" << endl;
v3 = v2; cout << "v3 = v2; v3 = " << v3 << "; v2 = " << v2 << endl;
cout << "-(v3) = " << -v3 << endl;
v3 = 0; cout << "v3 = 0; v3 = " << v3 << endl;
cout << endl;
//vector2 comparison
cout << "-> Testing Vector2 Comparison" << endl;
if(!(v1 == v2)) { cout << "v1 == v2 is False" << endl; }
if(v1 != v2) { cout << "v1 != v2 is True" << endl; }
if(!(v1 < v2)) { cout << "v1 < v2 is False" << endl; }
if(v1 > v2) { cout << "v1 > v2 is True" << endl; }
cout << endl;
//scaler arithmetic
cout << "-> Testing Vector2 Scaler Arithmetic" << endl;
cout << "v1 + 10 = " << v1 + 10 << endl;
cout << "v1 - 10 = " << v1 - 10 << endl;
cout << "v2 * 10 = " << v2 * 10 << endl;
cout << "v2 / 10 = " << v2 / 10 << endl;
cout << endl;
//scaler assingment arithmetic
cout << "-> Testing Vector2 Scaler Arithmetic to Assingment" << endl;
v3 += 20; cout << "v3 += 20; v3 = " << v3 << endl;
v3 -= 10; cout << "v3 -= 10; v3 = " << v3 << endl;
v3 *= 20; cout << "v3 *= 20; v3 = " << v3 << endl;
v3 /= 10; cout << "v3 /= 10; v3 = " << v3 << endl;
cout << endl;
//static arithmetic
cout << "-> Testing Vector2 Static Arithmetic" << endl;
cout << "Vector2::Add(v1, v2) = " << Vector2::Add(v1, v2) << endl;
cout << "Vector2::Sub(v1, v2) = " << Vector2::Sub(v1, v2) << endl;
cout << "Vector2::Mul(v1, v2) = " << Vector2::Mul(v1, v2) << endl;
cout << "vector2::Div(v1, v2) = " << Vector2::Div(v1, v2) << endl;
cout << endl;
//static member functions
cout << "-> Testing Vector2 Static Member Functions" << endl;
cout << "Vector2::Distance(v2, v1) = " << Vector2::Distance(v2, v1) << endl;
cout << "Vector2::DistanceSq(v2, v1) = " << Vector2::DistanceSq(v2, v1) << endl;
cout << "Vector2::Dot(v2, v1) = " << Vector2::Dot(v2, v1) << endl;
cout << "Vector2::Min(v1, v2) = " << Vector2::Min(v1, v2) << endl;
cout << "Vector2::Max(v1, v2) = " << Vector2::Max(v1, v2) << endl;
cout << "Vector2::Clamp(Vector2(5, 30), v2, v1) = " << Vector2::Clamp(Vector2(5, 30), v2, v1) << endl;
cout << endl;
//member functions
cout << "-> Testing Vector2 Member Functions" << endl;
cout << "v1.Length() = " << v1.Length() << endl;
cout << "v1.LengthSquared() = " << v1.LengthSq() << endl;
cout << "v2.Skew() = " << v2.Skew() << endl;
cout << "v2.Normalize() = " << v2.Normalize() << endl;
cout << endl;
//testing cpp copy
cout << "-> Testing Vector2 Default Copy Ctor" << endl;
Vector2 * vec = new Vector2(v2);
cout << "v2 = " << v2 << endl;
cout << "Vector2 * vec = new Vector2(v2);" << endl;
cout << "v4 = " << *vec << endl;
cout << endl;
//free
delete vec;
}
}//end namespace
BTW, I know this is not the same account. I lost my info for that account and have since been using this account.