/* SCE CONFIDENTIAL
PLAYSTATION(R)3 Programmer Tool Runtime Library 084.006
* Copyright (C) 2006 Sony Computer Entertainment Inc.
* All Rights Reserved.
*/

#ifndef _VECTORMATH_SOA_C_H
#define _VECTORMATH_SOA_C_H

#include <math.h>
#include <altivec.h>
#include "vectormath_aos.h"

#ifdef _VECTORMATH_DEBUG
#include <stdio.h>
#endif

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

#ifndef _VECTORMATH_SOA_C_TYPES_H
#define _VECTORMATH_SOA_C_TYPES_H

/* A set of four 3-D vectors in structure-of-arrays format
 */
typedef struct _VmathSoaVector3
{
    vec_float4 x;
    vec_float4 y;
    vec_float4 z;
} VmathSoaVector3;

/* A set of four 4-D vectors in structure-of-arrays format
 */
typedef struct _VmathSoaVector4
{
    vec_float4 x;
    vec_float4 y;
    vec_float4 z;
    vec_float4 w;
} VmathSoaVector4;

/* A set of four 3-D points in structure-of-arrays format
 */
typedef struct _VmathSoaPoint3
{
    vec_float4 x;
    vec_float4 y;
    vec_float4 z;
} VmathSoaPoint3;

/* A set of four quaternions in structure-of-arrays format
 */
typedef struct _VmathSoaQuat
{
    vec_float4 x;
    vec_float4 y;
    vec_float4 z;
    vec_float4 w;
} VmathSoaQuat;

/* A set of four 3x3 matrices in structure-of-arrays format
 */
typedef struct _VmathSoaMatrix3
{
    VmathSoaVector3 col0;
    VmathSoaVector3 col1;
    VmathSoaVector3 col2;
} VmathSoaMatrix3;

/* A set of four 4x4 matrices in structure-of-arrays format
 */
typedef struct _VmathSoaMatrix4
{
    VmathSoaVector4 col0;
    VmathSoaVector4 col1;
    VmathSoaVector4 col2;
    VmathSoaVector4 col3;
} VmathSoaMatrix4;

/* A set of four 3x4 transformation matrices in structure-of-arrays format
 */
typedef struct _VmathSoaTransform3
{
    VmathSoaVector3 col0;
    VmathSoaVector3 col1;
    VmathSoaVector3 col2;
    VmathSoaVector3 col3;
} VmathSoaTransform3;

#endif

/*
 * Copy a 3-D vector
 */
static inline void vmathSoaV3Copy( VmathSoaVector3 *result, const VmathSoaVector3 *vec );

/*
 * Construct a 3-D vector from x, y, and z elements
 */
static inline void vmathSoaV3MakeFromElems( VmathSoaVector3 *result, vec_float4 x, vec_float4 y, vec_float4 z );

/*
 * Copy elements from a 3-D point into a 3-D vector
 */
static inline void vmathSoaV3MakeFromP3( VmathSoaVector3 *result, const VmathSoaPoint3 *pnt );

/*
 * Set all elements of a 3-D vector to the same scalar value
 */
static inline void vmathSoaV3MakeFromScalar( VmathSoaVector3 *result, vec_float4 scalar );

/*
 * Replicate an AoS 3-D vector
 */
static inline void vmathSoaV3MakeFromAos( VmathSoaVector3 *result, const VmathVector3 *vec );

/*
 * Insert four AoS 3-D vectors
 */
static inline void vmathSoaV3MakeFrom4Aos( VmathSoaVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1, const VmathVector3 *vec2, const VmathVector3 *vec3 );

/*
 * Extract four AoS 3-D vectors
 */
static inline void vmathSoaV3Get4Aos( const VmathSoaVector3 *vec, VmathVector3 *result0, VmathVector3 *result1, VmathVector3 *result2, VmathVector3 *result3 );

/*
 * Set the x element of a 3-D vector
 */
static inline void vmathSoaV3SetX( VmathSoaVector3 *result, vec_float4 x );

/*
 * Set the y element of a 3-D vector
 */
static inline void vmathSoaV3SetY( VmathSoaVector3 *result, vec_float4 y );

/*
 * Set the z element of a 3-D vector
 */
static inline void vmathSoaV3SetZ( VmathSoaVector3 *result, vec_float4 z );

/*
 * Get the x element of a 3-D vector
 */
static inline vec_float4 vmathSoaV3GetX( const VmathSoaVector3 *vec );

/*
 * Get the y element of a 3-D vector
 */
static inline vec_float4 vmathSoaV3GetY( const VmathSoaVector3 *vec );

/*
 * Get the z element of a 3-D vector
 */
static inline vec_float4 vmathSoaV3GetZ( const VmathSoaVector3 *vec );

/*
 * Set an x, y, or z element of a 3-D vector by index
 */
static inline void vmathSoaV3SetElem( VmathSoaVector3 *result, int idx, vec_float4 value );

/*
 * Get an x, y, or z element of a 3-D vector by index
 */
static inline vec_float4 vmathSoaV3GetElem( const VmathSoaVector3 *vec, int idx );

/*
 * Add two 3-D vectors
 */
static inline void vmathSoaV3Add( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 );

/*
 * Subtract a 3-D vector from another 3-D vector
 */
static inline void vmathSoaV3Sub( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 );

/*
 * Add a 3-D vector to a 3-D point
 */
static inline void vmathSoaV3AddP3( VmathSoaPoint3 *result, const VmathSoaVector3 *vec, const VmathSoaPoint3 *pnt );

/*
 * Multiply a 3-D vector by a scalar
 */
static inline void vmathSoaV3ScalarMul( VmathSoaVector3 *result, const VmathSoaVector3 *vec, vec_float4 scalar );

/*
 * Divide a 3-D vector by a scalar
 */
static inline void vmathSoaV3ScalarDiv( VmathSoaVector3 *result, const VmathSoaVector3 *vec, vec_float4 scalar );

/*
 * Negate all elements of a 3-D vector
 */
static inline void vmathSoaV3Neg( VmathSoaVector3 *result, const VmathSoaVector3 *vec );

/*
 * Construct x axis
 */
static inline void vmathSoaV3MakeXAxis( VmathSoaVector3 *result );

/*
 * Construct y axis
 */
static inline void vmathSoaV3MakeYAxis( VmathSoaVector3 *result );

/*
 * Construct z axis
 */
static inline void vmathSoaV3MakeZAxis( VmathSoaVector3 *result );

/*
 * Multiply two 3-D vectors per element
 */
static inline void vmathSoaV3MulPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 );

/*
 * Divide two 3-D vectors per element
 * NOTE: 
 * Floating-point behavior matches standard library function divf4.
 */
static inline void vmathSoaV3DivPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 );

/*
 * Compute the reciprocal of a 3-D vector per element
 * NOTE: 
 * Floating-point behavior matches standard library function recipf4.
 */
static inline void vmathSoaV3RecipPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec );

/*
 * Compute the absolute value of a 3-D vector per element
 */
static inline void vmathSoaV3AbsPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec );

/*
 * Copy sign from one 3-D vector to another, per element
 */
static inline void vmathSoaV3CopySignPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 );

/*
 * Maximum of two 3-D vectors per element
 */
static inline void vmathSoaV3MaxPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 );

/*
 * Minimum of two 3-D vectors per element
 */
static inline void vmathSoaV3MinPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 );

/*
 * Maximum element of a 3-D vector
 */
static inline vec_float4 vmathSoaV3MaxElem( const VmathSoaVector3 *vec );

/*
 * Minimum element of a 3-D vector
 */
static inline vec_float4 vmathSoaV3MinElem( const VmathSoaVector3 *vec );

/*
 * Compute the sum of all elements of a 3-D vector
 */
static inline vec_float4 vmathSoaV3Sum( const VmathSoaVector3 *vec );

/*
 * Compute the dot product of two 3-D vectors
 */
static inline vec_float4 vmathSoaV3Dot( const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 );

/*
 * Compute the square of the length of a 3-D vector
 */
static inline vec_float4 vmathSoaV3LengthSqr( const VmathSoaVector3 *vec );

