Files
INS-VN-200/vnproglib/cpp/include/vn/vector.h
r.koeppe 2d22ccd2d6 initial
2024-05-14 02:14:13 +02:00

1376 lines
30 KiB
C++

/// \file
/// {COMMON_HEADER}
///
/// \section DESCRIPTION
/// This header file provides may types for working with vectors.
#ifndef _VN_MATH_VECTOR_H_
#define _VN_MATH_VECTOR_H_
#include <cassert>
#include <sstream>
#include <ostream>
#include <cmath>
#include "exceptions.h"
#include "int.h"
namespace vn {
namespace math {
/// \brief Template for a Euclidean vector.
template <size_t tdim, typename T = float>
struct vec
{
// Public Members /////////////////////////////////////////////////////////
public:
/// \brief The vector's components.
T c[tdim];
// Constructors ///////////////////////////////////////////////////////////
public:
/// \brief Creates a new vector with uninitialized components.
vec() { }
/// \brief Creates new vector with components initialized to val.
///
/// \param[in] val The initialization value.
explicit vec(T val)
{
std::fill_n(c, tdim, val);
}
// Helper Methods /////////////////////////////////////////////////////////
public:
/// \brief Vector with all of its components set to 0.
///
/// \return The 0 vector.
static vec zero()
{
return vec<tdim, T>(0);
}
/// \brief Vector with all of its components set to 1.
///
/// \return The 1 vector.
static vec one()
{
return vec<tdim, T>(1);
}
// Operator Overloads /////////////////////////////////////////////////////
public:
/// \brief Indexing into the vector's components.
///
/// \param[in] index 0-based component index.
/// \exception dimension_error The index exceeded the dimension of the vector.
T& operator[](size_t index)
{
return const_cast<T&>(static_cast<const vec&>(*this)[index]);
}
/// \brief Indexing into the vector's components.
///
/// \param[in] index 0-based component index.
/// \exception dimension_error The index exceeded the dimension of the vector.
const T& operator[](size_t index) const
{
assert(index < tdim);
return c[index];
}
/// \brief Negates the vector.
///
/// \return The negated vector.
vec operator-() const
{
return neg();
}
/// \brief Adds a vector to this vector.
///
/// \param[in] rhs The right-side vector.
/// \return The resulting vector.
vec& operator+=(const vec& rhs)
{
for (size_t i = 0; i < tdim; i++)
c[i] += rhs.c[i];
return *this;
}
/// \brief Subtracts a vector from this vector.
///
/// \param[in] rhs The right-side vector.
/// \return The resulting vector.
vec& operator-=(const vec& rhs)
{
for (size_t i = 0; i < tdim; i++)
c[i] -= rhs.c[i];
return *this;
}
/// \brief Multiplies the vector by a scalar.
///
/// \param[in] rhs The scalar.
/// \return The multiplied vector.
vec& operator*=(const T& rhs)
{
for (size_t i = 0; i < tdim; i++)
c[i] *= rhs;
return *this;
}
/// \brief Divides the vector by a scalar.
///
/// \param[in] rhs The scalar.
/// \return The divided vector.
vec& operator/=(const T & rhs)
{
for (size_t i = 0; i < tdim; i++)
c[i] /= rhs;
return *this;
}
// Public Methods /////////////////////////////////////////////////////////
public:
/// \brief The vector's dimension.
///
/// \return The vector's dimension.
size_t dim() const { return tdim; }
/// \brief Negates the vector.
///
/// \return The negated vector.
vec neg() const
{
vec v;
for (size_t i = 0; i < tdim; i++)
v.c[i] = -c[i];
return v;
}
/// \brief The vector's magnitude.
///
/// \return The magnitude.
T mag() const
{
T sumOfSquares = 0;
for (size_t i = 0; i < tdim; i++)
sumOfSquares += c[i] * c[i];
return sqrt(sumOfSquares);
}
/// \brief Adds a vector to this vector.
///
/// \param[in] toAdd The vector to add.
/// \return The resulting vector.
vec add(const vec& toAdd) const
{
vec v;
for (size_t i = 0; i < tdim; i++)
v.c[i] = c[i] + toAdd.c[i];
return v;
}
/// \brief Subtracts a vector from this vector.
///
/// \param[in] to_sub The vector to subtract from this.
/// \return The resulting vector.
vec sub(const vec& to_sub) const
{
vec v;
for (size_t i = 0; i < tdim; i++)
v.c[i] = c[i] - to_sub.c[i];
return v;
}
/// \brief Multiplies the vector by a scalar.
///
/// \param[in] scalar The scalar value.
/// \return The multiplied vector.
vec mult(const double& scalar) const
{
vec v;
for (size_t i = 0; i < tdim; i++)
v.c[i] = c[i] * scalar;
return v;
}
/// \brief Divides the vector by a scalar.
///
/// \param[in] scalar The scalar value.
/// \return The divided vector.
vec div(const double& scalar) const
{
vec v;
for (size_t i = 0; i < tdim; i++)
v.c[i] = c[i] / scalar;
return v;
}
/// \brief Normalizes the vector.
///
/// \return The normalized vector.
vec norm() const
{
vec v;
T m = mag();
for (size_t i = 0; i < tdim; i++)
v.c[i] = c[i] / m;
return v;
}
/// \brief Computes the dot product of this and the provided vector.
///
/// \param[in] rhs The right-side vector.
/// \return The computed dot product.
T dot(const vec& rhs) const
{
T runningSum = 0;
for (size_t i = 0; i < tdim; i++)
runningSum += c[i] * rhs.c[i];
return runningSum;
}
};
// Specializations ////////////////////////////////////////////////////////////
#if defined(_MSC_VER)
#pragma warning(push)
// Disable warning about 'nonstandard extension used : nameless struct/union'.
#pragma warning(disable:4201)
#endif
/// \brief Vector with 2 component specialization.
template <typename T>
struct vec<2, T>
{
// Public Members /////////////////////////////////////////////////////////
public:
union
{
struct
{
/// \brief X (0-component).
T x;
/// \brief Y (1-component).
T y;
};
/// \brief The vector's components.
T c[2];
};
// Constructors ///////////////////////////////////////////////////////////
public:
/// \brief Creates a new vector with uninitialized components.
vec() { }
/// \brief Creates new vector with components initialized to val.
///
/// \param[in] val The initialization value.
explicit vec(T val) : x(val), y(val) { }
/// \brief Creates a new vector with its components inintialized to the
/// provided values.
///
/// \param[in] x_val The x value.
/// \param[in] y_val The y value.
vec(T x_val, T y_val) : x(x_val), y(y_val) { }
// Helper Methods /////////////////////////////////////////////////////////
public:
/// \brief Vector with all of its components set to 0.
///
/// \return The 0 vector.
static vec zero()
{
return vec<2, T>(0);
}
/// \brief Vector with all of its components set to 1.
///
/// \return The 1 vector.
static vec one()
{
return vec<2, T>(1);
}
/// \brief Unit vector pointing in the X (0-component) direction.
///
/// \return The unit vector.
static vec unitX()
{
return vec<2, T>(1, 0);
}
/// \brief Unit vector pointing in the Y (1-component) direction.
///
/// \return The unit vector.
static vec unitY()
{
return vec<2, T>(0, 1);
}
// Operator Overloads /////////////////////////////////////////////////////
public:
/// \brief Indexing into the vector's components.
///
/// \param[in] index 0-based component index.
/// \exception dimension_error The index exceeded the dimension of the vector.
T& operator[](size_t index)
{
return const_cast<T&>(static_cast<const vec&>(*this)[index]);
}
/// \brief Indexing into the vector's components.
///
/// \param[in] index 0-based component index.
/// \exception dimension_error The index exceeded the dimension of the vector.
const T& operator[](size_t index) const
{
assert(index < 2);
return c[index];
}
/// \brief Negates the vector.
///
/// \return The negated vector.
vec operator-() const
{
return neg();
}
/// \brief Adds a vector to this vector.
///
/// \param[in] rhs The right-side vector.
/// \return The resulting vector.
vec& operator+=(const vec& rhs)
{
x += rhs.x;
y += rhs.y;
return *this;
}
/// \brief Subtracts a vector from this vector.
///
/// \param[in] rhs The right-side vector.
/// \return The resulting vector.
vec& operator-=(const vec& rhs)
{
x -= rhs.x;
y -= rhs.y;
return *this;
}
/// \brief Multiplies the vector by a scalar.
///
/// \param[in] rhs The scalar.
/// \return The multiplied vector.
vec& operator*=(const T& rhs)
{
x *= rhs;
y *= rhs;
return *this;
}
/// \brief Divides the vector by a scalar.
///
/// \param[in] rhs The scalar.
/// \return The divided vector.
vec& operator/=(const T & rhs)
{
x /= rhs;
y /= rhs;
return *this;
}
// Public Methods /////////////////////////////////////////////////////////
public:
/// \brief The vector's dimension.
///
/// \return The vector's dimension.
size_t dim() const { return 2; }
/// \brief Negates the vector.
///
/// \return The negated vector.
vec neg() const
{
// TODO: Issue when the underlying type is an unsigned integer.
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4146)
#endif
return vec(-x, -y);
#if defined (_MSC_VER)
#pragma warning(pop)
#endif
}
/// \brief The vector's magnitude.
///
/// \return The magnitude.
T mag() const
{
// TODO: Might want this method to return a float even if the underlying
// data type is integer.
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4244)
#endif
#if (defined(_MSC_VER) && _MSC_VER <= 1600)
// HACK: Visual Studio 2010 has trouble determining the correct 'sqrt'
// function for the template int32_t.
return sqrt(static_cast<float>(x*x + y*y));
#else
// HACK:
return sqrt(static_cast<float>(x*x + y*y));
//return sqrt(x*x + y*y);
#endif
#if defined (_MSC_VER)
#pragma warning(pop)
#endif
}
/// \brief Adds a vector to this vector.
///
/// \param[in] toAdd The vector to add.
/// \return The resulting vector.
vec add(const vec& toAdd) const
{
return vec(x + toAdd.x, y + toAdd.y);
}
/// \brief Subtracts a vector from this vector.
///
/// \param[in] to_sub The vector to subtract from this.
/// \return The resulting vector.
vec sub(const vec& to_sub) const
{
return vec(x - to_sub.x, y - to_sub.y);
}
/// \brief Multiplies the vector by a scalar.
///
/// \param[in] scalar The scalar value.
/// \return The multiplied vector.
vec mult(const double& scalar) const
{
return vec(x * scalar, y * scalar);
}
/// \brief Divides the vector by a scalar.
///
/// \param[in] scalar The scalar value.
/// \return The divided vector.
vec div(const double& scalar) const
{
return vec(x / scalar, y / scalar);
}
/// \brief Normalizes the vector.
///
/// \return The normalized vector.
vec norm() const
{
T m = mag();
return vec(x / m, y / m);
}
/// \brief Computes the dot product of this and the provided vector.
///
/// \param[in] rhs The right-side vector.
/// \return The computed dot product.
T dot(const vec& rhs) const
{
return x*rhs.x + y*rhs.y;
}
};
/// \brief Vector with 3 component specialization.
template <typename T>
struct vec<3, T>
{
// Public Members /////////////////////////////////////////////////////////
public:
union
{
struct
{
/// \brief X (0-component).
T x;
/// \brief Y (1-component).
T y;
/// \brief Z (2-component).
T z;
};
struct
{
/// \brief Red (0-component).
T r;
/// \brief Green (1-component).
T g;
/// \brief Blue (2-component).
T b;
};
// Union of template class with constructor not allowed until C++11.
#if __cplusplus >= 201103L
/// \brief XY (0,1-components).
vec<2, T> xy;
#endif
/// \brief The vector's components.
T c[3];
};
// Constructors ///////////////////////////////////////////////////////////
public:
/// \brief Creates a new vector with uninitialized components.
vec() { }
/// \brief Creates new vector with components initialized to val.
///
/// \param[in] val The initialization value.
explicit vec(T val) : x(val), y(val), z(val) { }
/// \brief Creates a new vector with its components initialized to the
/// provided values.
///
/// \param[in] x_val The x value.
/// \param[in] y_val The y value.
/// \param[in] z_val The z value.
vec(const T& x_val, const T& y_val, const T& z_val) : x(x_val), y(y_val), z(z_val) { }
// Helper Methods /////////////////////////////////////////////////////////
public:
/// \brief Vector with all of its components set to 0.
///
/// \return The 0 vector.
static vec zero()
{
return vec<3, T>(0);
}
/// \brief Vector with all of its components set to 1.
///
/// \return The 1 vector.
static vec one()
{
return vec<3, T>(1);
}
/// \brief Unit vector pointing in the X (0-component) direction.
///
/// \return The unit vector.
static vec unitX()
{
return vec<3, T>(1, 0, 0);
}
/// \brief Unit vector pointing in the Y (1-component) direction.
///
/// \return The unit vector.
static vec unitY()
{
return vec<3, T>(0, 1, 0);
}
/// \brief Unit vector pointing in the Z (2-component) direction.
///
/// \return The unit vector.
static vec unitZ()
{
return vec<3, T>(0, 0, 1);
}
// Operator Overloads /////////////////////////////////////////////////////
public:
/// \brief Indexing into the vector's components.
///
/// \param[in] index 0-based component index.
/// \exception dimension_error The index exceeded the dimension of the vector.
T& operator[](size_t index)
{
return const_cast<T&>(static_cast<const vec&>(*this)[index]);
}
/// \brief Indexing into the vector's components.
///
/// \param[in] index 0-based component index.
/// \exception dimension_error The index exceeded the dimension of the vector.
const T& operator[](size_t index) const
{
assert(index < 3);
return c[index];
}
/// \brief Negates the vector.
///
/// \return The negated vector.
vec operator-() const
{
return neg();
}
/// \brief Adds a vector to this vector.
///
/// \param[in] rhs The right-side vector.
/// \return The resulting vector.
vec& operator+=(const vec& rhs)
{
for (size_t i = 0; i < 3; i++)
c[i] += rhs.c[i];
return *this;
}
/// \brief Subtracts a vector from this vector.
///
/// \param[in] rhs The right-side vector.
/// \return The resulting vector.
vec& operator-=(const vec& rhs)
{
for (size_t i = 0; i < 3; i++)
c[i] -= rhs.c[i];
return *this;
}
/// \brief Multiplies the vector by a scalar.
///
/// \param[in] rhs The scalar.
/// \return The multiplied vector.
vec& operator*=(const T& rhs)
{
for (size_t i = 0; i < 3; i++)
c[i] *= rhs;
return *this;
}
/// \brief Divides the vector by a scalar.
///
/// \param[in] rhs The scalar.
/// \return The divided vector.
vec& operator/=(const T & rhs)
{
for (size_t i = 0; i < 3; i++)
c[i] /= rhs;
return *this;
}
// Public Methods /////////////////////////////////////////////////////////
public:
/// \brief The vector's dimension.
///
/// \return The vector's dimension.
size_t dim() const { return 3; }
/// \brief Negates the vector.
///
/// \return The negated vector.
vec neg() const
{
// TODO: Issue when the underlying type is an unsigned integer.
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4146)
#endif
return vec(-x, -y, -z);
#if defined (_MSC_VER)
#pragma warning(pop)
#endif
}
/// \brief The vector's magnitude.
///
/// \return The magnitude.
T mag() const
{
// TODO: Might want this method to return a float even if the underlying
// data type is integer.
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4244)
#endif
#if (defined(_MSC_VER) && _MSC_VER <= 1600)
// HACK: Visual Studio 2010 has trouble determining the correct 'sqrt'
// function for the template int32_t.
return sqrt(static_cast<float>(x*x + y*y + z*z));
#else
// HACK:
return sqrt(static_cast<float>(x*x + y*y + z*z));
//return sqrt(x*x + y*y + z*z);
#endif
#if defined (_MSC_VER)
#pragma warning(pop)
#endif
}
/// \brief Adds a vector to this vector.
///
/// \param[in] toAdd The vector to add.
/// \return The resulting vector.
vec add(const vec& toAdd) const
{
return vec(x + toAdd.x, y + toAdd.y, z + toAdd.z);
}
/// \brief Subtracts a vector from this vector.
///
/// \param[in] to_sub The vector to subtract from this.
/// \return The resulting vector.
vec sub(const vec& to_sub) const
{
return vec(x - to_sub.x, y - to_sub.y, z - to_sub.z);
}
/// \brief Multiplies the vector by a scalar.
///
/// \param[in] scalar The scalar value.
/// \return The multiplied vector.
vec mult(const double& scalar) const
{
return vec(x * scalar, y * scalar, z * scalar);
}
/// \brief Divides the vector by a scalar.
///
/// \param[in] scalar The scalar value.
/// \return The divided vector.
vec div(const double& scalar) const
{
return vec(x / scalar, y / scalar, z / scalar);
}
/// \brief Normalizes the vector.
///
/// \return The normalized vector.
vec norm() const
{
T m = mag();
return vec(x / m, y / m, z / m);
}
/// \brief Computes the dot product of this and the provided vector.
///
/// \param[in] rhs The right-side vector.
/// \return The computed dot product.
T dot(const vec& rhs) const
{
return x*rhs.x + y*rhs.y + z*rhs.z;
}
/// \brief Computes the cross product of this and the provided vector.
///
/// \param[in] rhs The right-side vector.
/// \return The computed cross product.
/// \exception dimension_error The dimension of the vector is not 3.
vec<3, T> cross(const vec<3, T>& rhs) const
{
vec<3, T> v;
v.c[0] = c[1] * rhs.c[2] - c[2] * rhs.c[1];
v.c[1] = c[2] * rhs.c[0] - c[0] * rhs.c[2];
v.c[2] = c[0] * rhs.c[1] - c[1] * rhs.c[0];
return v;
}
};
/// \brief Vector with 4 component specialization.
template <typename T>
struct vec<4, T>
{
// Public Members /////////////////////////////////////////////////////////
public:
union
{
struct
{
/// \brief X (0-component).
T x;
/// \brief Y (1-component).
T y;
/// \brief Z (2-component).
T z;
/// \brief W (3-component).
T w;
};
struct
{
/// \brief Red (0-component).
T r;
/// \brief Green (1-component).
T g;
/// \brief Blue (2-component).
T b;
/// \brief Alpha (3-component).
T a;
};
// Union of template class with constructor not allowed until C++11.
#if __cplusplus >= 201103L
/// \brief XY (0,1-components).
vec<2, T> xy;
/// \brief XYZ (0,1,2-components).
vec<3, T> xyz;
/// \brief RGB (0,1,2-components).
vec<3, T> rgb;
#endif
/// \brief The vector's components.
T c[4];
};
// Constructors ///////////////////////////////////////////////////////////
public:
/// \brief Creates a new vector with uninitialized components.
vec() { }
/// \brief Creates new vector with components initialized to val.
///
/// \param[in] val The initialization value.
explicit vec(T val) : x(val), y(val), z(val), w(val) { }
/// \brief Creates a new vector with its components inintialized to the
/// provided values.
///
/// \param[in] x_val The x value.
/// \param[in] y_val The y value.
/// \param[in] z_val The z value.
/// \param[in] w_val The w value.
vec(T x_val, T y_val, T z_val, T w_val) : x(x_val), y(y_val), z(z_val), w(w_val) { }
// Helper Methods /////////////////////////////////////////////////////////
public:
/// \brief Vector with all of its components set to 0.
///
/// \return The 0 vector.
static vec zero()
{
return vec<4, T>(0);
}
/// \brief Vector with all of its components set to 1.
///
/// \return The 1 vector.
static vec one()
{
return vec<4, T>(1);
}
/// \brief Unit vector pointing in the X (0-component) direction.
///
/// \return The unit vector.
static vec unitX()
{
return vec<4, T>(1, 0, 0, 0);
}
/// \brief Unit vector pointing in the Y (1-component) direction.
///
/// \return The unit vector.
static vec unitY()
{
return vec<4, T>(0, 1, 0, 0);
}
/// \brief Unit vector pointing in the Z (2-component) direction.
///
/// \return The unit vector.
static vec unitZ()
{
return vec<4, T>(0, 0, 1, 0);
}
/// \brief Unit vector pointing in the W (3-component) direction.
///
/// \return The unit vector.
static vec unitW()
{
return vec<4, T>(0, 0, 0, 1);
}
// Operator Overloads /////////////////////////////////////////////////////
public:
/// \brief Indexing into the vector's components.
///
/// \param[in] index 0-based component index.
/// \exception dimension_error The index exceeded the dimension of the vector.
T& operator[](size_t index)
{
return const_cast<T&>(static_cast<const vec&>(*this)[index]);
}
/// \brief Indexing into the vector's components.
///
/// \param[in] index 0-based component index.
/// \exception dimension_error The index exceeded the dimension of the vector.
const T& operator[](size_t index) const
{
assert(index < 4);
return c[index];
}
/// \brief Negates the vector.
///
/// \return The negated vector.
vec operator-() const
{
return neg();
}
/// \brief Adds a vector to this vector.
///
/// \param[in] rhs The right-side vector.
/// \return The resulting vector.
vec& operator+=(const vec& rhs)
{
x += rhs.x;
y += rhs.y;
z += rhs.z;
w += rhs.w;
return *this;
}
/// \brief Subtracts a vector from this vector.
///
/// \param[in] rhs The right-side vector.
/// \return The resulting vector.
vec& operator-=(const vec& rhs)
{
x -= rhs.x;
y -= rhs.y;
z -= rhs.z;
w -= rhs.w;
return *this;
}
/// \brief Multiplies the vector by a scalar.
///
/// \param[in] rhs The scalar.
/// \return The multiplied vector.
vec& operator*=(const T& rhs)
{
x *= rhs;
y *= rhs;
z *= rhs;
w *= rhs;
return *this;
}
/// \brief Divides the vector by a scalar.
///
/// \param[in] rhs The scalar.
/// \return The divided vector.
vec& operator/=(const T & rhs)
{
x /= rhs;
y /= rhs;
z /= rhs;
w /= rhs;
return *this;
}
// Public Methods /////////////////////////////////////////////////////////
public:
/// \brief The vector's dimension.
///
/// \return The vector's dimension.
size_t dim() const { return 4; }
/// \brief Negates the vector.
///
/// \return The negated vector.
vec neg() const
{
// TODO: Issue when the underlying type is an unsigned integer.
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4146)
#endif
return vec(-x, -y, -z, -w);
#if defined (_MSC_VER)
#pragma warning(pop)
#endif
}
/// \brief The vector's magnitude.
///
/// \return The magnitude.
T mag() const
{
// TODO: Might want this method to return a float even if the underlying
// data type is integer.
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4244)
#endif
#if (defined(_MSC_VER) && _MSC_VER <= 1600)
// HACK: Visual Studio 2010 has trouble determining the correct 'sqrt'
// function for the template int32_t.
return sqrt(static_cast<float>(x*x + y*y + z*z + w*w));
#else
// HACK:
return sqrt(static_cast<float>(x*x + y*y + z*z + w*w));
//return sqrt(x*x + y*y + z*z + w*w);
#endif
#if defined (_MSC_VER)
#pragma warning(pop)
#endif
}
/// \brief Adds a vector to this vector.
///
/// \param[in] toAdd The vector to add.
/// \return The resulting vector.
vec add(const vec& toAdd) const
{
return vec(x + toAdd.x, y + toAdd.y, z + toAdd.z, w + toAdd.w);
}
/// \brief Subtracts a vector from this vector.
///
/// \param[in] to_sub The vector to subtract from this.
/// \return The resulting vector.
vec sub(const vec& to_sub) const
{
return vec(x - to_sub.x, y - to_sub.y, z - to_sub.z, w - to_sub.w);
}
/// \brief Multiplies the vector by a scalar.
///
/// \param[in] scalar The scalar value.
/// \return The multiplied vector.
vec mult(const double& scalar) const
{
return vec(x * scalar, y * scalar, z * scalar, w * scalar);
}
/// \brief Divides the vector by a scalar.
///
/// \param[in] scalar The scalar value.
/// \return The divided vector.
vec div(const double& scalar) const
{
return vec(x / scalar, y / scalar, z / scalar, w / scalar);
}
/// \brief Normalizes the vector.
///
/// \return The normalized vector.
vec norm() const
{
T m = mag();
return vec(x / m, y / m, z / m, w / m);
}
/// \brief Computes the dot product of this and the provided vector.
///
/// \param[in] rhs The right-side vector.
/// \return The computed dot product.
T dot(const vec& rhs) const
{
return x*rhs.x + y*rhs.y + z*rhs.z + w*rhs.w;
}
};
#if defined (_MSC_VER)
#pragma warning(pop)
#endif
// Operator Overloads /////////////////////////////////////////////////////////
/// \brief Adds two vectors together.
///
/// \param[in] lhs The left-side vector.
/// \param[in] rhs The right-side vector.
/// \return The resulting vector.
template <size_t tdim, typename T>
vec<tdim, T> operator+(vec<tdim, T> lhs, const vec<tdim, T>& rhs)
{
lhs += rhs;
return lhs;
}
/// \brief Subtracts a vector from another vector.
///
/// \param[in] lhs The left-side vector.
/// \param[in] rhs The right-side vector.
/// \return The resulting vector.
template <size_t tdim, typename T>
vec<tdim, T> operator-(vec<tdim, T> lhs, const vec<tdim, T>& rhs)
{
lhs -= rhs;
return lhs;
}
#if defined(_MSC_VER)
#pragma warning(push)
// The operator* and operator/ throw a warning when a vec*f is multiplied by a double.
#pragma warning(disable:4244)
#endif
/// \brief Multiplies a vector by a scalar. Done both ways for python
///
/// \param[in] lhs The scalar.
/// \param[in] rhs The vector.
/// \return The result.
template <size_t tdim, typename T, typename S>
vec<tdim, T> operator*(vec<tdim, T> lhs, const S& rhs)
{
lhs *= rhs;
return lhs;
}
/// \brief Multiplies a vector by a scalar. Done both ways for Python
///
/// \param[in] lhs The vector.
/// \param[in] rhs The scalar.
/// \return The result.
template <size_t tdim, typename T, typename S>
vec<tdim, T> operator*(const S& rhs, vec<tdim, T> lhs)
{
lhs *= rhs;
return lhs;
}
/// \brief Divides a vector by a scalar.
///
/// \param[in] lhs The vector.
/// \param[in] rhs The scalar.
/// \return The result.
template <size_t tdim, typename T, typename S>
vec<tdim, T> operator/(vec<tdim, T> lhs, const S& rhs)
{
lhs /= rhs;
return lhs;
}
#if defined (_MSC_VER)
#pragma warning(pop)
#endif
// Specific Typedefs //////////////////////////////////////////////////////////
/// \brief 2-component vector using <c>float</c> as its underlying data type.
typedef vec<2> vec2;
/// \brief 3-component vector using <c>float</c> as its underlying data type.
typedef vec<3> vec3;
/// \brief 4-component vector using <c>float</c> as its underlying data type.
typedef vec<4> vec4;
/// \brief 2-component vector using <c>float</c> as its underlying data type.
typedef vec<2, float> vec2f;
/// \brief 3-component vector using <c>float</c> as its underlying data type.
typedef vec<3, float> vec3f;
/// \brief 4-component vector using <c>float</c> as its underlying data type.
typedef vec<4, float> vec4f;
/// \brief 2-component vector using <c>double</c> as its underlying data type.
typedef vec<2, double> vec2d;
/// \brief 3-component vector using <c>double</c> as its underlying data type.
typedef vec<3, double> vec3d;
/// \brief 4-component vector using <c>double</c> as its underlying data type.
typedef vec<4, double> vec4d;
/// \brief 2-component vector using <c>long double</c> as its underlying data type.
typedef vec<2, long double> vec2ld;
/// \brief 3-component vector using <c>long double</c> as its underlying data type.
typedef vec<3, long double> vec3ld;
/// \brief 4-component vector using <c>long double</c> as its underlying data type.
typedef vec<4, long double> vec4ld;
/// \brief 2-component vector using <c>int32_t</c> as its underlying data type.
typedef vec<2, int32_t> vec2i32;
/// \brief Namenclature used by OpenGL API.
typedef vec2i32 ivec2;
/// \brief 3-component vector using <c>int32_t</c> as its underlying data type.
typedef vec<3, int32_t> vec3i32;
/// \brief 4-component vector using <c>int32_t</c> as its underlying data type.
typedef vec<4, int32_t> vec4i32;
/// \brief 2-component vector using <c>uint32_t</c> as its underlying data type.
typedef vec<2, uint32_t> vec2u32;
/// \brief 3-component vector using <c>uint32_t</c> as its underlying data type.
typedef vec<3, uint32_t> vec3u32;
/// \brief 4-component vector using <c>uint32_t</c> as its underlying data type.
typedef vec<4, uint32_t> vec4u32;
// Common functions for working with vectors.
/// \brief Provides a method to generate a representable string from a provided
/// vector.
///
/// \param[in] v The vector to convert to string.
/// \return The string representation.
template <size_t tdim, typename T> std::string str(vec<tdim, T> v)
{
std::stringstream ss;
ss << "(";
for (size_t i = 0; i < v.dim(); i++)
{
ss << v[i];
if (i + 1 < v.dim())
ss << "; ";
}
ss << ")";
return ss.str();
}
/// \brief Overloads the ostream << operator for easy usage in displaying
/// vectors.
///
/// \param[in] out The ostream being output to.
/// \param[in] v The vector to output to ostream.
/// \return Reference to the current ostream.
template <size_t tdim, typename T> std::ostream& operator<<(std::ostream& out, vec<tdim, T> v)
{
out << str(v);
return out;
}
}
}
#endif