M_Vector
—
Agar-Math vector-related functions
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 on vector-capable platforms, all
M_Vector
operations may be expanded inline for the
target platform (using the Agar build options "--with-sse-inline"
and "--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_Vector *
M_VecFromLongDoubles
(Uint
n, const long 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.
The M_VecFromReals
(),
M_VecFromFloats
(),
M_VecFromDoubles
(), and
M_VecFromLongDoubles
() functions generate an
M_Vector
from an array of
M_Real, float,
double or long double,
respectively. The latter function is only available on platforms where
HAVE_LONG_DOUBLE
is defined.
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.