/*
 * Compute the length of a 3-D vector
 */
static inline vec_float4 vmathSoaV3Length( const VmathSoaVector3 *vec );

/*
 * Normalize a 3-D vector
 * NOTE: 
 * The result is unpredictable when all elements of vec are at or near zero.
 */
static inline void vmathSoaV3Normalize( VmathSoaVector3 *result, const VmathSoaVector3 *vec );

/*
 * Compute cross product of two 3-D vectors
 */
static inline void vmathSoaV3Cross( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 );

/*
 * Outer product of two 3-D vectors
 */
static inline void vmathSoaV3Outer( VmathSoaMatrix3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 );

/*
 * Pre-multiply a row vector by a 3x3 matrix
 */
static inline void vmathSoaV3RowMul( VmathSoaVector3 *result, const VmathSoaVector3 *vec, const VmathSoaMatrix3 *mat );

/*
 * Cross-product matrix of a 3-D vector
 */
static inline void vmathSoaV3CrossMatrix( VmathSoaMatrix3 *result, const VmathSoaVector3 *vec );

/*
 * Create cross-product matrix and multiply
 * NOTE: 
 * Faster than separately creating a cross-product matrix and multiplying.
 */
static inline void vmathSoaV3CrossMatrixMul( VmathSoaMatrix3 *result, const VmathSoaVector3 *vec, const VmathSoaMatrix3 *mat );

/*
 * Linear interpolation between two 3-D vectors
 * NOTE: 
 * Does not clamp t between 0 and 1.
 */
static inline void vmathSoaV3Lerp( VmathSoaVector3 *result, vec_float4 t, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 );

/*
 * Spherical linear interpolation between two 3-D vectors
 * NOTE: 
 * The result is unpredictable if the vectors point in opposite directions.
 * Does not clamp t between 0 and 1.
 */
static inline void vmathSoaV3Slerp( VmathSoaVector3 *result, vec_float4 t, const VmathSoaVector3 *unitVec0, const VmathSoaVector3 *unitVec1 );

/*
 * Conditionally select between two 3-D vectors
 * NOTE: 
 * This function uses a conditional select instruction to avoid a branch.
 */
static inline void vmathSoaV3Select( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1, vec_uint4 select1 );

/*
 * Load four three-float 3-D vectors, stored in three quadwords
 */
static inline void vmathSoaV3LoadXYZArray( VmathSoaVector3 *vec, const vec_float4 *threeQuads );

/*
 * Store four slots of an SoA 3-D vector in three quadwords
 */
static inline void vmathSoaV3StoreXYZArray( const VmathSoaVector3 *vec, vec_float4 *threeQuads );

/*
 * Store eight slots of two SoA 3-D vectors as half-floats
 */
static inline void vmathSoaV3StoreHalfFloats( const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1, vec_ushort8 *threeQuads );

#ifdef _VECTORMATH_DEBUG

/*
 * Print a 3-D vector
 * NOTE: 
 * Function is only defined when _VECTORMATH_DEBUG is defined.
 */
static inline void vmathSoaV3Print( const VmathSoaVector3 *vec );

/*
 * Print a 3-D vector and an associated string identifier
 * NOTE: 
 * Function is only defined when _VECTORMATH_DEBUG is defined.
 */
static inline void vmathSoaV3Prints( const VmathSoaVector3 *vec, const char *name );

#endif

/*
 * Copy a 4-D vector
 */
static inline void vmathSoaV4Copy( VmathSoaVector4 *result, const VmathSoaVector4 *vec );

/*
 * Construct a 4-D vector from x, y, z, and w elements
 */
static inline void vmathSoaV4MakeFromElems( VmathSoaVector4 *result, vec_float4 x, vec_float4 y, vec_float4 z, vec_float4 w );

/*
 * Construct a 4-D vector from a 3-D vector and a scalar
 */
static inline void vmathSoaV4MakeFromV3Scalar( VmathSoaVector4 *result, const VmathSoaVector3 *xyz, vec_float4 w );

/*
 * Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0
 */
static inline void vmathSoaV4MakeFromV3( VmathSoaVector4 *result, const VmathSoaVector3 *vec );

/*
 * Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1
 */
static inline void vmathSoaV4MakeFromP3( VmathSoaVector4 *result, const VmathSoaPoint3 *pnt );

/*
 * Copy elements from a quaternion into a 4-D vector
 */
static inline void vmathSoaV4MakeFromQ( VmathSoaVector4 *result, const VmathSoaQuat *quat );

/*
 * Set all elements of a 4-D vector to the same scalar value
 */
static inline void vmathSoaV4MakeFromScalar( VmathSoaVector4 *result, vec_float4 scalar );

/*
 * Replicate an AoS 4-D vector
 */
static inline void vmathSoaV4MakeFromAos( VmathSoaVector4 *result, const VmathVector4 *vec );

/*
 * Insert four AoS 4-D vectors
 */
static inline void vmathSoaV4MakeFrom4Aos( VmathSoaVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1, const VmathVector4 *vec2, const VmathVector4 *vec3 );

/*
 * Extract four AoS 4-D vectors
 */
static inline void vmathSoaV4Get4Aos( const VmathSoaVector4 *vec, VmathVector4 *result0, VmathVector4 *result1, VmathVector4 *result2, VmathVector4 *result3 );

/*
 * Set the x, y, and z elements of a 4-D vector
 * NOTE: 
 * This function does not change the w element.
 */
static inline void vmathSoaV4SetXYZ( VmathSoaVector4 *result, const VmathSoaVector3 *vec );

/*
 * Get the x, y, and z elements of a 4-D vector
 */
static inline void vmathSoaV4GetXYZ( VmathSoaVector3 *result, const VmathSoaVector4 *vec );

/*
 * Set the x element of a 4-D vector
 */
static inline void vmathSoaV4SetX( VmathSoaVector4 *result, vec_float4 x );

/*
 * Set the y element of a 4-D vector
 */
static inline void vmathSoaV4SetY( VmathSoaVector4 *result, vec_float4 y );

/*
 * Set the z element of a 4-D vector
 */
static inline void vmathSoaV4SetZ( VmathSoaVector4 *result, vec_float4 z );

/*
 * Set the w element of a 4-D vector
 */
static inline void vmathSoaV4SetW( VmathSoaVector4 *result, vec_float4 w );

/*
 * Get the x element of a 4-D vector
 */
static inline vec_float4 vmathSoaV4GetX( const VmathSoaVector4 *vec );

/*
 * Get the y element of a 4-D vector
 */
static inline vec_float4 vmathSoaV4GetY( const VmathSoaVector4 *vec );

/*
 * Get the z element of a 4-D vector
 */
static inline vec_float4 vmathSoaV4GetZ( const VmathSoaVector4 *vec );

/*
 * Get the w element of a 4-D vector
 */
static inline vec_float4 vmathSoaV4GetW( const VmathSoaVector4 *vec );

/*
 * Set an x, y, z, or w element of a 4-D vector by index
 */
static inline void vmathSoaV4SetElem( VmathSoaVector4 *result, int idx, vec_float4 value );

/*
 * Get an x, y, z, or w element of a 4-D vector by index
 */
static inline vec_float4 vmathSoaV4GetElem( const VmathSoaVector4 *vec, int idx );

/*
 * Add two 4-D vectors
 */
static inline void vmathSoaV4Add( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 );

/*
 * Subtract a 4-D vector from another 4-D vector
 */
static inline void vmathSoaV4Sub( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 );

/*
 * Multiply a 4-D vector by a scalar
 */
static inline void vmathSoaV4ScalarMul( VmathSoaVector4 *result, const VmathSoaVector4 *vec, vec_float4 scalar );

/*
 * Divide a 4-D vector by a scalar
 */
static inline void vmathSoaV4ScalarDiv( VmathSoaVector4 *result, const VmathSoaVector4 *vec, vec_float4 scalar );

/*
 * Negate all elements of a 4-D vector
 */
static inline void vmathSoaV4Neg( VmathSoaVector4 *result, const VmathSoaVector4 *vec );

/*
 * Construct x axis
 */
