.\" .\" Copyright (c) 2009-2022 Julien Nadeau Carriere .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED .\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, .\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES .\" (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR .\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, .\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" .Dd December 21, 2022 .Dt M_VECTOR 3 .Os Agar 1.7 .Sh NAME .Nm M_Vector .Nd Agar-Math vector-related functions .Sh SYNOPSIS .Bd -literal #include #include #include .Ed .Sh DESCRIPTION .\" BEGIN DUP in M_Vector(3) The .Nm and .Xr M_Matrix 3 interfaces implement linear algebra operations on (real or complex valued) .Va n dimensional vectors, and .Va m by .Va n matrices. Optimized interfaces are provided for fixed-dimensional types (which have entries directly accessible as .Va x , .Va y , .Va z and .Va 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. .Pp 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". .\" END DUP .Sh VECTORS IN R^N The following routines operate on dynamically-allocated vectors in R^n. Unlike .Ft M_Matrix (which might use different memory representations), vector entries are always directly accessible through the .Va v array. The .Ft M_Vector structure is defined as: .Bd -literal .\" SYNTAX(c) typedef struct m_vector { Uint m; /* Size */ M_Real *v; /* Elements */ } M_Vector; .Ed .Pp The following backends are currently available for .Ft M_Vector : .Pp .Bl -tag -width "fpu " -compact .It fpu Native scalar floating point methods. .El .Sh VECTORS IN R^N: INITIALIZATION .nr nS 1 .Ft "M_Vector *" .Fn M_VecNew "Uint m" .Pp .Ft "void" .Fn M_VecFree "M_Vector *v" .Pp .Ft int .Fn M_VecResize "M_Vector *v" "Uint m" .Pp .Ft void .Fn M_VecSetZero "M_Vector *v" .Pp .Ft "M_Vector *" .Fn M_ReadVector "AG_DataSource *ds" .Pp .Ft void .Fn M_WriteVector "AG_DataSource *ds" "const M_Vector *v" .Pp .nr nS 0 The .Fn M_VecNew function allocates a new vector in R^n. .Fn M_VecFree releases all resources allocated for the specified vector. .Pp .Fn M_VecResize resizes the vector .Fa v to .Fa 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. .Pp .Fn M_VecSetZero initializes .Fa v to the zero vector. .Pp .Fn M_ReadVector reads a .Ft M_Vector from a data source and .Fn M_WriteVector writes vector .Fa v to a data source; see .Xr AG_DataSource 3 for details. .Sh VECTORS IN R^N: ACCESSING ELEMENTS .nr nS 1 .Ft "M_Real *" .Fn M_VecGetElement "const M_Vector *v" "Uint i" .Pp .Ft "M_Real" .Fn M_VecGet "const M_Vector *v" "Uint i" .Pp .Ft "M_Vector *" .Fn M_VecFromReals "Uint n" "const M_Real *values" .Pp .Ft "M_Vector *" .Fn M_VecFromFloats "Uint n" "const float *values" .Pp .Ft "M_Vector *" .Fn M_VecFromDoubles "Uint n" "const double *values" .Pp .nr nS 0 .Fn M_VecGetElement returns a direct pointer to entry .Fa i in the (non-sparse) vector .Fa v . The .Fn M_VecGet function returns the value of entry .Fa i in a vector .Fa v , which can be a sparse vector. .Pp .Fn M_VecFromReals , .Fn M_VecFromFloats , and .Fn M_VecFromDoubles generate an .Nm from an array of .Ft M_Real , .Ft float or .Ft double . .Sh VECTORS IN R^N: BASIC OPERATIONS .nr nS 1 .Ft int .Fn M_VecCopy "M_Vector *vDst" "const M_Vector *vSrc" .Pp .Ft "M_Vector *" .Fn M_VecFlip "const M_Vector *v" .Pp .Ft "M_Vector *" .Fn M_VecScale "const M_Vector *v" "M_Real c" .Pp .Ft "void" .Fn M_VecScalev "M_Vector *v" "M_Real c" .Pp .Ft "M_Vector *" .Fn M_VecAdd "const M_Vector *a" "const M_Vector *b" .Pp .Ft int .Fn M_VecAddv "M_Vector *a" "const M_Vector *b" .Pp .Ft "M_Vector *" .Fn M_VecSub "const M_Vector *a" "const M_Vector *b" .Pp .Ft int .Fn M_VecSubv "M_Vector *a" "const M_Vector *b" .Pp .Ft M_Real .Fn M_VecLen "const M_Vector *v" .Pp .Ft M_Real .Fn M_VecDot "const M_Vector *a" "const M_Vector *b" .Pp .Ft M_Real .Fn M_VecDistance "const M_Vector *a" "const M_Vector *b" .Pp .Ft "M_Vector *" .Fn M_VecNorm "const M_Vector *v" .Pp .Ft "M_Vector *" .Fn M_VecLERP "const M_Vector *a" "const M_Vector *b" "M_Real t" .Pp .Ft "M_Vector *" .Fn M_VecElemPow "const M_Vector *v" "M_Real pow" .Pp .nr nS 0 The .Fn M_VecCopy routine copies the contents of vector .Fa vSrc into .Fa vDst . Both vectors must have the same size. .Pp The .Fn M_VecFlip function returns the vector .Fa v scaled to -1. .Pp .Fn M_VecScale scales the vector .Fa v by factor .Fa c and returns the resulting vector. .Fn M_VecScalev scales the vector in place. .Pp .Fn M_VecAdd returns the sum of .Fa a and .Fa b , which must be of equal size. The .Fn M_VecAddv variant writes the result back into .Fa a . .Pp .Fn M_VecSub returns the difference (a - b). Both vectors must be of equal size. The .Fn M_VecSubv variant writes the result back into .Fa a . .Pp .Fn M_VecLen returns the Euclidean length of a vector. .Pp .Fn M_VecDot returns the dot product of vectors .Fa a and .Fa b . .Pp .Fn M_VecDistance returns the Euclidean distance between .Fa a and .Fa b . .Pp .Fn M_VecNorm returns the normalized (unit-length) form of .Fa v . .Pp .Fn M_VecLERP returns the result of linear interpolation between equally-sized vectors .Fa a and .Fa b , with scaling factor .Fa t . .Pp .Fn M_ElemPow raises the entries of .Fa v to the power .Fa pow , and returns the resulting vector. .\" MANLINK(M_Vector2) .Sh VECTORS IN R^2 The following routines operate on vectors in R^2, which are always represented by the structure: .Bd -literal .\" SYNTAX(c) typedef struct m_vector2 { M_Real x, y; } M_Vector2; .Ed .Pp The following backends are currently available for .Ft M_Vector2 : .Pp .Bl -tag -width "fpu " -compact .It fpu Native scalar floating point methods. .El .Sh VECTORS IN R^2: INITIALIZATION .nr nS 1 .Ft M_Vector2 .Fn M_VecI2 "void" .Pp .Ft M_Vector2 .Fn M_VecJ2 "void" .Pp .Ft M_Vector2 .Fn M_VecZero2 "void" .Pp .Ft M_Vector2 .Fn M_VecGet2 "M_Real x" "M_Real y" .Pp .Ft M_Vector2 .Fn M_VECTOR2 "M_Real x" "M_Real y" .Pp .Ft void .Fn M_VecSet2 "M_Vector2 *v" "M_Real x" "M_Real y" .Pp .Ft void .Fn M_VecCopy2 "M_Vector2 *vDst" "const M_Vector2 *vSrc" .Pp .Ft M_Vector2 .Fn M_VecFromProj2 "M_Vector3 p" .Pp .Ft M_Vector3 .Fn M_VecToProj2 "M_Vector2 v" "M_Real z" .Pp .Ft M_Vector2 .Fn M_ReadVector2 "AG_DataSource *ds" .Pp .Ft void .Fn M_WriteVector2 "AG_DataSource *ds" "const M_Vector2 *v" .Pp .nr nS 0 The .Fn M_VecI2 and .Fn M_VecJ2 routines return the basis vectors [1;0] and [0;1], respectively. .Fn M_VecZero2 returns the zero vector [0;0]. .Fn M_VecGet2 returns the vector [x,y]. The .Fn M_VECTOR2 macro expands to a static initializer for the vector [x,y]. .Pp .Fn M_VecSet2 writes the values [x,y] into vector .Fa v (note that entries are also directly accessible via the .Ft M_Vector2 structure). .Pp .Fn M_VecFromProj2 returns an Euclidean vector corresponding to .Fa p in projective space. If .Fa p is at infinity, a fatal divide-by-zero condition is raised. .Fn M_VecToProj2 returns the vector in projective space corresponding to .Fa v in Euclidean space (if w=1), or .Fa v at infinity (if w=0). .Pp .Fn M_ReadVector2 reads a .Ft M_Vector2 from a data source and .Fn M_WriteVector2 writes vector .Fa v to a data source; see .Xr AG_DataSource 3 for details. .Sh VECTORS IN R^2: BASIC OPERATIONS .nr nS 1 .Ft int .Fn M_VecCopy2 "M_Vector2 *vDst" "const M_Vector2 *vSrc" .Pp .Ft M_Vector2 .Fn M_VecFlip2 "M_Vector2 v" .Pp .Ft M_Real .Fn M_VecLen2 "M_Vector2 v" .Pp .Ft M_Real .Fn M_VecLen2p "const M_Vector2 *v" .Pp .Ft M_Real .Fn M_VecDot2 "M_Vector2 a" "M_Vector2 b" .Pp .Ft M_Real .Fn M_VecDot2p "const M_Vector2 *a" "const M_Vector2 *b" .Pp .Ft M_Real .Fn M_VecPerpDot2 "M_Vector2 a" "M_Vector2 b" .Pp .Ft M_Real .Fn M_VecPerpDot2p "const M_Vector2 *a" "const M_Vector2 *b" .Pp .Ft M_Real .Fn M_VecDistance2 "M_Vector2 a" "M_Vector2 b" .Pp .Ft M_Real .Fn M_VecDistance2p "const M_Vector2 *a" "const M_Vector2 *b" .Pp .Ft M_Vector2 .Fn M_VecNorm2 "M_Vector2 v" .Pp .Ft M_Vector2 .Fn M_VecNorm2p "const M_Vector2 *v" .Pp .Ft void .Fn M_VecNorm2v "M_Vector2 *v" .Pp .Ft M_Vector2 .Fn M_VecScale2 "M_Vector2 v" "M_Real c" .Pp .Ft M_Vector2 .Fn M_VecScale2p "const M_Vector2 *v" "M_Real c" .Pp .Ft void .Fn M_VecScale2v "M_Vector2 *v" "M_Real c" .Pp .Ft M_Vector2 .Fn M_VecAdd2 "M_Vector2 a" "M_Vector2 b" .Pp .Ft M_Vector2 .Fn M_VecAdd2p "const M_Vector2 *a" "const M_Vector2 *b" .Pp .Ft void .Fn M_VecAdd2v "M_Vector2 *a" "const M_Vector2 *b" .Pp .Ft M_Vector2 .Fn M_VecSum2 "const M_Vector2 *vs" "Uint count" .Pp .Ft M_Vector2 .Fn M_VecSub2 "M_Vector2 a" "M_Vector2 b" .Pp .Ft M_Vector2 .Fn M_VecSub2p "const M_Vector2 *a" "const M_Vector2 *b" .Pp .Ft void .Fn M_VecSub2v "M_Vector2 *a" "const M_Vector2 *b" .Pp .Ft M_Vector2 .Fn M_VecAvg2 "M_Vector2 a" "M_Vector2 b" .Pp .Ft M_Vector2 .Fn M_VecAvg2p "const M_Vector2 *a" "const M_Vector2 *b" .Pp .Ft M_Vector2 .Fn M_VecLERP2 "M_Vector2 a" "M_Vector2 b" "M_Real t" .Pp .Ft M_Vector2 .Fn M_VecLERP2p "M_Vector2 *a" "M_Vector2 *b" "M_Real t" .Pp .Ft M_Vector2 .Fn M_VecElemPow2 "M_Vector2 *v" "M_Real pow" .Pp .Ft M_Real .Fn M_VecVecAngle2 "M_Vector2 a" "M_Vector2 b" .Pp .nr nS 0 The .Fn M_VecCopy2 function copies the contents of vector .Fa vSrc into .Fa vDst . .Pp The function .Fn M_VecFlip2 returns the vector scaled to -1. .Pp .Fn M_VecLen2 and .Fn M_VecLen2p return the real length of vector .Fa v , that is Sqrt(x^2 + y^2). .Pp .Fn M_VecDot2 and .Fn M_VecDot2p return the dot product of vectors .Fa a and .Fa b , that is (a.x*b.x + a.y*b.y). .Pp .Fn M_VecPerpDot2 and .Fn M_VecPerpDot2p compute the "perp dot product" of .Fa a and .Fa b , which is (a.x*b.y - a.y*b.x). .Pp .Fn M_VecDistance2 and .Fn M_VecDistance2p return the real distance between vectors .Fa a and .Fa b , that is the length of the difference vector (a - b). .Pp .Fn M_VecNorm2 and .Fn M_VecNorm2p return the normalized (unit-length) form of .Fa v . The .Fn M_VecNorm2v variant normalizes the vector in-place. .Pp .Fn M_VecScale2 and .Fn M_VecScale2p multiplies vector .Fa v by scalar .Fa c and returns the result. The .Fn M_VecScale2v variant scales the vector in-place. .Pp .Fn M_VecAdd2 and .Fn M_VecAdd2p return the sum of vectors .Fa a and .Fa b . The .Fn M_VecAdd2v variant returns the result back into .Fa a . The .Fn M_VecSum2 function returns the vector sum of the .Fa count vectors in the .Fa vs array. .Pp .Fn M_VecSub2 and .Fn M_VecSub2p return the difference of vectors (a-b). The .Fn M_VecSub2v variant returns the result back into .Fa a . .Pp The .Fn M_VecAvg2 and .Fn M_VecAvg2p routines compute the average of two vectors (a+b)/2. .Pp The functions .Fn M_VecLERP2 and .Fn M_VecLERP2p interpolate linearly between vectors .Fa a and .Fa b , using the scaling factor .Fa t and returns the result. The result is computed as a+(b-a)*t. .Pp .Fn M_VecElemPow2 raises the entries of .Fa v to the power .Fa pow , and returns the resulting vector. .Pp .Fn M_VecVecAngle2 returns the angle (in radians) between vectors .Fa a and .Fa b , about the origin. .\" MANLINK(M_Vector3) .Sh VECTORS IN R^3 The following routines operate on vectors in R^3, which are represented by the structure: .Bd -literal .\" SYNTAX(c) #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 .Ed .Pp 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 .Ft M_Vector type may be used). .Pp The following backends are currently available for .Ft M_Vector3 : .Pp .Bl -tag -width "fpu " -compact .It fpu Native scalar floating point methods. .It sse Accelerate operations using Streaming SIMD Extensions (SSE). .It sse3 Accelerate operations using SSE3 extensions. .El .Sh VECTORS IN R^3: INITIALIZATION .nr nS 1 .Ft M_Vector3 .Fn M_VecI3 "void" .Pp .Ft M_Vector3 .Fn M_VecJ3 "void" .Pp .Ft M_Vector3 .Fn M_VecK3 "void" .Pp .Ft M_Vector3 .Fn M_VecZero3 "void" .Pp .Ft M_Vector3 .Fn M_VecGet3 "M_Real x" "M_Real y" "M_Real z" .Pp .Ft M_Vector3 .Fn M_VECTOR3 "M_Real x" "M_Real y" "M_Real z" .Pp .Ft void .Fn M_VecSet3 "M_Vector3 *v" "M_Real x" "M_Real y" "M_Real z" .Pp .Ft void .Fn M_VecCopy3 "M_Vector3 *vDst" "const M_Vector3 *vSrc" .Pp .Ft M_Vector3 .Fn M_VecFromProj3 "M_Vector4 p" .Pp .Ft M_Vector4 .Fn M_VecToProj3 "M_Vector3 v" "M_Real w" .Pp .Ft M_Vector3 .Fn M_ReadVector3 "AG_DataSource *ds" .Pp .Ft void .Fn M_WriteVector3 "AG_DataSource *ds" "const M_Vector3 *v" .Pp .nr nS 0 The .Fn M_VecI3 , .Fn M_VecJ3 and .Fn M_VecK3 routines return the basis vectors [1;0;0], [0;1;0] and [0;0;1], respectively. .Fn M_VecZero3 returns the zero vector [0;0;0]. .Fn M_VecGet3 returns the vector [x,y,z]. The .Fn M_VECTOR3 macro expands to a static initializer for the vector [x,y,z]. .Pp .Fn M_VecSet3 writes the values [x,y,z] into vector .Fa v (note that entries are also directly accessible via the .Ft M_Vector3 structure). .Pp .Fn M_VecFromProj3 returns an Euclidean vector corresponding to the specified vector .Fa p in projective space. If .Fa p is at infinity, a fatal divide-by-zero condition is raised. .Pp .Fn M_ReadVector3 reads a .Ft M_Vector3 from a data source and .Fn M_WriteVector3 writes vector .Fa v to a data source; see .Xr AG_DataSource 3 for details. .Sh VECTORS IN R^3: BASIC OPERATIONS .nr nS 1 .Ft int .Fn M_VecCopy3 "M_Vector3 *vDst" "const M_Vector3 *vSrc" .Pp .Ft M_Vector3 .Fn M_VecFlip3 "M_Vector3 v" .Pp .Ft M_Real .Fn M_VecLen3 "M_Vector3 v" .Pp .Ft M_Real .Fn M_VecLen3p "const M_Vector3 *v" .Pp .Ft M_Real .Fn M_VecDot3 "M_Vector3 a" "M_Vector3 b" .Pp .Ft M_Real .Fn M_VecDot3p "const M_Vector3 *a" "const M_Vector3 *b" .Pp .Ft M_Real .Fn M_VecDistance3 "M_Vector3 a" "M_Vector3 b" .Pp .Ft M_Real .Fn M_VecDistance3p "const M_Vector3 *a" "const M_Vector3 *b" .Pp .Ft M_Vector3 .Fn M_VecNorm3 "M_Vector3 v" .Pp .Ft M_Vector3 .Fn M_VecNorm3p "const M_Vector3 *v" .Pp .Ft void .Fn M_VecNorm3v "M_Vector3 *v" .Pp .Ft M_Vector3 .Fn M_VecCross3 "M_Vector3 a" "M_Vector3 b" .Pp .Ft M_Vector3 .Fn M_VecCross3p "const M_Vector3 *a" "const M_Vector3 *b" .Pp .Ft M_Vector3 .Fn M_VecNormCross3 "M_Vector3 a" "M_Vector3 b" .Pp .Ft M_Vector3 .Fn M_VecNormCross3p "const M_Vector3 *a" "const M_Vector3 *b" .Pp .Ft M_Vector3 .Fn M_VecScale3 "M_Vector3 v" "M_Real c" .Pp .Ft M_Vector3 .Fn M_VecScale3p "const M_Vector3 *v" "M_Real c" .Pp .Ft void .Fn M_VecScale3v "M_Vector3 *v" "M_Real c" .Pp .Ft M_Vector3 .Fn M_VecAdd3 "M_Vector3 a" "M_Vector3 b" .Pp .Ft M_Vector3 .Fn M_VecAdd3p "const M_Vector3 *a" "const M_Vector3 *b" .Pp .Ft void .Fn M_VecAdd3v "M_Vector3 *a" "const M_Vector3 *b" .Pp .Ft M_Vector3 .Fn M_VecSum3 "const M_Vector3 *vs" "Uint count" .Pp .Ft M_Vector3 .Fn M_VecSub3 "M_Vector3 a" "M_Vector3 b" .Pp .Ft M_Vector3 .Fn M_VecSub3p "const M_Vector3 *a" "const M_Vector3 *b" .Pp .Ft void .Fn M_VecSub3v "M_Vector3 *a" "const M_Vector3 *b" .Pp .Ft M_Vector3 .Fn M_VecAvg3 "M_Vector3 a" "M_Vector3 b" .Pp .Ft M_Vector3 .Fn M_VecAvg3p "const M_Vector3 *a" "const M_Vector3 *b" .Pp .Ft M_Vector3 .Fn M_VecLERP3 "M_Vector3 a" "M_Vector3 b" "M_Real t" .Pp .Ft M_Vector3 .Fn M_VecLERP3p "M_Vector3 *a" "M_Vector3 *b" "M_Real t" .Pp .Ft M_Vector3 .Fn M_VecElemPow3 "M_Vector3 *v" "M_Real pow" .Pp .Ft void .Fn M_VecVecAngle3 "M_Vector3 a" "M_Vector3 b" "M_Real *theta" "M_Real *phi" .Pp .nr nS 0 The .Fn M_VecCopy3 function copies the contents of vector .Fa vSrc into .Fa vDst . .Pp The function .Fn M_VecFlip3 returns the vector scaled to -1. .Pp .Fn M_VecLen3 and .Fn M_VecLen3p return the real length of vector .Fa v , that is Sqrt(x^2 + y^2 + z^2). .Pp .Fn M_VecDot3 and .Fn M_VecDot3p return the dot product of vectors .Fa a and .Fa b , that is (a.x*b.x + a.y*b.y + a.z*b.z). .Pp .Fn M_VecDistance3 and .Fn M_VecDistance3p return the real distance between vectors .Fa a and .Fa b , that is the length of the difference vector (a - b). .Pp .Fn M_VecNorm3 and .Fn M_VecNorm3p return the normalized (unit-length) form of .Fa v . The .Fn M_VecNorm3v variant normalizes the vector in-place. .Pp .Fn M_VecCross3 and .Fn M_VecCross3p return the cross-product (also known as the "vector product" or "Gibbs vector product) of vectors .Fa a and .Fa b . .Pp .Fn M_VecNormCross3 and .Fn M_VecNormCross3 return the normalized cross-product of vectors .Fa a and .Fa b . This is a useful operation in computer graphics (e.g., for computing plane normals from the vertices of a triangle). .Pp .Fn M_VecScale3 and .Fn M_VecScale3p multiplies vector .Fa v by scalar .Fa c and returns the result. The .Fn M_VecScale3v variant scales the vector in-place. .Pp .Fn M_VecAdd3 and .Fn M_VecAdd3p return the sum of vectors .Fa a and .Fa b . The .Fn M_VecAdd3v variant returns the result back into .Fa a . The .Fn M_VecSum3 function returns the vector sum of the .Fa count vectors in the .Fa vs array. .Pp .Fn M_VecSub3 and .Fn M_VecSub3p return the difference of vectors (a-b). The .Fn M_VecSub3v variant returns the result back into .Fa a . .Pp The .Fn M_VecAvg3 and .Fn M_VecAvg3p routines compute the average of two vectors (a+b)/2. .Pp The functions .Fn M_VecLERP3 and .Fn M_VecLERP3p interpolate linearly between vectors .Fa a and .Fa b , using the scaling factor .Fa t and returns the result. The result is computed as a+(b-a)*t. .Pp .Fn M_VecElemPow3 raises the entries of .Fa v to the power .Fa pow , and returns the resulting vector. .Pp .Fn M_VecVecAngle3 returns the two angles (in radians) between vectors .Fa a and .Fa b , about the origin. .\" MANLINK(M_Vector4) .Sh VECTORS IN R^4 The following routines operate on vectors in R^4, which are represented by the structure: .Bd -literal .\" SYNTAX(c) #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 .Ed .Pp 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 .Ft M_Vector type may be used). .Pp The following backends are currently available for .Ft M_Vector4 : .Pp .Bl -tag -width "fpu " -compact .It fpu Native scalar floating point methods. .It sse Accelerate operations using Streaming SIMD Extensions (SSE). .It sse3 Accelerate operations using SSE3 extensions. .El .Sh VECTORS IN R^4: INITIALIZATION .nr nS 1 .Ft M_Vector4 .Fn M_VecI4 "void" .Pp .Ft M_Vector4 .Fn M_VecJ4 "void" .Pp .Ft M_Vector4 .Fn M_VecK4 "void" .Pp .Ft M_Vector4 .Fn M_VecL4 "void" .Pp .Ft M_Vector4 .Fn M_VecZero4 "void" .Pp .Ft M_Vector4 .Fn M_VecGet4 "M_Real x" "M_Real y" "M_Real z" "M_Real w" .Pp .Ft M_Vector4 .Fn M_VECTOR4 "M_Real x" "M_Real y" "M_Real z" "M_Real w" .Pp .Ft void .Fn M_VecSet4 "M_Vector4 *v" "M_Real x" "M_Real y" "M_Real z" "M_Real w" .Pp .Ft void .Fn M_VecCopy4 "M_Vector4 *vDst" "const M_Vector4 *vSrc" .Pp .Ft M_Vector4 .Fn M_ReadVector4 "AG_DataSource *ds" .Pp .Ft void .Fn M_WriteVector4 "AG_DataSource *ds" "const M_Vector4 *v" .Pp .nr nS 0 The .Fn M_VecI4 , .Fn M_VecJ4 , .Fn M_VecK4 and .Fn 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. .Fn M_VecZero4 returns the zero vector [0;0;0;0]. .Fn M_VecGet4 returns the vector [x,y,z,w]. The .Fn M_VECTOR4 macro expands to a static initializer for the vector [x,y,z,w]. .Pp .Fn M_VecSet4 writes the values [x,y,z,w] into vector .Fa v (note that entries are also directly accessible via the .Ft M_Vector4 structure). .Pp .Fn M_ReadVector4 reads a .Ft M_Vector4 from a data source and .Fn M_WriteVector4 writes vector .Fa v to a data source; see .Xr AG_DataSource 4 for details. .Sh VECTORS IN R^4: BASIC OPERATIONS .nr nS 1 .Ft int .Fn M_VecCopy4 "M_Vector4 *vDst" "const M_Vector4 *vSrc" .Pp .Ft M_Vector4 .Fn M_VecFlip4 "M_Vector4 v" .Pp .Ft M_Real .Fn M_VecLen4 "M_Vector4 v" .Pp .Ft M_Real .Fn M_VecLen4p "const M_Vector4 *v" .Pp .Ft M_Real .Fn M_VecDot4 "M_Vector4 a" "M_Vector4 b" .Pp .Ft M_Real .Fn M_VecDot4p "const M_Vector4 *a" "const M_Vector4 *b" .Pp .Ft M_Real .Fn M_VecDistance4 "M_Vector4 a" "M_Vector4 b" .Pp .Ft M_Real .Fn M_VecDistance4p "const M_Vector4 *a" "const M_Vector4 *b" .Pp .Ft M_Vector4 .Fn M_VecNorm4 "M_Vector4 v" .Pp .Ft M_Vector4 .Fn M_VecNorm4p "const M_Vector4 *v" .Pp .Ft void .Fn M_VecNorm4v "M_Vector4 *v" .Pp .Ft M_Vector4 .Fn M_VecScale4 "M_Vector4 v" "M_Real c" .Pp .Ft M_Vector4 .Fn M_VecScale4p "const M_Vector4 *v" "M_Real c" .Pp .Ft void .Fn M_VecScale4v "M_Vector4 *v" "M_Real c" .Pp .Ft M_Vector4 .Fn M_VecAdd4 "M_Vector4 a" "M_Vector4 b" .Pp .Ft M_Vector4 .Fn M_VecAdd4p "const M_Vector4 *a" "const M_Vector4 *b" .Pp .Ft void .Fn M_VecAdd4v "M_Vector4 *a" "const M_Vector4 *b" .Pp .Ft M_Vector4 .Fn M_VecSum4 "const M_Vector4 *vs" "Uint count" .Pp .Ft M_Vector4 .Fn M_VecSub4 "M_Vector4 a" "M_Vector4 b" .Pp .Ft M_Vector4 .Fn M_VecSub4p "const M_Vector4 *a" "const M_Vector4 *b" .Pp .Ft void .Fn M_VecSub4v "M_Vector4 *a" "const M_Vector4 *b" .Pp .Ft M_Vector4 .Fn M_VecAvg4 "M_Vector4 a" "M_Vector4 b" .Pp .Ft M_Vector4 .Fn M_VecAvg4p "const M_Vector4 *a" "const M_Vector4 *b" .Pp .Ft M_Vector4 .Fn M_VecLERP4 "M_Vector4 a" "M_Vector4 b" "M_Real t" .Pp .Ft M_Vector4 .Fn M_VecLERP4p "M_Vector4 *a" "M_Vector4 *b" "M_Real t" .Pp .Ft M_Vector4 .Fn M_VecElemPow4 "M_Vector4 *v" "M_Real pow" .Pp .Ft void .Fn M_VecVecAngle4 "M_Vector4 a" "M_Vector4 b" "M_Real *phi1" "M_Real *phi2" "M_Real *phi3" .Pp .nr nS 0 The .Fn M_VecCopy4 function copies the contents of vector .Fa vSrc into .Fa vDst . .Pp The function .Fn M_VecFlip4 returns the vector scaled to -1. .Pp .Fn M_VecLen4 and .Fn M_VecLen4p return the real length of vector .Fa v , that is Sqrt(x^2 + y^2 + z^2 + w^2). .Pp .Fn M_VecDot4 and .Fn M_VecDot4p return the dot product of vectors .Fa a and .Fa b , that is (a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w). .Pp .Fn M_VecDistance4 and .Fn M_VecDistance4p return the real distance between vectors .Fa a and .Fa b , that is the length of the difference vector (a - b). .Pp .Fn M_VecNorm4 and .Fn M_VecNorm4p return the normalized (unit-length) form of .Fa v . The .Fn M_VecNorm4v variant normalizes the vector in-place. .Pp .Fn M_VecScale4 and .Fn M_VecScale4p multiplies vector .Fa v by scalar .Fa c and returns the result. The .Fn M_VecScale4v variant scales the vector in-place. .Pp .Fn M_VecAdd4 and .Fn M_VecAdd4p return the sum of vectors .Fa a and .Fa b . The .Fn M_VecAdd4v variant returns the result back into .Fa a . The .Fn M_VecSum4 function returns the vector sum of the .Fa count vectors in the .Fa vs array. .Pp .Fn M_VecSub4 and .Fn M_VecSub4p return the difference of vectors (a-b). The .Fn M_VecSub4v variant returns the result back into .Fa a . .Pp The .Fn M_VecAvg4 and .Fn M_VecAvg4p routines compute the average of two vectors (a+b)/2. .Pp The functions .Fn M_VecLERP4 and .Fn M_VecLERP4p interpolate linearly between vectors .Fa a and .Fa b , using the scaling factor .Fa t and returns the result. The result is computed as a+(b-a)*t. .Pp .Fn M_VecElemPow4 raises the entries of .Fa v to the power .Fa pow , and returns the resulting vector. .Pp .Fn M_VecVecAngle4 returns the three angles (in radians) between vectors .Fa a and .Fa b , about the origin. .Sh SEE ALSO .Xr AG_Intro 3 , .Xr M_Complex 3 , .Xr M_Matrix 3 , .Xr M_Matview 3 , .Xr M_Quaternion 3 , .Xr M_Real 3 .Sh HISTORY The .Nm interface first appeared in Agar 1.3.4.