M_Vector —
Agar-Math vector-related functions
#include <agar/core.h>
#include <agar/gui.h>
#include <agar/math/m.h>
The M_Vector and
M_Matrix(3)
interfaces implement linear algebra operations on (real or complex valued)
n dimensional vectors, and m by
n matrices. Optimized interfaces are provided for
fixed-dimensional types (which have entries directly accessible as
x, y, z
and w). Arbitrary-dimensional types may or may not use
fixed arrays in memory. For example, the "sparse" backend uses a
sparse matrix representation, and the "db" backend stores vector
entries in a database.
Backends can be selected at run-time, or Agar-Math can be compiled
to provide inline expansions of all operations of a specific backend. Vector
extensions (such as SSE and AltiVec) are used by default, if a runtime
cpuinfo check determines that they are available (the build remains
compatible with non-vector platforms, at the cost of extra function calls).
For best performance, Agar should be compiled with
"--with-sse=inline", or "--with-altivec=inline".
The following routines operate on dynamically-allocated vectors in
R^n. Unlike M_Matrix (which might use different memory
representations), vector entries are always directly accessible through the
v array. The M_Vector structure
is defined as:
typedef struct m_vector {
Uint m; /* Size */
M_Real *v; /* Elements */
} M_Vector;
The following backends are currently available for
M_Vector:
- fpu
- Native scalar floating point methods.
M_Vector *
M_VecNew(Uint
m);
void
M_VecFree(M_Vector
*v);
int
M_VecResize(M_Vector
*v, Uint m);
void
M_VecSetZero(M_Vector
*v);
M_Vector *
M_ReadVector(AG_DataSource
*ds);
void
M_WriteVector(AG_DataSource
*ds, const M_Vector
*v);
The
M_VecNew()
function allocates a new vector in R^n. M_VecFree()
releases all resources allocated for the specified vector.
M_VecResize()
resizes the vector v to m.
Existing entries are preserved, but new entries are left uninitialized. If
insufficient memory is available, -1 is returned and an error message is
set. On success, the function returns 0.
M_VecSetZero()
initializes v to the zero vector.
M_ReadVector()
reads a M_Vector from a data source and
M_WriteVector() writes vector
v to a data source; see
AG_DataSource(3)
for details.
M_Real *
M_VecGetElement(const
M_Vector *v, Uint
i);
M_Real
M_VecGet(const
M_Vector *v, Uint
i);
M_Vector *
M_VecFromReals(Uint
n, const M_Real
*values);
M_Vector *
M_VecFromFloats(Uint
n, const float
*values);
M_Vector *
M_VecFromDoubles(Uint
n, const double
*values);
M_VecGetElement()
returns a direct pointer to entry i in the
(non-sparse) vector v. The
M_VecGet() function returns the value of entry
i in a vector v, which can be a
sparse vector.
M_VecFromReals(),
M_VecFromFloats(), and
M_VecFromDoubles() generate an
M_Vector from an array of
M_Real, float or
double.
int
M_VecCopy(M_Vector
*vDst, const M_Vector
*vSrc);
M_Vector *
M_VecFlip(const
M_Vector *v);
M_Vector *
M_VecScale(const
M_Vector *v, M_Real
c);
void
M_VecScalev(M_Vector
*v, M_Real c);
M_Vector *
M_VecAdd(const
M_Vector *a, const
M_Vector *b);
int
M_VecAddv(M_Vector
*a, const M_Vector
*b);
M_Vector *
M_VecSub(const
M_Vector *a, const
M_Vector *b);
int
M_VecSubv(M_Vector
*a, const M_Vector
*b);
M_Real
M_VecLen(const
M_Vector *v);
M_Real
M_VecDot(const
M_Vector *a, const
M_Vector *b);
M_Real
M_VecDistance(const
M_Vector *a, const
M_Vector *b);
M_Vector *
M_VecNorm(const
M_Vector *v);
M_Vector *
M_VecLERP(const
M_Vector *a, const
M_Vector *b, M_Real
t);
M_Vector *
M_VecElemPow(const
M_Vector *v, M_Real
pow);
The
M_VecCopy()
routine copies the contents of vector vSrc into
vDst. Both vectors must have the same size.
The
M_VecFlip()
function returns the vector v scaled to -1.
M_VecScale()
scales the vector v by factor c
and returns the resulting vector. M_VecScalev()
scales the vector in place.
M_VecAdd()
returns the sum of a and b,
which must be of equal size. The M_VecAddv() variant
writes the result back into a.
M_VecSub()
returns the difference (a - b). Both vectors must be of equal size. The
M_VecSubv() variant writes the result back into
a.
M_VecLen()
returns the Euclidean length of a vector.
M_VecDot()
returns the dot product of vectors a and
b.
M_VecDistance()
returns the Euclidean distance between a and
b.
M_VecNorm()
returns the normalized (unit-length) form of v.
M_VecLERP()
returns the result of linear interpolation between equally-sized vectors
a and b, with scaling factor
t.
M_ElemPow()
raises the entries of v to the power
pow, and returns the resulting vector.
The following routines operate on vectors in R^2, which are always
represented by the structure:
typedef struct m_vector2 {
M_Real x, y;
} M_Vector2;
The following backends are currently available for
M_Vector2:
- fpu
- Native scalar floating point methods.
M_Vector2
M_VecI2(void);
M_Vector2
M_VecJ2(void);
M_Vector2
M_VecZero2(void);
M_Vector2
M_VecGet2(M_Real
x, M_Real y);
M_Vector2
M_VECTOR2(M_Real
x, M_Real y);
void
M_VecSet2(M_Vector2
*v, M_Real x,
M_Real y);
void
M_VecCopy2(M_Vector2
*vDst, const M_Vector2
*vSrc);
M_Vector2
M_VecFromProj2(M_Vector3
p);
M_Vector3
M_VecToProj2(M_Vector2
v, M_Real z);
M_Vector2
M_ReadVector2(AG_DataSource
*ds);
void
M_WriteVector2(AG_DataSource
*ds, const M_Vector2
*v);
The
M_VecI2()
and M_VecJ2() routines return the basis vectors
[1;0] and [0;1], respectively. M_VecZero2() returns
the zero vector [0;0]. M_VecGet2() returns the
vector [x,y]. The M_VECTOR2() macro expands to a
static initializer for the vector [x,y].
M_VecSet2()
writes the values [x,y] into vector v (note that
entries are also directly accessible via the M_Vector2
structure).
M_VecFromProj2()
returns an Euclidean vector corresponding to p in
projective space. If p is at infinity, a fatal
divide-by-zero condition is raised. M_VecToProj2()
returns the vector in projective space corresponding to
v in Euclidean space (if w=1), or
v at infinity (if w=0).
M_ReadVector2()
reads a M_Vector2 from a data source and
M_WriteVector2() writes vector
v to a data source; see
AG_DataSource(3)
for details.
int
M_VecCopy2(M_Vector2
*vDst, const M_Vector2
*vSrc);
M_Vector2
M_VecFlip2(M_Vector2
v);
M_Real
M_VecLen2(M_Vector2
v);
M_Real
M_VecLen2p(const
M_Vector2 *v);
M_Real
M_VecDot2(M_Vector2
a, M_Vector2
b);
M_Real
M_VecDot2p(const
M_Vector2 *a, const
M_Vector2 *b);
M_Real
M_VecPerpDot2(M_Vector2
a, M_Vector2
b);
M_Real
M_VecPerpDot2p(const
M_Vector2 *a, const
M_Vector2 *b);
M_Real
M_VecDistance2(M_Vector2
a, M_Vector2
b);
M_Real
M_VecDistance2p(const
M_Vector2 *a, const
M_Vector2 *b);
M_Vector2
M_VecNorm2(M_Vector2
v);
M_Vector2
M_VecNorm2p(const
M_Vector2 *v);
void
M_VecNorm2v(M_Vector2
*v);
M_Vector2
M_VecScale2(M_Vector2
v, M_Real c);
M_Vector2
M_VecScale2p(const
M_Vector2 *v, M_Real
c);
void
M_VecScale2v(M_Vector2
*v, M_Real c);
M_Vector2
M_VecAdd2(M_Vector2
a, M_Vector2
b);
M_Vector2
M_VecAdd2p(const
M_Vector2 *a, const
M_Vector2 *b);
void
M_VecAdd2v(M_Vector2
*a, const M_Vector2
*b);
M_Vector2
M_VecSum2(const
M_Vector2 *vs, Uint
count);
M_Vector2
M_VecSub2(M_Vector2
a, M_Vector2
b);
M_Vector2
M_VecSub2p(const
M_Vector2 *a, const
M_Vector2 *b);
void
M_VecSub2v(M_Vector2
*a, const M_Vector2
*b);
M_Vector2
M_VecAvg2(M_Vector2
a, M_Vector2
b);
M_Vector2
M_VecAvg2p(const
M_Vector2 *a, const
M_Vector2 *b);
M_Vector2
M_VecLERP2(M_Vector2
a, M_Vector2 b,
M_Real t);
M_Vector2
M_VecLERP2p(M_Vector2
*a, M_Vector2 *b,
M_Real t);
M_Vector2
M_VecElemPow2(M_Vector2
*v, M_Real
pow);
M_Real
M_VecVecAngle2(M_Vector2
a, M_Vector2
b);
The
M_VecCopy2()
function copies the contents of vector vSrc into
vDst.
The function
M_VecFlip2()
returns the vector scaled to -1.
M_VecLen2()
and M_VecLen2p() return the real length of vector
v, that is Sqrt(x^2 + y^2).
M_VecDot2()
and M_VecDot2p() return the dot product of vectors
a and b, that is (a.x*b.x +
a.y*b.y).
M_VecPerpDot2()
and M_VecPerpDot2p() compute the "perp dot
product" of a and b, which
is (a.x*b.y - a.y*b.x).
M_VecDistance2()
and M_VecDistance2p() return the real distance
between vectors a and b, that is
the length of the difference vector (a - b).
M_VecNorm2()
and M_VecNorm2p() return the normalized
(unit-length) form of v. The
M_VecNorm2v() variant normalizes the vector
in-place.
M_VecScale2()
and M_VecScale2p() multiplies vector
v by scalar c and returns the
result. The M_VecScale2v() variant scales the vector
in-place.
M_VecAdd2()
and M_VecAdd2p() return the sum of vectors
a and b. The
M_VecAdd2v() variant returns the result back into
a. The M_VecSum2() function
returns the vector sum of the count vectors in the
vs array.
M_VecSub2()
and M_VecSub2p() return the difference of vectors
(a-b). The M_VecSub2v() variant returns the result
back into a.
The
M_VecAvg2()
and M_VecAvg2p() routines compute the average of two
vectors (a+b)/2.
The functions
M_VecLERP2()
and M_VecLERP2p() interpolate linearly between
vectors a and b, using the
scaling factor t and returns the result. The result is
computed as a+(b-a)*t.
M_VecElemPow2()
raises the entries of v to the power
pow, and returns the resulting vector.
M_VecVecAngle2()
returns the angle (in radians) between vectors a and
b, about the origin.
The following routines operate on vectors in R^3, which are
represented by the structure:
#ifdef HAVE_SSE
typedef union m_vector3 {
__m128 m128;
struct { float x, y, z, _pad; };
} M_Vector3;
#else
typedef struct m_vector3 {
M_Real x, y, z;
} M_Vector3;
#endif
Notice that SIMD extensions force single-precision floats,
regardless of the precision for which Agar-Math was built (if a
3-dimensional vector of higher precision is required, the general
M_Vector type may be used).
The following backends are currently available for
M_Vector3:
- fpu
- Native scalar floating point methods.
- sse
- Accelerate operations using Streaming SIMD Extensions (SSE).
- sse3
- Accelerate operations using SSE3 extensions.
M_Vector3
M_VecI3(void);
M_Vector3
M_VecJ3(void);
M_Vector3
M_VecK3(void);
M_Vector3
M_VecZero3(void);
M_Vector3
M_VecGet3(M_Real
x, M_Real y,
M_Real z);
M_Vector3
M_VECTOR3(M_Real
x, M_Real y,
M_Real z);
void
M_VecSet3(M_Vector3
*v, M_Real x,
M_Real y,
M_Real z);
void
M_VecCopy3(M_Vector3
*vDst, const M_Vector3
*vSrc);
M_Vector3
M_VecFromProj3(M_Vector4
p);
M_Vector4
M_VecToProj3(M_Vector3
v, M_Real w);
M_Vector3
M_ReadVector3(AG_DataSource
*ds);
void
M_WriteVector3(AG_DataSource
*ds, const M_Vector3
*v);
The
M_VecI3(),
M_VecJ3() and M_VecK3()
routines return the basis vectors [1;0;0], [0;1;0] and [0;0;1],
respectively. M_VecZero3() returns the zero vector
[0;0;0]. M_VecGet3() returns the vector [x,y,z]. The
M_VECTOR3() macro expands to a static initializer
for the vector [x,y,z].
M_VecSet3()
writes the values [x,y,z] into vector v (note that
entries are also directly accessible via the M_Vector3
structure).
M_VecFromProj3()
returns an Euclidean vector corresponding to the specified vector
p in projective space. If p is
at infinity, a fatal divide-by-zero condition is raised.
M_ReadVector3()
reads a M_Vector3 from a data source and
M_WriteVector3() writes vector
v to a data source; see
AG_DataSource(3)
for details.
int
M_VecCopy3(M_Vector3
*vDst, const M_Vector3
*vSrc);
M_Vector3
M_VecFlip3(M_Vector3
v);
M_Real
M_VecLen3(M_Vector3
v);
M_Real
M_VecLen3p(const
M_Vector3 *v);
M_Real
M_VecDot3(M_Vector3
a, M_Vector3
b);
M_Real
M_VecDot3p(const
M_Vector3 *a, const
M_Vector3 *b);
M_Real
M_VecDistance3(M_Vector3
a, M_Vector3
b);
M_Real
M_VecDistance3p(const
M_Vector3 *a, const
M_Vector3 *b);
M_Vector3
M_VecNorm3(M_Vector3
v);
M_Vector3
M_VecNorm3p(const
M_Vector3 *v);
void
M_VecNorm3v(M_Vector3
*v);
M_Vector3
M_VecCross3(M_Vector3
a, M_Vector3
b);
M_Vector3
M_VecCross3p(const
M_Vector3 *a, const
M_Vector3 *b);
M_Vector3
M_VecNormCross3(M_Vector3
a, M_Vector3
b);
M_Vector3
M_VecNormCross3p(const
M_Vector3 *a, const
M_Vector3 *b);
M_Vector3
M_VecScale3(M_Vector3
v, M_Real c);
M_Vector3
M_VecScale3p(const
M_Vector3 *v, M_Real
c);
void
M_VecScale3v(M_Vector3
*v, M_Real c);
M_Vector3
M_VecAdd3(M_Vector3
a, M_Vector3
b);
M_Vector3
M_VecAdd3p(const
M_Vector3 *a, const
M_Vector3 *b);
void
M_VecAdd3v(M_Vector3
*a, const M_Vector3
*b);
M_Vector3
M_VecSum3(const
M_Vector3 *vs, Uint
count);
M_Vector3
M_VecSub3(M_Vector3
a, M_Vector3
b);
M_Vector3
M_VecSub3p(const
M_Vector3 *a, const
M_Vector3 *b);
void
M_VecSub3v(M_Vector3
*a, const M_Vector3
*b);
M_Vector3
M_VecAvg3(M_Vector3
a, M_Vector3
b);
M_Vector3
M_VecAvg3p(const
M_Vector3 *a, const
M_Vector3 *b);
M_Vector3
M_VecLERP3(M_Vector3
a, M_Vector3 b,
M_Real t);
M_Vector3
M_VecLERP3p(M_Vector3
*a, M_Vector3 *b,
M_Real t);
M_Vector3
M_VecElemPow3(M_Vector3
*v, M_Real
pow);
void
M_VecVecAngle3(M_Vector3
a, M_Vector3 b,
M_Real *theta,
M_Real *phi);
The
M_VecCopy3()
function copies the contents of vector vSrc into
vDst.
The function
M_VecFlip3()
returns the vector scaled to -1.
M_VecLen3()
and M_VecLen3p() return the real length of vector
v, that is Sqrt(x^2 + y^2 + z^2).
M_VecDot3()
and M_VecDot3p() return the dot product of vectors
a and b, that is (a.x*b.x +
a.y*b.y + a.z*b.z).
M_VecDistance3()
and M_VecDistance3p() return the real distance
between vectors a and b, that is
the length of the difference vector (a - b).
M_VecNorm3()
and M_VecNorm3p() return the normalized
(unit-length) form of v. The
M_VecNorm3v() variant normalizes the vector
in-place.
M_VecCross3()
and M_VecCross3p() return the cross-product (also
known as the "vector product" or "Gibbs vector product) of
vectors a and b.
M_VecNormCross3()
and M_VecNormCross3() return the normalized
cross-product of vectors a and
b. This is a useful operation in computer graphics
(e.g., for computing plane normals from the vertices of a triangle).
M_VecScale3()
and M_VecScale3p() multiplies vector
v by scalar c and returns the
result. The M_VecScale3v() variant scales the vector
in-place.
M_VecAdd3()
and M_VecAdd3p() return the sum of vectors
a and b. The
M_VecAdd3v() variant returns the result back into
a. The M_VecSum3() function
returns the vector sum of the count vectors in the
vs array.
M_VecSub3()
and M_VecSub3p() return the difference of vectors
(a-b). The M_VecSub3v() variant returns the result
back into a.
The
M_VecAvg3()
and M_VecAvg3p() routines compute the average of two
vectors (a+b)/2.
The functions
M_VecLERP3()
and M_VecLERP3p() interpolate linearly between
vectors a and b, using the
scaling factor t and returns the result. The result is
computed as a+(b-a)*t.
M_VecElemPow3()
raises the entries of v to the power
pow, and returns the resulting vector.
M_VecVecAngle3()
returns the two angles (in radians) between vectors a
and b, about the origin.
The following routines operate on vectors in R^4, which are
represented by the structure:
#ifdef HAVE_SSE
typedef union m_vector4 {
__m128 m128;
struct { float x, y, z, w; };
} M_Vector4;
#else
typedef struct m_vector4 {
M_Real x, y, z, w;
} M_Vector4;
#endif
Notice that SIMD extensions force single-precision floats,
regardless of the precision for which Agar-Math was built (if a
4-dimensional vector of higher precision is required, the general
M_Vector type may be used).
The following backends are currently available for
M_Vector4:
- fpu
- Native scalar floating point methods.
- sse
- Accelerate operations using Streaming SIMD Extensions (SSE).
- sse3
- Accelerate operations using SSE3 extensions.
M_Vector4
M_VecI4(void);
M_Vector4
M_VecJ4(void);
M_Vector4
M_VecK4(void);
M_Vector4
M_VecL4(void);
M_Vector4
M_VecZero4(void);
M_Vector4
M_VecGet4(M_Real
x, M_Real y,
M_Real z,
M_Real w);
M_Vector4
M_VECTOR4(M_Real
x, M_Real y,
M_Real z,
M_Real w);
void
M_VecSet4(M_Vector4
*v, M_Real x,
M_Real y,
M_Real z,
M_Real w);
void
M_VecCopy4(M_Vector4
*vDst, const M_Vector4
*vSrc);
M_Vector4
M_ReadVector4(AG_DataSource
*ds);
void
M_WriteVector4(AG_DataSource
*ds, const M_Vector4
*v);
The
M_VecI4(),
M_VecJ4(), M_VecK4() and
M_VecL4() routines return the basis vectors
[1;0;0;0], [0;1;0;0], [0;0;1;0] and [0;0;0;1], respectively.
M_VecZero4() returns the zero vector [0;0;0;0].
M_VecGet4() returns the vector [x,y,z,w]. The
M_VECTOR4() macro expands to a static initializer
for the vector [x,y,z,w].
M_VecSet4()
writes the values [x,y,z,w] into vector v (note that
entries are also directly accessible via the M_Vector4
structure).
M_ReadVector4()
reads a M_Vector4 from a data source and
M_WriteVector4() writes vector
v to a data source; see
AG_DataSource(4)
for details.
int
M_VecCopy4(M_Vector4
*vDst, const M_Vector4
*vSrc);
M_Vector4
M_VecFlip4(M_Vector4
v);
M_Real
M_VecLen4(M_Vector4
v);
M_Real
M_VecLen4p(const
M_Vector4 *v);
M_Real
M_VecDot4(M_Vector4
a, M_Vector4
b);
M_Real
M_VecDot4p(const
M_Vector4 *a, const
M_Vector4 *b);
M_Real
M_VecDistance4(M_Vector4
a, M_Vector4
b);
M_Real
M_VecDistance4p(const
M_Vector4 *a, const
M_Vector4 *b);
M_Vector4
M_VecNorm4(M_Vector4
v);
M_Vector4
M_VecNorm4p(const
M_Vector4 *v);
void
M_VecNorm4v(M_Vector4
*v);
M_Vector4
M_VecScale4(M_Vector4
v, M_Real c);
M_Vector4
M_VecScale4p(const
M_Vector4 *v, M_Real
c);
void
M_VecScale4v(M_Vector4
*v, M_Real c);
M_Vector4
M_VecAdd4(M_Vector4
a, M_Vector4
b);
M_Vector4
M_VecAdd4p(const
M_Vector4 *a, const
M_Vector4 *b);
void
M_VecAdd4v(M_Vector4
*a, const M_Vector4
*b);
M_Vector4
M_VecSum4(const
M_Vector4 *vs, Uint
count);
M_Vector4
M_VecSub4(M_Vector4
a, M_Vector4
b);
M_Vector4
M_VecSub4p(const
M_Vector4 *a, const
M_Vector4 *b);
void
M_VecSub4v(M_Vector4
*a, const M_Vector4
*b);
M_Vector4
M_VecAvg4(M_Vector4
a, M_Vector4
b);
M_Vector4
M_VecAvg4p(const
M_Vector4 *a, const
M_Vector4 *b);
M_Vector4
M_VecLERP4(M_Vector4
a, M_Vector4 b,
M_Real t);
M_Vector4
M_VecLERP4p(M_Vector4
*a, M_Vector4 *b,
M_Real t);
M_Vector4
M_VecElemPow4(M_Vector4
*v, M_Real
pow);
void
M_VecVecAngle4(M_Vector4
a, M_Vector4 b,
M_Real *phi1,
M_Real *phi2,
M_Real *phi3);
The
M_VecCopy4()
function copies the contents of vector vSrc into
vDst.
The function
M_VecFlip4()
returns the vector scaled to -1.
M_VecLen4()
and M_VecLen4p() return the real length of vector
v, that is Sqrt(x^2 + y^2 + z^2 + w^2).
M_VecDot4()
and M_VecDot4p() return the dot product of vectors
a and b, that is (a.x*b.x +
a.y*b.y + a.z*b.z + a.w*b.w).
M_VecDistance4()
and M_VecDistance4p() return the real distance
between vectors a and b, that is
the length of the difference vector (a - b).
M_VecNorm4()
and M_VecNorm4p() return the normalized
(unit-length) form of v. The
M_VecNorm4v() variant normalizes the vector
in-place.
M_VecScale4()
and M_VecScale4p() multiplies vector
v by scalar c and returns the
result. The M_VecScale4v() variant scales the vector
in-place.
M_VecAdd4()
and M_VecAdd4p() return the sum of vectors
a and b. The
M_VecAdd4v() variant returns the result back into
a. The M_VecSum4() function
returns the vector sum of the count vectors in the
vs array.
M_VecSub4()
and M_VecSub4p() return the difference of vectors
(a-b). The M_VecSub4v() variant returns the result
back into a.
The
M_VecAvg4()
and M_VecAvg4p() routines compute the average of two
vectors (a+b)/2.
The functions
M_VecLERP4()
and M_VecLERP4p() interpolate linearly between
vectors a and b, using the
scaling factor t and returns the result. The result is
computed as a+(b-a)*t.
M_VecElemPow4()
raises the entries of v to the power
pow, and returns the resulting vector.
M_VecVecAngle4()
returns the three angles (in radians) between vectors
a and b, about the origin.
The M_Vector interface first appeared in
Agar 1.3.4.