static inline void vmathSoaV4MakeXAxis( VmathSoaVector4 *result );

/*
 * Construct y axis
 */
static inline void vmathSoaV4MakeYAxis( VmathSoaVector4 *result );

/*
 * Construct z axis
 */
static inline void vmathSoaV4MakeZAxis( VmathSoaVector4 *result );

/*
 * Construct w axis
 */
static inline void vmathSoaV4MakeWAxis( VmathSoaVector4 *result );

/*
 * Multiply two 4-D vectors per element
 */
static inline void vmathSoaV4MulPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 );

/*
 * Divide two 4-D vectors per element
 * NOTE: 
 * Floating-point behavior matches standard library function divf4.
 */
static inline void vmathSoaV4DivPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 );

/*
 * Compute the reciprocal of a 4-D vector per element
 * NOTE: 
 * Floating-point behavior matches standard library function recipf4.
 */
static inline void vmathSoaV4RecipPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec );

/*
 * Compute the absolute value of a 4-D vector per element
 */
static inline void vmathSoaV4AbsPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec );

/*
 * Copy sign from one 4-D vector to another, per element
 */
static inline void vmathSoaV4CopySignPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 );

/*
 * Maximum of two 4-D vectors per element
 */
static inline void vmathSoaV4MaxPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 );

/*
 * Minimum of two 4-D vectors per element
 */
static inline void vmathSoaV4MinPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 );

/*
 * Maximum element of a 4-D vector
 */
static inline vec_float4 vmathSoaV4MaxElem( const VmathSoaVector4 *vec );

/*
 * Minimum element of a 4-D vector
 */
static inline vec_float4 vmathSoaV4MinElem( const VmathSoaVector4 *vec );

/*
 * Compute the sum of all elements of a 4-D vector
 */
static inline vec_float4 vmathSoaV4Sum( const VmathSoaVector4 *vec );

/*
 * Compute the dot product of two 4-D vectors
 */
static inline vec_float4 vmathSoaV4Dot( const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 );

/*
 * Compute the square of the length of a 4-D vector
 */
static inline vec_float4 vmathSoaV4LengthSqr( const VmathSoaVector4 *vec );

/*
 * Compute the length of a 4-D vector
 */
static inline vec_float4 vmathSoaV4Length( const VmathSoaVector4 *vec );

/*
 * Normalize a 4-D vector
 * NOTE: 
 * The result is unpredictable when all elements of vec are at or near zero.
 */
static inline void vmathSoaV4Normalize( VmathSoaVector4 *result, const VmathSoaVector4 *vec );

/*
 * Outer product of two 4-D vectors
 */
static inline void vmathSoaV4Outer( VmathSoaMatrix4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 );

/*
 * Linear interpolation between two 4-D vectors
 * NOTE: 
 * Does not clamp t between 0 and 1.
 */
static inline void vmathSoaV4Lerp( VmathSoaVector4 *result, vec_float4 t, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 );

/*
 * Spherical linear interpolation between two 4-D vectors
 * NOTE: 
 * The result is unpredictable if the vectors point in opposite directions.
 * Does not clamp t between 0 and 1.
 */
static inline void vmathSoaV4Slerp( VmathSoaVector4 *result, vec_float4 t, const VmathSoaVector4 *unitVec0, const VmathSoaVector4 *unitVec1 );

/*
 * Conditionally select between two 4-D vectors
 * NOTE: 
 * This function uses a conditional select instruction to avoid a branch.
 */
static inline void vmathSoaV4Select( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1, vec_uint4 select1 );

/*
 * Store four slots of an SoA 4-D vector as half-floats
 */
static inline void vmathSoaV4StoreHalfFloats( const VmathSoaVector4 *vec, vec_ushort8 *twoQuads );

#ifdef _VECTORMATH_DEBUG

/*
 * Print a 4-D vector
 * NOTE: 
 * Function is only defined when _VECTORMATH_DEBUG is defined.
 */
static inline void vmathSoaV4Print( const VmathSoaVector4 *vec );

/*
 * Print a 4-D vector and an associated string identifier
 * NOTE: 
 * Function is only defined when _VECTORMATH_DEBUG is defined.
 */
static inline void vmathSoaV4Prints( const VmathSoaVector4 *vec, const char *name );

#endif

/*
 * Copy a 3-D point
 */
static inline void vmathSoaP3Copy( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt );

/*
 * Construct a 3-D point from x, y, and z elements
 */
static inline void vmathSoaP3MakeFromElems( VmathSoaPoint3 *result, vec_float4 x, vec_float4 y, vec_float4 z );

/*
 * Copy elements from a 3-D vector into a 3-D point
 */
static inline void vmathSoaP3MakeFromV3( VmathSoaPoint3 *result, const VmathSoaVector3 *vec );

/*
 * Set all elements of a 3-D point to the same scalar value
 */
static inline void vmathSoaP3MakeFromScalar( VmathSoaPoint3 *result, vec_float4 scalar );

/*
 * Replicate an AoS 3-D point
 */
static inline void vmathSoaP3MakeFromAos( VmathSoaPoint3 *result, const VmathPoint3 *pnt );

/*
 * Insert four AoS 3-D points
 */
static inline void vmathSoaP3MakeFrom4Aos( VmathSoaPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1, const VmathPoint3 *pnt2, const VmathPoint3 *pnt3 );

/*
 * Extract four AoS 3-D points
 */
static inline void vmathSoaP3Get4Aos( const VmathSoaPoint3 *pnt, VmathPoint3 *result0, VmathPoint3 *result1, VmathPoint3 *result2, VmathPoint3 *result3 );

/*
 * Set the x element of a 3-D point
 */
static inline void vmathSoaP3SetX( VmathSoaPoint3 *result, vec_float4 x );

/*
 * Set the y element of a 3-D point
 */
static inline void vmathSoaP3SetY( VmathSoaPoint3 *result, vec_float4 y );

/*
 * Set the z element of a 3-D point
 */
static inline void vmathSoaP3SetZ( VmathSoaPoint3 *result, vec_float4 z );

/*
 * Get the x element of a 3-D point
 */
static inline vec_float4 vmathSoaP3GetX( const VmathSoaPoint3 *pnt );

/*
 * Get the y element of a 3-D point
 */
static inline vec_float4 vmathSoaP3GetY( const VmathSoaPoint3 *pnt );

/*
 * Get the z element of a 3-D point
 */
static inline vec_float4 vmathSoaP3GetZ( const VmathSoaPoint3 *pnt );

/*
 * Set an x, y, or z element of a 3-D point by index
 */
static inline void vmathSoaP3SetElem( VmathSoaPoint3 *result, int idx, vec_float4 value );

/*
 * Get an x, y, or z element of a 3-D point by index
 */
static inline vec_float4 vmathSoaP3GetElem( const VmathSoaPoint3 *pnt, int idx );

/*
 * Subtract a 3-D point from another 3-D point
 */
static inline void vmathSoaP3Sub( VmathSoaVector3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 );

/*
 * Add a 3-D point to a 3-D vector
 */
static inline void vmathSoaP3AddV3( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt, const VmathSoaVector3 *vec );

/*
 * Subtract a 3-D vector from a 3-D point
 */
static inline void vmathSoaP3SubV3( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt, const VmathSoaVector3 *vec );

/*
 * Multiply two 3-D points per element
 */
static inline void vmathSoaP3MulPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 );

/*
 * Divide two 3-D points per element
 * NOTE: 
 * Floating-point behavior matches standard library function divf4.
 */
static inline void vmathSoaP3DivPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 );

/*
 * Compute the reciprocal of a 3-D point per element
 * NOTE: 
 * Floating-point behavior matches standard library function recipf4.
 */
static inline void vmathSoaP3RecipPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt );

/*
 * Compute the absolute value of a 3-D point per element
 */
static inline void vmathSoaP3AbsPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt );

/*
 * Copy sign from one 3-D point to another, per element
 */
static inline void vmathSoaP3CopySignPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 );

/*
 * Maximum of two 3-D points per element
 */
static inline void vmathSoaP3MaxPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 );

/*
 * Minimum of two 3-D points per element
 */
static inline void vmathSoaP3MinPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 );

/*
 * Maximum element of a 3-D point
 */
static inline vec_float4 vmathSoaP3MaxElem( const VmathSoaPoint3 *pnt );

/*
 * Minimum element of a 3-D point
 */
static inline vec_float4 vmathSoaP3MinElem( const VmathSoaPoint3 *pnt );

/*
 * Compute the sum of all elements of a 3-D point
 */
static inline vec_float4 vmathSoaP3Sum( const VmathSoaPoint3 *pnt );

/*
 * Apply uniform scale to a 3-D point
 */
static inline void vmathSoaP3Scale( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt, vec_float4 scaleVal );

/*
 * Apply non-uniform scale to a 3-D point
 */
static inline void vmathSoaP3NonUniformScale( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt, const VmathSoaVector3 *scaleVec );

/*
 * Scalar projection of a 3-D point on a unit-length 3-D vector
 */
static inline vec_float4 vmathSoaP3Projection( const VmathSoaPoint3 *pnt, const VmathSoaVector3 *unitVec );

/*
 * Compute the square of the distance of a 3-D point from the coordinate-system origin
 */
static inline vec_float4 vmathSoaP3DistSqrFromOrigin( const VmathSoaPoint3 *pnt );

/*
 * Compute the distance of a 3-D point from the coordinate-system origin
 */
static inline vec_float4 vmathSoaP3DistFromOrigin( const VmathSoaPoint3 *pnt );

/*
 * Compute the square of the distance between two 3-D points
 */
static inline vec_float4 vmathSoaP3DistSqr( const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 );

/*
 * Compute the distance between two 3-D points
 */
static inline vec_float4 vmathSoaP3Dist( const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 );

/*
 * Linear interpolation between two 3-D points
 * NOTE: 
 * Does not clamp t between 0 and 1.
 */
static inline void vmathSoaP3Lerp( VmathSoaPoint3 *result, vec_float4 t, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 );

/*
 * Conditionally select between two 3-D points
 * NOTE: 
 * This function uses a conditional select instruction to avoid a branch.
 */
static inline void vmathSoaP3Select( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1, vec_uint4 select1 );

/*
 * Load four three-float 3-D points, stored in three quadwords
 */
static inline void vmathSoaP3LoadXYZArray( VmathSoaPoint3 *pnt, const vec_float4 *threeQuads );

/*
 * Store four slots of an SoA 3-D point in three quadwords
 */
static inline void vmathSoaP3StoreXYZArray( const VmathSoaPoint3 *pnt, vec_float4 *threeQuads );

/*
 * Store eight slots of two SoA 3-D points as half-floats
 */
static inline void vmathSoaP3StoreHalfFloats( const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1, vec_ushort8 *threeQuads );

#ifdef _VECTORMATH_DEBUG

/*
 * Print a 3-D point
 * NOTE: 
 * Function is only defined when _VECTORMATH_DEBUG is defined.
 */
static inline void vmathSoaP3Print( const VmathSoaPoint3 *pnt );

/*
 * Print a 3-D point and an associated string identifier
 * NOTE: 
 * Function is only defined when _VECTORMATH_DEBUG is defined.
 */
static inline void vmathSoaP3Prints( const VmathSoaPoint3 *pnt, const char *name );

#endif

/*
 * Copy a quaternion
 */
static inline void vmathSoaQCopy( VmathSoaQuat *result, const VmathSoaQuat *quat );

/*
 * Construct a quaternion from x, y, z, and w elements
 */
static inline void vmathSoaQMakeFromElems( VmathSoaQuat *result, vec_float4 x, vec_float4 y, vec_float4 z, vec_float4 w );

/*
 * Construct a quaternion from a 3-D vector and a scalar
 */
static inline void vmathSoaQMakeFromV3Scalar( VmathSoaQuat *result, const VmathSoaVector3 *xyz, vec_float4 w );

/*
 * Copy elements from a 4-D vector into a quaternion
 */
static inline void vmathSoaQMakeFromV4( VmathSoaQuat *result, const VmathSoaVector4 *vec );

/*
 * Convert a rotation matrix to a unit-length quaternion
 */
static inline void vmathSoaQMakeFromM3( VmathSoaQuat *result, const VmathSoaMatrix3 *rotMat );

/*
 * Set all elements of a quaternion to the same scalar value
 */
static inline void vmathSoaQMakeFromScalar( VmathSoaQuat *result, vec_float4 scalar );

/*
 * Replicate an AoS quaternion
 */
static inline void vmathSoaQMakeFromAos( VmathSoaQuat *result, const VmathQuat *quat );

/*
 * Insert four AoS quaternions
 */
static inline void vmathSoaQMakeFrom4Aos( VmathSoaQuat *result, const VmathQuat *quat0, const VmathQuat *quat1, const VmathQuat *quat2, const VmathQuat *quat3 );

/*
 * Extract four AoS quaternions
 */
static inline void vmathSoaQGet4Aos( const VmathSoaQuat *quat, VmathQuat *result0, VmathQuat *result1, VmathQuat *result2, VmathQuat *result3 );

/*
 * Set the x, y, and z elements of a quaternion
 * NOTE: 
 * This function does not change the w element.
 */
static inline void vmathSoaQSetXYZ( VmathSoaQuat *result, const VmathSoaVector3 *vec );

/*
 * Get the x, y, and z elements of a quaternion
 */
static inline void vmathSoaQGetXYZ( VmathSoaVector3 *result, const VmathSoaQuat *quat );

/*
 * Set the x element of a quaternion
 */
static inline void vmathSoaQSetX( VmathSoaQuat *result, vec_float4 x );

/*
 * Set the y element of a quaternion
 */
static inline void vmathSoaQSetY( VmathSoaQuat *result, vec_float4 y );

/*
 * Set the z element of a quaternion
 */
static inline void vmathSoaQSetZ( VmathSoaQuat *result, vec_float4 z );

/*
 * Set the w element of a quaternion
 */
static inline void vmathSoaQSetW( VmathSoaQuat *result, vec_float4 w );

/*
 * Get the x element of a quaternion
 */
static inline vec_float4 vmathSoaQGetX( const VmathSoaQuat *quat );

/*
 * Get the y element of a quaternion
 */
static inline vec_float4 vmathSoaQGetY( const VmathSoaQuat *quat );

/*
 * Get the z element of a quaternion
 */
static inline vec_float4 vmathSoaQGetZ( const VmathSoaQuat *quat );

/*
 * Get the w element of a quaternion
 */
static inline vec_float4 vmathSoaQGetW( const VmathSoaQuat *quat );

/*
 * Set an x, y, z, or w element of a quaternion by index
 */
static inline void vmathSoaQSetElem( VmathSoaQuat *result, int idx, vec_float4 value );

/*
 * Get an x, y, z, or w element of a quaternion by index
 */
static inline vec_float4 vmathSoaQGetElem( const VmathSoaQuat *quat, int idx );

/*
 * Add two quaternions
 */
static inline void vmathSoaQAdd( VmathSoaQuat *result, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 );

/*
 * Subtract a quaternion from another quaternion
 */
static inline void vmathSoaQSub( VmathSoaQuat *result, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 );

/*
 * Multiply two quaternions
 */
static inline void vmathSoaQMul( VmathSoaQuat *result, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 );

/*
 * Multiply a quaternion by a scalar
 */
static inline void vmathSoaQScalarMul( VmathSoaQuat *result, const VmathSoaQuat *quat, vec_float4 scalar );

/*
 * Divide a quaternion by a scalar
 */
static inline void vmathSoaQScalarDiv( VmathSoaQuat *result, const VmathSoaQuat *quat, vec_float4 scalar );

/*
 * Negate all elements of a quaternion
 */
static inline void vmathSoaQNeg( VmathSoaQuat *result, const VmathSoaQuat *quat );

/*
 * Construct an identity quaternion
 */
static inline void vmathSoaQMakeIdentity( VmathSoaQuat *result );

/*
 * Construct a quaternion to rotate between two unit-length 3-D vectors
 * NOTE: 
 * The result is unpredictable if unitVec0 and unitVec1 point in opposite directions.
 */
static inline void vmathSoaQMakeRotationArc( VmathSoaQuat *result, const VmathSoaVector3 *unitVec0, const VmathSoaVector3 *unitVec1 );

/*
 * Construct a quaternion to rotate around a unit-length 3-D vector
 */
static inline void vmathSoaQMakeRotationAxis( VmathSoaQuat *result, vec_float4 radians, const VmathSoaVector3 *unitVec );

/*
 * Construct a quaternion to rotate around the x axis
 */
static inline void vmathSoaQMakeRotationX( VmathSoaQuat *result, vec_float4 radians );

/*
 * Construct a quaternion to rotate around the y axis
 */
static inline void vmathSoaQMakeRotationY( VmathSoaQuat *result, vec_float4 radians );

/*
 * Construct a quaternion to rotate around the z axis
 */
static inline void vmathSoaQMakeRotationZ( VmathSoaQuat *result, vec_float4 radians );

/*
 * Compute the conjugate of a quaternion
 */
static inline void vmathSoaQConj( VmathSoaQuat *result, const VmathSoaQuat *quat );

/*
 * Use a unit-length quaternion to rotate a 3-D vector
 */
static inline void vmathSoaQRotate( VmathSoaVector3 *result, const VmathSoaQuat *unitQuat, const VmathSoaVector3 *vec );

/*
 * Compute the dot product of two quaternions
 */
static inline vec_float4 vmathSoaQDot( const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 );

/*
 * Compute the norm of a quaternion
 */
static inline vec_float4 vmathSoaQNorm( const VmathSoaQuat *quat );

/*
 * Compute the length of a quaternion
 */
static inline vec_float4 vmathSoaQLength( const VmathSoaQuat *quat );

/*
 * Normalize a quaternion
 * NOTE: 
 * The result is unpredictable when all elements of quat are at or near zero.
 */
static inline void vmathSoaQNormalize( VmathSoaQuat *result, const VmathSoaQuat *quat );

/*
 * Linear interpolation between two quaternions
 * NOTE: 
 * Does not clamp t between 0 and 1.
 */
static inline void vmathSoaQLerp( VmathSoaQuat *result, vec_float4 t, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 );

/*
 * Spherical linear interpolation between two quaternions
 * NOTE: 
 * Interpolates along the shortest path between orientations.
 * Does not clamp t between 0 and 1.
 */
static inline void vmathSoaQSlerp( VmathSoaQuat *result, vec_float4 t, const VmathSoaQuat *unitQuat0, const VmathSoaQuat *unitQuat1 );

/*
 * Spherical quadrangle interpolation
 */
static inline void vmathSoaQSquad( VmathSoaQuat *result, vec_float4 t, const VmathSoaQuat *unitQuat0, const VmathSoaQuat *unitQuat1, const VmathSoaQuat *unitQuat2, const VmathSoaQuat *unitQuat3 );

/*
 * Conditionally select between two quaternions
 * NOTE: 
 * This function uses a conditional select instruction to avoid a branch.
 */
static inline void vmathSoaQSelect( VmathSoaQuat *result, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1, vec_uint4 select1 );

#ifdef _VECTORMATH_DEBUG

/*
 * Print a quaternion
 * NOTE: 
 * Function is only defined when _VECTORMATH_DEBUG is defined.
 */
static inline void vmathSoaQPrint( const VmathSoaQuat *quat );

/*
 * Print a quaternion and an associated string identifier
 * NOTE: 
 * Function is only defined when _VECTORMATH_DEBUG is defined.
 */
static inline void vmathSoaQPrints( const VmathSoaQuat *quat, const char *name );

#endif

/*
 * Copy a 3x3 matrix
 */
static inline void vmathSoaM3Copy( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat );

/*
 * Construct a 3x3 matrix containing the specified columns
 */
static inline void vmathSoaM3MakeFromCols( VmathSoaMatrix3 *result, const VmathSoaVector3 *col0, const VmathSoaVector3 *col1, const VmathSoaVector3 *col2 );

/*
 * Construct a 3x3 rotation matrix from a unit-length quaternion
 */
static inline void vmathSoaM3MakeFromQ( VmathSoaMatrix3 *result, const VmathSoaQuat *unitQuat );

/*
 * Set all elements of a 3x3 matrix to the same scalar value
 */
static inline void vmathSoaM3MakeFromScalar( VmathSoaMatrix3 *result, vec_float4 scalar );

/*
 * Replicate an AoS 3x3 matrix
 */
static inline void vmathSoaM3MakeFromAos( VmathSoaMatrix3 *result, const VmathMatrix3 *mat );

/*
 * Insert four AoS 3x3 matrices
 */
static inline void vmathSoaM3MakeFrom4Aos( VmathSoaMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1, const VmathMatrix3 *mat2, const VmathMatrix3 *mat3 );

/*
 * Extract four AoS 3x3 matrices
 */
static inline void vmathSoaM3Get4Aos( const VmathSoaMatrix3 *mat, VmathMatrix3 *result0, VmathMatrix3 *result1, VmathMatrix3 *result2, VmathMatrix3 *result3 );

/*
 * Set column 0 of a 3x3 matrix
 */
static inline void vmathSoaM3SetCol0( VmathSoaMatrix3 *result, const VmathSoaVector3 *col0 );

/*
 * Set column 1 of a 3x3 matrix
 */
static inline void vmathSoaM3SetCol1( VmathSoaMatrix3 *result, const VmathSoaVector3 *col1 );

/*
 * Set column 2 of a 3x3 matrix
 */
static inline void vmathSoaM3SetCol2( VmathSoaMatrix3 *result, const VmathSoaVector3 *col2 );

/*
 * Get column 0 of a 3x3 matrix
 */
static inline void vmathSoaM3GetCol0( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat );

/*
 * Get column 1 of a 3x3 matrix
 */
static inline void vmathSoaM3GetCol1( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat );

/*
 * Get column 2 of a 3x3 matrix
 */
static inline void vmathSoaM3GetCol2( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat );

/*
 * Set the column of a 3x3 matrix referred to by the specified index
 */
static inline void vmathSoaM3SetCol( VmathSoaMatrix3 *result, int col, const VmathSoaVector3 *vec );

/*
 * Set the row of a 3x3 matrix referred to by the specified index
 */
static inline void vmathSoaM3SetRow( VmathSoaMatrix3 *result, int row, const VmathSoaVector3 *vec );

/*
 * Get the column of a 3x3 matrix referred to by the specified index
 */
static inline void vmathSoaM3GetCol( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat, int col );

/*
 * Get the row of a 3x3 matrix referred to by the specified index
 */
static inline void vmathSoaM3GetRow( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat, int row );

/*
 * Set the element of a 3x3 matrix referred to by column and row indices
 */
static inline void vmathSoaM3SetElem( VmathSoaMatrix3 *result, int col, int row, vec_float4 val );

/*
 * Get the element of a 3x3 matrix referred to by column and row indices
 */
static inline vec_float4 vmathSoaM3GetElem( const VmathSoaMatrix3 *mat, int col, int row );

/*
 * Add two 3x3 matrices
 */
static inline void vmathSoaM3Add( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1 );

/*
 * Subtract a 3x3 matrix from another 3x3 matrix
 */
static inline void vmathSoaM3Sub( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1 );

/*
 * Negate all elements of a 3x3 matrix
 */
static inline void vmathSoaM3Neg( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat );

/*
 * Multiply a 3x3 matrix by a scalar
 */
static inline void vmathSoaM3ScalarMul( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat, vec_float4 scalar );

/*
 * Multiply a 3x3 matrix by a 3-D vector
 */
static inline void vmathSoaM3MulV3( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat, const VmathSoaVector3 *vec );

/*
 * Multiply two 3x3 matrices
 */
static inline void vmathSoaM3Mul( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1 );

/*
 * Construct an identity 3x3 matrix
 */
static inline void vmathSoaM3MakeIdentity( VmathSoaMatrix3 *result );

/*
 * Construct a 3x3 matrix to rotate around the x axis
 */
static inline void vmathSoaM3MakeRotationX( VmathSoaMatrix3 *result, vec_float4 radians );

/*
 * Construct a 3x3 matrix to rotate around the y axis
 */
static inline void vmathSoaM3MakeRotationY( VmathSoaMatrix3 *result, vec_float4 radians );

/*
 * Construct a 3x3 matrix to rotate around the z axis
 */
static inline void vmathSoaM3MakeRotationZ( VmathSoaMatrix3 *result, vec_float4 radians );

/*
 * Construct a 3x3 matrix to rotate around the x, y, and z axes
 */
static inline void vmathSoaM3MakeRotationZYX( VmathSoaMatrix3 *result, const VmathSoaVector3 *radiansXYZ );

/*
 * Construct a 3x3 matrix to rotate around a unit-length 3-D vector
 */
static inline void vmathSoaM3MakeRotationAxis( VmathSoaMatrix3 *result, vec_float4 radians, const VmathSoaVector3 *unitVec );

/*
 * Construct a rotation matrix from a unit-length quaternion
 */
static inline void vmathSoaM3MakeRotationQ( VmathSoaMatrix3 *result, const VmathSoaQuat *unitQuat );

/*
 * Construct a 3x3 matrix to perform scaling
 */
static inline void vmathSoaM3MakeScale( VmathSoaMatrix3 *result, const VmathSoaVector3 *scaleVec );

/*
 * Append (post-multiply) a scale transformation to a 3x3 matrix
 * NOTE: 
 * Faster than creating and multiplying a scale transformation matrix.
 */
static inline void vmathSoaM3AppendScale( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat, const VmathSoaVector3 *scaleVec );

/*
 * Prepend (pre-multiply) a scale transformation to a 3x3 matrix
 * NOTE: 
 * Faster than creating and multiplying a scale transformation matrix.
 */
static inline void vmathSoaM3PrependScale( VmathSoaMatrix3 *result, const VmathSoaVector3 *scaleVec, const VmathSoaMatrix3 *mat );

/*
 * Multiply two 3x3 matrices per element
 */
static inline void vmathSoaM3MulPerElem( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1 );

/*
 * Compute the absolute value of a 3x3 matrix per element
 */
static inline void vmathSoaM3AbsPerElem( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat );

/*
 * Transpose of a 3x3 matrix
 */
static inline void vmathSoaM3Transpose( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat );

/*
 * Compute the inverse of a 3x3 matrix
 * NOTE: 
 * Result is unpredictable when the determinant of mat is equal to or near 0.
 */
static inline void vmathSoaM3Inverse( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat );

/*
 * Determinant of a 3x3 matrix
 */
static inline vec_float4 vmathSoaM3Determinant( const VmathSoaMatrix3 *mat );

/*
 * Conditionally select between two 3x3 matrices
 * NOTE: 
 * This function uses a conditional select instruction to avoid a branch.
 */
static inline void vmathSoaM3Select( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1, vec_uint4 select1 );

#ifdef _VECTORMATH_DEBUG

/*
 * Print a 3x3 matrix
 * NOTE: 
 * Function is only defined when _VECTORMATH_DEBUG is defined.
 */
static inline void vmathSoaM3Print( const VmathSoaMatrix3 *mat );

/*
 * Print a 3x3 matrix and an associated string identifier
 * NOTE: 
 * Function is only defined when _VECTORMATH_DEBUG is defined.
 */
static inline void vmathSoaM3Prints( const VmathSoaMatrix3 *mat, const char *name );

#endif

/*
 * Copy a 4x4 matrix
 */
static inline void vmathSoaM4Copy( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat );

/*
 * Construct a 4x4 matrix containing the specified columns
 */
static inline void vmathSoaM4MakeFromCols( VmathSoaMatrix4 *result, const VmathSoaVector4 *col0, const VmathSoaVector4 *col1, const VmathSoaVector4 *col2, const VmathSoaVector4 *col3 );

/*
 * Construct a 4x4 matrix from a 3x4 transformation matrix
 */
static inline void vmathSoaM4MakeFromT3( VmathSoaMatrix4 *result, const VmathSoaTransform3 *mat );

/*
 * Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector
 */
static inline void vmathSoaM4MakeFromM3V3( VmathSoaMatrix4 *result, const VmathSoaMatrix3 *mat, const VmathSoaVector3 *translateVec );

/*
 * Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector
 */
static inline void vmathSoaM4MakeFromQV3( VmathSoaMatrix4 *result, const VmathSoaQuat *unitQuat, const VmathSoaVector3 *translateVec );

/*
 * Set all elements of a 4x4 matrix to the same scalar value
 */
static inline void vmathSoaM4MakeFromScalar( VmathSoaMatrix4 *result, vec_float4 scalar );

/*
 * Replicate an AoS 4x4 matrix
 */
static inline void vmathSoaM4MakeFromAos( VmathSoaMatrix4 *result, const VmathMatrix4 *mat );

/*
 * Insert four AoS 4x4 matrices
 */
static inline void vmathSoaM4MakeFrom4Aos( VmathSoaMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1, const VmathMatrix4 *mat2, const VmathMatrix4 *mat3 );

/*
 * Extract four AoS 4x4 matrices
 */
static inline void vmathSoaM4Get4Aos( const VmathSoaMatrix4 *mat, VmathMatrix4 *result0, VmathMatrix4 *result1, VmathMatrix4 *result2, VmathMatrix4 *result3 );

/*
 * Set the upper-left 3x3 submatrix
 * NOTE: 
 * This function does not change the bottom row elements.
 */
static inline void vmathSoaM4SetUpper3x3( VmathSoaMatrix4 *result, const VmathSoaMatrix3 *mat3 );

/*
 * Get the upper-left 3x3 submatrix of a 4x4 matrix
 */
static inline void vmathSoaM4GetUpper3x3( VmathSoaMatrix3 *result, const VmathSoaMatrix4 *mat );

/*
 * Set translation component
 * NOTE: 
 * This function does not change the bottom row elements.
 */
static inline void vmathSoaM4SetTranslation( VmathSoaMatrix4 *result, const VmathSoaVector3 *translateVec );

/*
 * Get the translation component of a 4x4 matrix
 */
static inline void vmathSoaM4GetTranslation( VmathSoaVector3 *result, const VmathSoaMatrix4 *mat );

/*
 * Set column 0 of a 4x4 matrix
 */
static inline void vmathSoaM4SetCol0( VmathSoaMatrix4 *result, const VmathSoaVector4 *col0 );

/*
 * Set column 1 of a 4x4 matrix
 */
static inline void vmathSoaM4SetCol1( VmathSoaMatrix4 *result, const VmathSoaVector4 *col1 );

/*
 * Set column 2 of a 4x4 matrix
 */
static inline void vmathSoaM4SetCol2( VmathSoaMatrix4 *result, const VmathSoaVector4 *col2 );

/*
 * Set column 3 of a 4x4 matrix
 */
static inline void vmathSoaM4SetCol3( VmathSoaMatrix4 *result, const VmathSoaVector4 *col3 );

/*
 * Get column 0 of a 4x4 matrix
 */
static inline void vmathSoaM4GetCol0( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat );

/*
 * Get column 1 of a 4x4 matrix
 */
static inline void vmathSoaM4GetCol1( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat );

/*
 * Get column 2 of a 4x4 matrix
 */
static inline void vmathSoaM4GetCol2( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat );

/*
 * Get column 3 of a 4x4 matrix
 */
static inline void vmathSoaM4GetCol3( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat );

/*
 * Set the column of a 4x4 matrix referred to by the specified index
 */
static inline void vmathSoaM4SetCol( VmathSoaMatrix4 *result, int col, const VmathSoaVector4 *vec );

/*
 * Set the row of a 4x4 matrix referred to by the specified index
 */
static inline void vmathSoaM4SetRow( VmathSoaMatrix4 *result, int row, const VmathSoaVector4 *vec );

/*
 * Get the column of a 4x4 matrix referred to by the specified index
 */
static inline void vmathSoaM4GetCol( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, int col );

/*
 * Get the row of a 4x4 matrix referred to by the specified index
 */
static inline void vmathSoaM4GetRow( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, int row );

/*
 * Set the element of a 4x4 matrix referred to by column and row indices
 */
static inline void vmathSoaM4SetElem( VmathSoaMatrix4 *result, int col, int row, vec_float4 val );

/*
 * Get the element of a 4x4 matrix referred to by column and row indices
 */
static inline vec_float4 vmathSoaM4GetElem( const VmathSoaMatrix4 *mat, int col, int row );

/*
 * Add two 4x4 matrices
 */
static inline void vmathSoaM4Add( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1 );

/*
 * Subtract a 4x4 matrix from another 4x4 matrix
 */
static inline void vmathSoaM4Sub( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1 );

/*
 * Negate all elements of a 4x4 matrix
 */
static inline void vmathSoaM4Neg( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat );

/*
 * Multiply a 4x4 matrix by a scalar
 */
static inline void vmathSoaM4ScalarMul( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat, vec_float4 scalar );

/*
 * Multiply a 4x4 matrix by a 4-D vector
 */
static inline void vmathSoaM4MulV4( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, const VmathSoaVector4 *vec );

/*
 * Multiply a 4x4 matrix by a 3-D vector
 */
static inline void vmathSoaM4MulV3( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, const VmathSoaVector3 *vec );

/*
 * Multiply a 4x4 matrix by a 3-D point
 */
static inline void vmathSoaM4MulP3( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, const VmathSoaPoint3 *pnt );

/*
 * Multiply two 4x4 matrices
 */
static inline void vmathSoaM4Mul( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1 );

/*
 * Multiply a 4x4 matrix by a 3x4 transformation matrix
 */
static inline void vmathSoaM4MulT3( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat, const VmathSoaTransform3 *tfrm );

/*
 * Construct an identity 4x4 matrix
 */
static inline void vmathSoaM4MakeIdentity( VmathSoaMatrix4 *result );

/*
 * Construct a 4x4 matrix to rotate around the x axis
 */
static inline void vmathSoaM4MakeRotationX( VmathSoaMatrix4 *result, vec_float4 radians );

/*
 * Construct a 4x4 matrix to rotate around the y axis
 */
static inline void vmathSoaM4MakeRotationY( VmathSoaMatrix4 *result, vec_float4 radians );

/*
 * Construct a 4x4 matrix to rotate around the z axis
 */
static inline void vmathSoaM4MakeRotationZ( VmathSoaMatrix4 *result, vec_float4 radians );

/*
 * Construct a 4x4 matrix to rotate around the x, y, and z axes
 */
static inline void vmathSoaM4MakeRotationZYX( VmathSoaMatrix4 *result, const VmathSoaVector3 *radiansXYZ );

/*
 * Construct a 4x4 matrix to rotate around a unit-length 3-D vector
 */
static inline void vmathSoaM4MakeRotationAxis( VmathSoaMatrix4 *result, vec_float4 radians, const VmathSoaVector3 *unitVec );

/*
 * Construct a rotation matrix from a unit-length quaternion
 */
static inline void vmathSoaM4MakeRotationQ( VmathSoaMatrix4 *result, const VmathSoaQuat *unitQuat );

/*
 * Construct a 4x4 matrix to perform scaling
 */
static inline void vmathSoaM4MakeScale( VmathSoaMatrix4 *result, const VmathSoaVector3 *scaleVec );

/*
 * Construct a 4x4 matrix to perform translation
 */
static inline void vmathSoaM4MakeTranslation( VmathSoaMatrix4 *result, const VmathSoaVector3 *translateVec );

/*
 * Construct viewing matrix based on eye, position looked at, and up direction
 */
static inline void vmathSoaM4MakeLookAt( VmathSoaMatrix4 *result, const VmathSoaPoint3 *eyePos, const VmathSoaPoint3 *lookAtPos, const VmathSoaVector3 *upVec );

/*
 * Construct a perspective projection matrix
 */
static inline void vmathSoaM4MakePerspective( VmathSoaMatrix4 *result, vec_float4 fovyRadians, vec_float4 aspect, vec_float4 zNear, vec_float4 zFar );

/*
 * Construct a perspective projection matrix based on frustum
 */
static inline void vmathSoaM4MakeFrustum( VmathSoaMatrix4 *result, vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar );

/*
 * Construct an orthographic projection matrix
 */
static inline void vmathSoaM4MakeOrthographic( VmathSoaMatrix4 *result, vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar );

/*
 * Append (post-multiply) a scale transformation to a 4x4 matrix
 * NOTE: 
 * Faster than creating and multiplying a scale transformation matrix.
 */
static inline void vmathSoaM4AppendScale( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat, const VmathSoaVector3 *scaleVec );

/*
 * Prepend (pre-multiply) a scale transformation to a 4x4 matrix
 * NOTE: 
 * Faster than creating and multiplying a scale transformation matrix.
 */
static inline void vmathSoaM4PrependScale( VmathSoaMatrix4 *result, const VmathSoaVector3 *scaleVec, const VmathSoaMatrix4 *mat );

/*
 * Multiply two 4x4 matrices per element
 */
static inline void vmathSoaM4MulPerElem( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1 );

/*
 * Compute the absolute value of a 4x4 matrix per element
 */
static inline void vmathSoaM4AbsPerElem( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat );

/*
 * Transpose of a 4x4 matrix
 */
static inline void vmathSoaM4Transpose( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat );

/*
 * Compute the inverse of a 4x4 matrix
 * NOTE: 
 * Result is unpredictable when the determinant of mat is equal to or near 0.
 */
static inline void vmathSoaM4Inverse( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat );

/*
 * Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix
 * NOTE: 
 * This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions.  The result is unpredictable when the determinant of mat is equal to or near 0.
 */
static inline void vmathSoaM4AffineInverse( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat );

/*
 * Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix
 * NOTE: 
 * This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions.
 */
static inline void vmathSoaM4OrthoInverse( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat );

/*
 * Determinant of a 4x4 matrix
 */
static inline vec_float4 vmathSoaM4Determinant( const VmathSoaMatrix4 *mat );

/*
 * Conditionally select between two 4x4 matrices
 * NOTE: 
 * This function uses a conditional select instruction to avoid a branch.
 */
static inline void vmathSoaM4Select( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1, vec_uint4 select1 );

#ifdef _VECTORMATH_DEBUG

/*
 * Print a 4x4 matrix
 * NOTE: 
 * Function is only defined when _VECTORMATH_DEBUG is defined.
 */
static inline void vmathSoaM4Print( const VmathSoaMatrix4 *mat );

/*
 * Print a 4x4 matrix and an associated string identifier
 * NOTE: 
 * Function is only defined when _VECTORMATH_DEBUG is defined.
 */
static inline void vmathSoaM4Prints( const VmathSoaMatrix4 *mat, const char *name );

#endif

/*
 * Copy a 3x4 transformation matrix
 */
static inline void vmathSoaT3Copy( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm );

/*
 * Construct a 3x4 transformation matrix containing the specified columns
 */
static inline void vmathSoaT3MakeFromCols( VmathSoaTransform3 *result, const VmathSoaVector3 *col0, const VmathSoaVector3 *col1, const VmathSoaVector3 *col2, const VmathSoaVector3 *col3 );

/*
 * Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector
 */
static inline void vmathSoaT3MakeFromM3V3( VmathSoaTransform3 *result, const VmathSoaMatrix3 *tfrm, const VmathSoaVector3 *translateVec );

/*
 * Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector
 */
static inline void vmathSoaT3MakeFromQV3( VmathSoaTransform3 *result, const VmathSoaQuat *unitQuat, const VmathSoaVector3 *translateVec );

/*
 * Set all elements of a 3x4 transformation matrix to the same scalar value
 */
static inline void vmathSoaT3MakeFromScalar( VmathSoaTransform3 *result, vec_float4 scalar );

/*
 * Replicate an AoS 3x4 transformation matrix
 */
static inline void vmathSoaT3MakeFromAos( VmathSoaTransform3 *result, const VmathTransform3 *tfrm );

/*
 * Insert four AoS 3x4 transformation matrices
 */
static inline void vmathSoaT3MakeFrom4Aos( VmathSoaTransform3 *result, const VmathTransform3 *tfrm0, const VmathTransform3 *tfrm1, const VmathTransform3 *tfrm2, const VmathTransform3 *tfrm3 );

/*
 * Extract four AoS 3x4 transformation matrices
 */
static inline void vmathSoaT3Get4Aos( const VmathSoaTransform3 *tfrm, VmathTransform3 *result0, VmathTransform3 *result1, VmathTransform3 *result2, VmathTransform3 *result3 );

/*
 * Set the upper-left 3x3 submatrix
 */
static inline void vmathSoaT3SetUpper3x3( VmathSoaTransform3 *result, const VmathSoaMatrix3 *mat3 );

/*
 * Get the upper-left 3x3 submatrix of a 3x4 transformation matrix
 */
static inline void vmathSoaT3GetUpper3x3( VmathSoaMatrix3 *result, const VmathSoaTransform3 *tfrm );

/*
 * Set translation component
 */
static inline void vmathSoaT3SetTranslation( VmathSoaTransform3 *result, const VmathSoaVector3 *translateVec );

/*
 * Get the translation component of a 3x4 transformation matrix
 */
static inline void vmathSoaT3GetTranslation( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm );

/*
 * Set column 0 of a 3x4 transformation matrix
 */
static inline void vmathSoaT3SetCol0( VmathSoaTransform3 *result, const VmathSoaVector3 *col0 );

/*
 * Set column 1 of a 3x4 transformation matrix
 */
static inline void vmathSoaT3SetCol1( VmathSoaTransform3 *result, const VmathSoaVector3 *col1 );

/*
 * Set column 2 of a 3x4 transformation matrix
 */
static inline void vmathSoaT3SetCol2( VmathSoaTransform3 *result, const VmathSoaVector3 *col2 );

/*
 * Set column 3 of a 3x4 transformation matrix
 */
static inline void vmathSoaT3SetCol3( VmathSoaTransform3 *result, const VmathSoaVector3 *col3 );

/*
 * Get column 0 of a 3x4 transformation matrix
 */
static inline void vmathSoaT3GetCol0( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm );

/*
 * Get column 1 of a 3x4 transformation matrix
 */
static inline void vmathSoaT3GetCol1( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm );

/*
 * Get column 2 of a 3x4 transformation matrix
 */
static inline void vmathSoaT3GetCol2( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm );

/*
 * Get column 3 of a 3x4 transformation matrix
 */
static inline void vmathSoaT3GetCol3( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm );

/*
 * Set the column of a 3x4 transformation matrix referred to by the specified index
 */
static inline void vmathSoaT3SetCol( VmathSoaTransform3 *result, int col, const VmathSoaVector3 *vec );

/*
 * Set the row of a 3x4 transformation matrix referred to by the specified index
 */
static inline void vmathSoaT3SetRow( VmathSoaTransform3 *result, int row, const VmathSoaVector4 *vec );

/*
 * Get the column of a 3x4 transformation matrix referred to by the specified index
 */
static inline void vmathSoaT3GetCol( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm, int col );

/*
 * Get the row of a 3x4 transformation matrix referred to by the specified index
 */
static inline void vmathSoaT3GetRow( VmathSoaVector4 *result, const VmathSoaTransform3 *tfrm, int row );

/*
 * Set the element of a 3x4 transformation matrix referred to by column and row indices
 */
static inline void vmathSoaT3SetElem( VmathSoaTransform3 *result, int col, int row, vec_float4 val );

/*
 * Get the element of a 3x4 transformation matrix referred to by column and row indices
 */
static inline vec_float4 vmathSoaT3GetElem( const VmathSoaTransform3 *tfrm, int col, int row );

/*
 * Multiply a 3x4 transformation matrix by a 3-D vector
 */
static inline void vmathSoaT3MulV3( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm, const VmathSoaVector3 *vec );

/*
 * Multiply a 3x4 transformation matrix by a 3-D point
 */
static inline void vmathSoaT3MulP3( VmathSoaPoint3 *result, const VmathSoaTransform3 *tfrm, const VmathSoaPoint3 *pnt );

/*
 * Multiply two 3x4 transformation matrices
 */
static inline void vmathSoaT3Mul( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm0, const VmathSoaTransform3 *tfrm1 );

/*
 * Construct an identity 3x4 transformation matrix
 */
static inline void vmathSoaT3MakeIdentity( VmathSoaTransform3 *result );

/*
 * Construct a 3x4 transformation matrix to rotate around the x axis
 */
static inline void vmathSoaT3MakeRotationX( VmathSoaTransform3 *result, vec_float4 radians );

/*
 * Construct a 3x4 transformation matrix to rotate around the y axis
 */
static inline void vmathSoaT3MakeRotationY( VmathSoaTransform3 *result, vec_float4 radians );

/*
 * Construct a 3x4 transformation matrix to rotate around the z axis
 */
static inline void vmathSoaT3MakeRotationZ( VmathSoaTransform3 *result, vec_float4 radians );

/*
 * Construct a 3x4 transformation matrix to rotate around the x, y, and z axes
 */
static inline void vmathSoaT3MakeRotationZYX( VmathSoaTransform3 *result, const VmathSoaVector3 *radiansXYZ );

/*
 * Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector
 */
static inline void vmathSoaT3MakeRotationAxis( VmathSoaTransform3 *result, vec_float4 radians, const VmathSoaVector3 *unitVec );

/*
 * Construct a rotation matrix from a unit-length quaternion
 */
static inline void vmathSoaT3MakeRotationQ( VmathSoaTransform3 *result, const VmathSoaQuat *unitQuat );

/*
 * Construct a 3x4 transformation matrix to perform scaling
 */
static inline void vmathSoaT3MakeScale( VmathSoaTransform3 *result, const VmathSoaVector3 *scaleVec );

/*
 * Construct a 3x4 transformation matrix to perform translation
 */
static inline void vmathSoaT3MakeTranslation( VmathSoaTransform3 *result, const VmathSoaVector3 *translateVec );

/*
 * Append (post-multiply) a scale transformation to a 3x4 transformation matrix
 * NOTE: 
 * Faster than creating and multiplying a scale transformation matrix.
 */
static inline void vmathSoaT3AppendScale( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm, const VmathSoaVector3 *scaleVec );

/*
 * Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix
 * NOTE: 
 * Faster than creating and multiplying a scale transformation matrix.
 */
static inline void vmathSoaT3PrependScale( VmathSoaTransform3 *result, const VmathSoaVector3 *scaleVec, const VmathSoaTransform3 *tfrm );

/*
 * Multiply two 3x4 transformation matrices per element
 */
static inline void vmathSoaT3MulPerElem( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm0, const VmathSoaTransform3 *tfrm1 );

/*
 * Compute the absolute value of a 3x4 transformation matrix per element
 */
static inline void vmathSoaT3AbsPerElem( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm );

/*
 * Inverse of a 3x4 transformation matrix
 * NOTE: 
 * Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0.
 */
static inline void vmathSoaT3Inverse( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm );

/*
 * Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix
 * NOTE: 
 * This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions.
 */
static inline void vmathSoaT3OrthoInverse( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm );

/*
 * Conditionally select between two 3x4 transformation matrices
 * NOTE: 
 * This function uses a conditional select instruction to avoid a branch.
 */
static inline void vmathSoaT3Select( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm0, const VmathSoaTransform3 *tfrm1, vec_uint4 select1 );

#ifdef _VECTORMATH_DEBUG

/*
 * Print a 3x4 transformation matrix
 * NOTE: 
 * Function is only defined when _VECTORMATH_DEBUG is defined.
 */
static inline void vmathSoaT3Print( const VmathSoaTransform3 *tfrm );

/*
 * Print a 3x4 transformation matrix and an associated string identifier
 * NOTE: 
 * Function is only defined when _VECTORMATH_DEBUG is defined.
 */
static inline void vmathSoaT3Prints( const VmathSoaTransform3 *tfrm, const char *name );

#endif

#ifdef __cplusplus
}
#endif /* __cplusplus */

#include "vec_soa.h"
#include "quat_soa.h"
#include "mat_soa.h"

#endif
