/* ##H_FILE#
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
FILE :          MTH3d.h
MODULE :        MTH     (Common Mathematic Library) 
 
DESCRIPTION : 3D Vectorial implementation
 
VERSION :       MTH V5.0.13 / Alexandre LANGER [ALX] Ubi R&D / Add Comments
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
 
#ifndef MTH3D_H
#define MTH3D_H
 
#include "MTH_Real.h"
 
/* ##TYPEDEF#----------------------------------------------------------------------------
                          Types definition
---------------------------------------------------------------------------------------*/
 
/* 3D Vector : */
typedef struct MTH3D_tdstVector_
{
    MTH_tdxReal xX;
    MTH_tdxReal xY;
    MTH_tdxReal xZ;
}	MTH3D_tdstVector;
 
/* 3D Matrix */
typedef struct MTH3D_tdstMatrix_
{
    MTH3D_tdstVector stCol_0;
    MTH3D_tdstVector stCol_1;
    MTH3D_tdstVector stCol_2;
}   MTH3D_tdstMatrix;
                                                   
 
/* ##MACRO#----------------------------------------------------------------------------
                          MACRO definition
---------------------------------------------------------------------------------------*/
 
/* ##-###################################### 
   ## MACRO AND FUNCTION FOR 3D MATHEMATICS
   ######################################### */
 
 
/* ##-########################### 
   ## Vector Operations
   ############################## */
 
 
/* ##M==================================================================================
NAME :          MTH3D_M_vAddVector
DESCRIPTION :   Add two vectors : VectDest= VectA + VectB
INPUT :         VectDest, VectA, VectB : address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS) 
	#if defined(OPTIMIZED_FOR_PC_FLOATS_WITH_ASM)
		#define MTH3D_M_vAddVector( VectDest, VectA, VectB)		MTH3D_M_vAddVectorASM( VectDest, VectA, VectB)	
	#else
		#define MTH3D_M_vAddVector( VectDest, VectA, VectB)		MTH3D_M_vAddVectorC( VectDest, VectA, VectB)	
	#endif
#else
	#define MTH3D_M_vAddVector( VectDest, VectA, VectB)			MTH3D_M_vAddVectorORG(VectDest, VectA, VectB)	
#endif
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSubVector
DESCRIPTION :   Sub two vectors : VectDest= VectA - VectB
INPUT :         VectDest, VectA, VectB : address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS) 
	#if defined(OPTIMIZED_FOR_PC_FLOATS_WITH_ASM)
		#define MTH3D_M_vSubVector( VectDest, VectA, VectB)		MTH3D_M_vSubVectorASM( VectDest, VectA, VectB)	
	#else
		#define MTH3D_M_vSubVector( VectDest, VectA, VectB)		MTH3D_M_vSubVectorC( VectDest, VectA, VectB)	
	#endif
#else
	#define MTH3D_M_vSubVector( VectDest, VectA, VectB)			MTH3D_M_vSubVectorORG(VectDest, VectA, VectB)	
#endif
 
 
/* ##M==================================================================================
NAME :          MTH3D_M_vNegVector
DESCRIPTION :   Negation of a vector : VectDest= - VectA
INPUT :         VectDest, VectA : address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS)
	#if defined(OPTIMIZED_FOR_PC_FLOATS_WITH_ASM)
		#define MTH3D_M_vNegVector( VectDest, VectA)		MTH3D_M_vNegVectorASM( VectDest, VectA)	
	#else
		#define MTH3D_M_vNegVector( VectDest, VectA)		MTH3D_M_vNegVectorC( VectDest, VectA)	
	#endif
#else
	#define MTH3D_M_vNegVector( VectDest, VectA)			MTH3D_M_vNegVectorORG(VectDest, VectA)	
#endif
 
/* ##M==================================================================================
NAME :          MTH3D_M_bEqualVector
DESCRIPTION :   Test if two vectors are equal
INPUT :         VectA, VectB : address of MTH3D_tdstVector
OUTPUT :        VectA==VectB : Boolean
=======================================================================================*/
#define MTH3D_M_bEqualVector( VectA, VectB)                                     \
                (                                                               \
                (MTH_M_bEqual((VectA)->xX, (VectB)->xX)) &&                     \
				(MTH_M_bEqual((VectA)->xY, (VectB)->xY)) &&                     \
				(MTH_M_bEqual((VectA)->xZ, (VectB)->xZ))                        \
        )
 
/* ##M==================================================================================
NAME :          MTH3D_M_vAddScalarVector
DESCRIPTION :   Add a scalare with a vector : VectDest= a.Id + VectA 
INPUT :         VectDest: address of MTH3D_tdstVector,
                a: MTH_tdxReal, VectA: address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vAddScalarVector( VectDest, a, VectA)   \
  {                                                     \
    (VectDest)->xX = MTH_M_xAdd((VectA)->xX, (a));      \
    (VectDest)->xY = MTH_M_xAdd((VectA)->xY, (a));      \
    (VectDest)->xZ = MTH_M_xAdd((VectA)->xZ, (a));      \
  }
 
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSubScalarVector
DESCRIPTION :   Add a scalare with a vector : VectDest= VectA - a.Id
INPUT :         VectDest: address of MTH3D_tdstVector,
                a: MTH_tdxReal, VectA: address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vSubScalarVector( VectDest, a, VectA)   \
  {                                                     \
    (VectDest)->xX = MTH_M_xSub((VectA)->xX, (a));      \
    (VectDest)->xY = MTH_M_xSub((VectA)->xY, (a));      \
    (VectDest)->xZ = MTH_M_xSub((VectA)->xZ, (a));      \
  }
 
 
/* ##M==================================================================================
NAME :          MTH3D_M_vAdd3ScalarVector
DESCRIPTION :   Add 3 scalare with a vector : VectDest= {x,y,z} + VectA 
INPUT :         VectDest: address of MTH3D_tdstVector,
                x,y,z: MTH_tdxReal, VectA: address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vAdd3( VectDest, VectA, x, y, z)   
 
#if defined(OPTIMIZED_FOR_PC_FLOATS)
	#if defined(OPTIMIZED_FOR_PC_FLOATS_WITH_ASM)
		#define MTH3D_M_vAdd3ScalarVector( VectDest, VectA, x, y, z) 		MTH3D_M_vAdd3ScalarVectorASM( VectDest, VectA, x, y, z) 
	#else
		#define MTH3D_M_vAdd3ScalarVector( VectDest, VectA, x, y, z) 		MTH3D_M_vAdd3ScalarVectorC( VectDest, VectA, x, y, z) 
	#endif
#else
	#define MTH3D_M_vAdd3ScalarVector( VectDest, VectA, x, y, z) 			MTH3D_M_vAdd3ScalarVectorORG( VectDest, VectA, x, y, z) 
#endif
 
/* ##M==================================================================================
NAME :          MTH3D_M_vMulScalarVector
DESCRIPTION :   Multiplicate a scalare with a vector : VectDest= a*VectA
INPUT :         VectDest: address of MTH3D_tdstVector,
                a: MTH_tdxReal, VectA: address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS)
	#if defined(OPTIMIZED_FOR_PC_FLOATS_WITH_ASM)
/*	is slower than C version...*/
/*		#define MTH3D_M_vMulScalarVector( VectDest, a, VectA)		MTH3D_M_vMulScalarVectorASM( VectDest, a ,VectA)*/
		#define MTH3D_M_vMulScalarVector( VectDest, a,VectA)		MTH3D_M_vMulScalarVectorC( VectDest, a, VectA)	
	#else
		#define MTH3D_M_vMulScalarVector( VectDest, a,VectA)		MTH3D_M_vMulScalarVectorC( VectDest, a, VectA)	
	#endif
#else
	#define MTH3D_M_vMulScalarVector( VectDest, a, VectA)			MTH3D_M_vMulScalarVectorORG(VectDest, a,VectA)	
#endif
 
 
/* ##M==================================================================================
NAME :          MTH3D_M_vDivScalarVector
DESCRIPTION :   Divide a vector by a scalare : VectDest= VectA/a
INPUT :         VectDest, VectA: address of MTH3D_tdstVector, a: MTH_tdxReal
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS)
	#if defined(OPTIMIZED_FOR_PC_FLOATS_WITH_ASM)
		#define MTH3D_M_vDivScalarVector( VectDest, VectA ,a)		MTH3D_M_vDivScalarVectorASM( VectDest, VectA, a)	
	#else
		#define MTH3D_M_vDivScalarVector( VectDest, VectA, a)		MTH3D_M_vDivScalarVectorC( VectDest, VectA, a)	
	#endif
#else
	#define MTH3D_M_vDivScalarVector( VectDest, VectA, a)			MTH3D_M_vDivScalarVectorORG(VectDest, VectA, a)	
#endif
 
/* ##M==================================================================================
NAME :          MTH3D_M_xDotProductVector
DESCRIPTION :   Return the Dot Product of two vectors
INPUT :         VectA, VectB : address of MTH3D_tdstVector
OUTPUT :        VectA.VectB  : MTH_tdxReal
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS) 
	#if defined(OPTIMIZED_FOR_PC_FLOATS_WITH_ASM)
/*		this fonction shouldn't be used, because passing the parameters makes it finally slower than the normal inline macro... */
/*		changed by yann le tensorer sept 21, 1998*/
/*		#define MTH3D_M_xDotProductVector( VectA, VectB)         MTH3D_M_xDotProductVectorASM( VectA, VectB)*/
		#define MTH3D_M_xDotProductVector( VectA, VectB)         MTH3D_M_xDotProductVectorC( VectA, VectB)
	#else
		#define MTH3D_M_xDotProductVector( VectA, VectB)         MTH3D_M_xDotProductVectorC( VectA, VectB)
	#endif
#else
	#define MTH3D_M_xDotProductVector( VectA, VectB)             MTH3D_M_xDotProductVectorORG( VectA, VectB)
#endif
 
/* ##M==================================================================================
NAME :          MTH3D_M_vCrossProductVectorWithoutBuffer
DESCRIPTION :   Calculate the cross product of two vectors : VectDest= VectA^VectB,
                 VectDest must be a other vector
INPUT :         VectDest, VectA, VectA: address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS) 
	#if defined(OPTIMIZED_FOR_PC_FLOATS_WITH_ASM)
		#define MTH3D_M_vCrossProductVectorWithoutBuffer(VectDest, VectA, VectB)                MTH3D_M_vCrossProductVectorWithoutBufferASM(VectDest, VectA, VectB)
	#else
		#define MTH3D_M_vCrossProductVectorWithoutBuffer(VectDest, VectA, VectB)                MTH3D_M_vCrossProductVectorWithoutBufferC(VectDest, VectA, VectB)
	#endif
#else
	#define MTH3D_M_vCrossProductVectorWithoutBuffer(VectDest, VectA, VectB)                    MTH3D_M_vCrossProductVectorWithoutBufferORG(VectDest, VectA, VectB)
#endif
 
/* ##M==================================================================================
NAME :          MTH3D_M_vCrossProductVector
DESCRIPTION :   Calculate the cross product of two vectors : VectDest= VectA^VectB
INPUT :         VectDest, VectA, VectA: address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS) 
	#if defined(OPTIMIZED_FOR_PC_FLOATS_WITH_ASM)
		#define MTH3D_M_vCrossProductVector(VectDest, VectA, VectB)                MTH3D_M_vCrossProductVectorASM(VectDest, VectA, VectB)
	#else
		#define MTH3D_M_vCrossProductVector(VectDest, VectA, VectB)                MTH3D_M_vCrossProductVectorC(VectDest, VectA, VectB)
	#endif
#else
	#define MTH3D_M_vCrossProductVector(VectDest, VectA, VectB)                    MTH3D_M_vCrossProductVectorORG(VectDest, VectA, VectB)
#endif
 
/* ##M==================================================================================
NAME :          MTH3D_M_xSqrVector
DESCRIPTION :   Return the square of a vector
INPUT :         VectA        : address of MTH3D_tdstVector
OUTPUT :        VectA.VectA  : MTH_tdxReal
=======================================================================================*/
#define MTH3D_M_xSqrVector( VectA)                                              \
                MTH_M_xAdd(                                                     \
                 MTH_M_xAdd(                                                    \
                        MTH_M_xSqr((VectA)->xX),                                \
            MTH_M_xSqr((VectA)->xY)                                             \
                           ),                                                   \
                MTH_M_xSqr((VectA)->xZ) )
 
/* ##M==================================================================================
NAME :          MTH3D_M_xNormVector
DESCRIPTION :   Return the norm of a vector
INPUT :         VectA     : address of MTH3D_tdstVector
OUTPUT :        ||VectA|| : MTH_tdxReal
=======================================================================================*/
#define MTH3D_M_xNormVector( VectA )                                            \
                        MTH_M_xSqrt( MTH3D_M_xSqrVector( VectA ) )
 
/* ##M==================================================================================
NAME :          MTH3D_M_xInvNormVector
DESCRIPTION :   Return the inverse of the norm of a vector
INPUT :         VectA       : address of MTH3D_tdstVector
OUTPUT :        1/||VectA|| : MTH_tdxReal
=======================================================================================*/
#define MTH3D_M_xInvNormVector( VectA )                                         \
                        MTH_M_xInvSqrt( MTH3D_M_xSqrVector( VectA ) )
 
/* ##M==================================================================================
NAME :          MTH3D_M_xQuickNormVector
DESCRIPTION :   Return the norm of a vector
INPUT :         VectA     : address of MTH3D_tdstVector
OUTPUT :        ||VectA|| : MTH_tdxReal
AUTHOR:			Yann Le Tensorer
=======================================================================================*/
#define MTH3D_M_xQuickNormVector( VectA )                                            \
                        MTH_M_xSqrtLow( MTH3D_M_xSqrVector( VectA ) )
 
/* ##M==================================================================================
NAME :          MTH3D_M_xQuickInvNormVector
DESCRIPTION :   Return the inverse of the norm of a vector
INPUT :         VectA       : address of MTH3D_tdstVector
OUTPUT :        1/||VectA|| : MTH_tdxReal
AUTHOR:			Yann Le Tensorer
=======================================================================================*/
#define MTH3D_M_xQuickInvNormVector( VectA )                                         \
                        MTH_M_xInvSqrtLow( MTH3D_M_xSqrVector( VectA ) )
 
 
/* ##M==================================================================================
NAME :          MTH3D_M_xVectorGapSqr
DESCRIPTION :   Return the square Gap between two vectors
INPUT :         VectA, VectB         : address of MTH3D_tdstVector
OUTPUT :        Sqr(||VectA-VectB||) : MTH_tdxReal
=======================================================================================*/
#define MTH3D_M_xVectorGapSqr(VectA, VectB)                                     \
                        (MTH_M_xSqrAddSqrAddSqr(                                \
             MTH_M_xSub( (VectA)->xX, (VectB)->xX),                             \
             MTH_M_xSub( (VectA)->xY, (VectB)->xY),                             \
             MTH_M_xSub( (VectA)->xZ, (VectB)->xZ) ) )
 
/* ##M==================================================================================
NAME :          MTH3D_M_xVectorGap
DESCRIPTION :   Return the Gap between two vectors
INPUT :         VectA, VectB    : address of MTH3D_tdstVector
OUTPUT :        ||VectA-VectB|| : MTH_tdxReal
=======================================================================================*/
#define MTH3D_M_xVectorGap(VectA, VectB)                                                \
                        (MTH_M_xSqrt( MTH3D_M_xVectorGapSqr(VectA, VectB) ))
 
/* ##M==================================================================================
NAME :          MTH3D_M_vFillVector
DESCRIPTION :   Fill each vector element with a value
INPUT :         VectA: address of MTH3D_tdstVector, a: MTH_tdxReal
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS)
/* only one computation of a an then copy without use of FPU*/
#define MTH3D_M_vFillVector( VectDest, a)                                               \
        {   (VectDest)->xZ=(VectDest)->xY=(VectDest)->xX = (a);                         \
        }
#else
#define MTH3D_M_vFillVector( VectDest, a)                                               \
        {   (VectDest)->xX = (a);														\
			(VectDest)->xY = (a);														\
			(VectDest)->xZ = (a);														\
        }
#endif
 
/* ##M==================================================================================
NAME :          MTH3D_M_vNormalizeVector
DESCRIPTION :   Normalize a vector : VectDest= VectA/||VectA||
INPUT :         VectDest, VectA : address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#ifndef U64
#define MTH3D_M_vNormalizeVector(VectDest, VectA)                                  \
         {																		   \
			register MTH_tdxReal inv_norm= MTH3D_M_xInvNormVector( VectA);         \
			MTH3D_M_vMulScalarVector(VectDest, (inv_norm), VectA );                \
         }
#else  /* U64 */
#define MTH3D_M_vNormalizeVector(VectDest, VectA)								\
	{																															\
		register MTH_tdxReal xNorm= MTH3D_M_xNormVector( VectA);		\
		if( MTH_M_bDifferentZero(xNorm) )														\
		{																														\
			xNorm = MTH_M_xInv(xNorm);																\
			MTH3D_M_vMulScalarVector(VectDest, xNorm, VectA );				\
		}																														\
	}
#endif /* U64 */
 
/* ##M==================================================================================
NAME :          MTH3D_M_vQuickNormalizeVector
DESCRIPTION :   Normalize a vector : VectDest= VectA/||VectA||
INPUT :         VectDest, VectA : address of MTH3D_tdstVector
OUTPUT :        void
AUTHOR:			Yann Le Tensorer
=======================================================================================*/
#ifndef U64
#define MTH3D_M_vQuickNormalizeVector(VectDest, VectA)                                  \
         {																		   \
			register MTH_tdxReal inv_norm= MTH3D_M_xQuickInvNormVector( VectA);         \
			MTH3D_M_vMulScalarVector(VectDest, (inv_norm), VectA );                \
         }
#else  /* U64 */
#define MTH3D_M_vQuickNormalizeVector(VectDest, VectA)	MTH3D_M_vNormalizeVector(VectDest,VectA)
#endif /* U64 */
 
/* ##M==================================================================================
NAME :          MTH3D_M_vGetVectorElements
DESCRIPTION :   Get x, y, z values of a vector
INPUT :         x, y, z : address of MTH_tdxReal, VectA : address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vGetVectorElements( Vx, Vy, Vz, VectA)                  \
        {   *Vx = (VectA)->xX;                                          \
            *Vy = (VectA)->xY;                                          \
            *Vz = (VectA)->xZ; }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSetVectorElements
DESCRIPTION :   Set a vector with  x, y, z values
INPUT :         VectDest : address of MTH3D_tdstVector, x, y, z : address of MTH_tdxReal, 
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vSetVectorElements( VectDest, Vx, Vy, Vz)               \
        {   (VectDest)->xX = (Vx);                                      \
            (VectDest)->xY = (Vy);                                      \
            (VectDest)->xZ = (Vz); }
 
/* ##M==================================================================================
NAME :          MTH3D_M_xGetXofVector
DESCRIPTION :   Return x element of a vector
INPUT :         VectA : address of MTH3D_tdstVector
OUTPUT :        x     : MTH_tdxReal
=======================================================================================*/
#define MTH3D_M_xGetXofVector( VectA )                                  (VectA)->xX
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSetXofVector
DESCRIPTION :   Set x element of a vector
INPUT :         VectDest : address of MTH3D_tdstVector, Vx : MTH_tdxReal
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vSetXofVector( VectDest, Vx)                            { (VectDest)->xX = (Vx); }
 
/* ##M==================================================================================
NAME :          MTH3D_M_xGetYofVector
DESCRIPTION :   Return y element of a vector
INPUT :         VectA : address of MTH3D_tdstVector
OUTPUT :        y     : MTH_tdxReal
=======================================================================================*/
#define MTH3D_M_xGetYofVector( VectA )                                  (VectA)->xY
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSetYofVector
DESCRIPTION :   Set y element of a vector
INPUT :         VectDest : address of MTH3D_tdstVector, Vy : MTH_tdxReal
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vSetYofVector( VectDest, Vy)                            { (VectDest)->xY = (Vy); }
 
/* ##M==================================================================================
NAME :          MTH3D_M_xGetZofVector
DESCRIPTION :   Return z element of a vector
INPUT :         VectA : address of MTH3D_tdstVector
OUTPUT :        z     : MTH_tdxReal
=======================================================================================*/
#define MTH3D_M_xGetZofVector( VectA )                                  (VectA)->xZ
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSetZofVector
DESCRIPTION :   Set z element of a vector
INPUT :         VectDest : address of MTH3D_tdstVector, Vz : MTH_tdxReal
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vSetZofVector( VectDest, Vz)                            { (VectDest)->xZ = (Vz); }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vCopyVector
DESCRIPTION :   Copy a vector : VectDest=VectA 
INPUT :         VectDest, VectA : address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#if (defined(OPTIMIZED_FOR_PC_FLOATS) || defined(MTH_RealIsFloat))
/* no fpu, no call to function*/
/*#define MTH3D_M_vCopyVector( VectDest, VectA)                                   \
     {  (VectDest)->xX = (VectA)->xX; \
		(VectDest)->xY = (VectA)->xY; \
		(VectDest)->xZ = (VectA)->xZ; \
	 }
*/
#define MTH3D_M_vCopyVector( VectDest, VectA)                                           \
	{	((unsigned long *) (VectDest))[0]=	((unsigned long *) (VectA))[0];				\
		((unsigned long *) (VectDest))[1]=	((unsigned long *) (VectA))[1];				\
		((unsigned long *) (VectDest))[2]=	((unsigned long *) (VectA))[2];				\
	}
 
#else
	#define MTH3D_M_vCopyVector( VectDest, VectA)                                   \
     {  memcpy(VectDest, VectA, sizeof(MTH3D_tdstVector)); }
#endif
 
/* ##M==================================================================================
NAME :          MTH3D_M_vNullVector
DESCRIPTION :   Set all elements of a vector to zero
INPUT :         VectDest : address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS)
#define MTH3D_M_vNullVector( VectDest)    { (VectDest)->xZ=(VectDest)->xY=(VectDest)->xX=MTH_C_ZERO; }
#else
#define MTH3D_M_vNullVector( VectDest)                                                  \
        {         (VectDest)->xX = MTH_C_ZERO;                                          \
                  (VectDest)->xY = MTH_C_ZERO;                                          \
                  (VectDest)->xZ = MTH_C_ZERO; }
#endif
            
/* ##M==================================================================================
NAME :          MTH3D_M_vScaleVector
DESCRIPTION :   Set each element of  VectDest with the multiplication of element of VectA by element of VectB
INPUT :         VectDest, VectA, VectB : address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS)
	#if defined(OPTIMIZED_FOR_PC_FLOATS_WITH_ASM)
		#define MTH3D_M_vScaleVector( VectDest, VectA, VectB )		MTH3D_M_vScaleVectorASM( VectDest, VectA, VectB)	
	#else
		#define MTH3D_M_vScaleVector( VectDest, VectA, VectB)		MTH3D_M_vScaleVectorC( VectDest, VectA, VectB)	
	#endif
#else
	#define MTH3D_M_vScaleVector( VectDest, VectA, VectB)			MTH3D_M_vScaleVectorORG(VectDest, VectA, VectB)	
#endif
 
 
/* ##M==================================================================================
NAME :          MTH3D_M_vMiddleVector
DESCRIPTION :   Calculate the middle of two vectors : VectDest= (VectA+VectB)/2 
INPUT :         VectDest, VectA, VectB : address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vMiddleVector( VectDest, VectA, VectB )                 \
        {       MTH3D_M_vAddVector( VectDest, VectA, VectB );           \
                MTH3D_M_vMulScalarVector( VectDest, MTH_C_Inv2 , VectDest); }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vLinearInterpolVector
DESCRIPTION :   Calculate the linear interpolation of two vectors : VectDest= VectA + t.(VectB-VectA)
INPUT :         VectDest, VectA, VectB: address of MTH3D_tdstVector, t: MTH_tdxReal
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS)
	#if defined(OPTIMIZED_FOR_PC_FLOATS_WITH_ASM)
		#define MTH3D_M_vLinearInterpolVector( VectDest, VectA, VectB, t)		MTH3D_M_vLinearInterpolVectorASM( VectDest, VectA, VectB, t)	
	#else
		#define MTH3D_M_vLinearInterpolVector( VectDest, VectA, VectB, t)		MTH3D_M_vLinearInterpolVectorC( VectDest, VectA, VectB, t)	
	#endif
#else
	#define MTH3D_M_vLinearInterpolVector( VectDest, VectA, VectB,t)			MTH3D_M_vLinearInterpolVectorORG(VectDest, VectA, VectB, t)	
#endif
 
 
/* ##M==================================================================================
NAME :          MTH3D_M_vLinearScaleVector
DESCRIPTION :   Calculate the linear interpolation of two vectors : VectDest= VectA + VectC*(VectB-VectA)
INPUT :         VectDest, VectA, VectB, VectC: address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS)
	#if defined(OPTIMIZED_FOR_PC_FLOATS_WITH_ASM)
		#define MTH3D_M_vLinearScaleVector( VectDest, VectA, VectB, VectC)		MTH3D_M_vLinearScaleVectorASM( VectDest, VectA, VectB, VectC)	
	#else
		#define MTH3D_M_vLinearScaleVector( VectDest, VectA, VectB, VectC)		MTH3D_M_vLinearScaleVectorC( VectDest, VectA, VectB, VectC)	
	#endif
#else
	#define MTH3D_M_vLinearScaleVector( VectDest, VectA, VectB, VectC)			MTH3D_M_vLinearScaleVectorORG(VectDest, VectA, VectB, VectC)	
#endif
 
 
/* ##M==================================================================================
NAME :          MTH3D_M_vMaxVector
DESCRIPTION :   Make a vector with max elements of two other vectors
INPUT :         VectDest, VectA, VectB: address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vMaxVector( VectDest, VectA, VectB)                     \
        {   (VectDest)->xX= MTH_M_xMax( (VectA)->xX, (VectB)->xX );     \
            (VectDest)->xY= MTH_M_xMax( (VectA)->xY, (VectB)->xY );     \
            (VectDest)->xZ= MTH_M_xMax( (VectA)->xZ, (VectB)->xZ ); } 
 
/* ##M==================================================================================
NAME :          MTH3D_M_vMinVector
DESCRIPTION :   Make a vector with min elements of two other vectors
INPUT :         VectDest, VectA, VectB: address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vMinVector( VectDest, VectA, VectB)                     \
        {   (VectDest)->xX= MTH_M_xMin( (VectA)->xX, (VectB)->xX );     \
            (VectDest)->xY= MTH_M_xMin( (VectA)->xY, (VectB)->xY );     \
            (VectDest)->xZ= MTH_M_xMin( (VectA)->xZ, (VectB)->xZ ); }
                                                       
 
/* ##M==================================================================================
NAME :          MTH3D_M_xDetXYVector
DESCRIPTION :   Return the 2D determinant between X and Y elements
INPUT :         VectA, VectB: address of MTH3D_tdstVector
OUTPUT :        DetXY |VectA, VectB| : MTH_tdxReal
=======================================================================================*/
#define MTH3D_M_xDetXYVector( VectA, VectB )    MTH_M_xMulSubMul( (VectA)->xX, (VectB)->xY, (VectA)->xY, (VectB)->xX)
 
/* ##M==================================================================================
NAME :          MTH3D_M_xDetYZVector
DESCRIPTION :   Return the 2D determinant between Y and Z elements
INPUT :         VectA, VectB: address of MTH3D_tdstVector
OUTPUT :        DetYZ |VectA, VectB| : MTH_tdxReal
=======================================================================================*/
#define MTH3D_M_xDetYZVector( VectA, VectB )    MTH_M_xMulSubMul( (VectA)->xY, (VectB)->xZ, (VectA)->xZ, (VectB)->xY)
   
/* ##M==================================================================================
NAME :          MTH3D_M_xDetZXVector
DESCRIPTION :   Return the 2D determinant between Z and X elements
INPUT :         VectA, VectB: address of MTH3D_tdstVector
OUTPUT :        DetZX |VectA, VectB| : MTH_tdxReal
=======================================================================================*/
#define MTH3D_M_xDetZXVector( VectA, VectB )    MTH_M_xMulSubMul( (VectA)->xZ, (VectB)->xX, (VectA)->xX, (VectB)->xZ)
 
/* ##M==================================================================================
NAME :          MTH3D_M_bIsNullVector
DESCRIPTION :   Test if a vector is null
INPUT :         VectA : address of MTH3D_tdstVector
OUTPUT :        VectA==Null vector : Boolean
=======================================================================================*/
#define MTH3D_M_bIsNullVector( VectA )          ( MTH_M_bEqualZero((VectA)->xX) && MTH_M_bEqualZero((VectA)->xY) && MTH_M_bEqualZero((VectA)->xZ) )  
 
/* ##M==================================================================================
NAME :          MTH3D_M_vMulAddVector
DESCRIPTION :   Multiply a scalar to a vector, and add it to a other vector: VectDest = x.VectA + VectB
INPUT :         VectDest: address of MTH3D_tdstVector,
                x: MTH_tdxReal, VectA, VectB : address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS)
	#if defined(OPTIMIZED_FOR_PC_FLOATS_WITH_ASM)
		#define MTH3D_M_vMulAddVector( VectDest, x,VectA, VectB )		MTH3D_M_vMulAddVectorASM( VectDest, x,VectA, VectB)	
	#else
		#define MTH3D_M_vMulAddVector( VectDest, x,VectA, VectB)		MTH3D_M_vMulAddVectorC( VectDest, x,VectA, VectB)	
	#endif
#else
	#define MTH3D_M_vMulAddVector( VectDest, x,VectA, VectB)			MTH3D_M_vMulAddVectorORG(VectDest, x,VectA, VectB)	
#endif
        
/* MTH3D_M_vMullAddVector( VectDest, x,  VectA, VectB) : VectDest = x.VectA + VectB */            
#define MTH3D_M_vMullAddVector MTH3D_M_vMulAddVector
 
/* ##M==================================================================================
NAME :          MTH3D_M_vMul3AddVector
DESCRIPTION :   VectDest = x.VectA + y.VectB + z.VectC
INPUT :         VectDest: address of MTH3D_tdstVector,
                x,y,z: MTH_tdxReal, VectA, VectB, VectC : address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS)
	#if defined(OPTIMIZED_FOR_PC_FLOATS_WITH_ASM)
		#define MTH3D_M_vMul3AddVector( VectDest, x,VectA, y,VectB, z,VectC)		MTH3D_M_vMul3AddVectorASM( VectDest, x,VectA, y,VectB, z,VectC)	
	#else
		#define MTH3D_M_vMul3AddVector( VectDest, x,VectA, y,VectB, z,VectC)		MTH3D_M_vMul3AddVectorC( VectDest, x,VectA, y,VectB, z,VectC)	
	#endif
#else
	#define MTH3D_M_vMul3AddVector( VectDest, x,VectA, y,VectB, z,VectC)			MTH3D_M_vMul3AddVectorORG(VectDest, x,VectA, y,VectB, z,VectC)	
#endif
 
/* ##M==================================================================================
NAME :          MTH3D_M_vMul4AddVector
DESCRIPTION :   VectDest = x.VectA + y.VectB + z.VectC + w.VectD
INPUT :         VectDest: address of MTH3D_tdstVector,
                x,y,z,w: MTH_tdxReal, VectA, VectB, VectC, VectD : address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS)
	#if defined(OPTIMIZED_FOR_PC_FLOATS_WITH_ASM)
		#define MTH3D_M_vMul4AddVector( VectDest, x,VectA, y,VectB, z,VectC, w,VectD)		MTH3D_M_vMul4AddVectorASM( VectDest, x,VectA, y,VectB, z,VectC, w,VectD)	
	#else
		#define MTH3D_M_vMul4AddVector( VectDest, x,VectA, y,VectB, z,VectC, w,VectD)		MTH3D_M_vMul4AddVectorC( VectDest, x,VectA, y,VectB, z,VectC, w,VectD)	
	#endif
#else
	#define MTH3D_M_vMul4AddVector( VectDest, x,VectA, y,VectB, z,VectC, w,VectD)			MTH3D_M_vMul4AddVectorORG(VectDest, x,VectA, y,VectB, z,VectC, w,VectD)	
#endif
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSetBaseIVector
DESCRIPTION :   Set a vector to Ox base vector : VectDest = ( 1, 0, 0 )
INPUT :         VectDest: address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vSetBaseIVector( VectDest )     { (VectDest)->xX = MTH_C_ONE; (VectDest)->xZ = (VectDest)->xY = MTH_C_ZERO; } 
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSetBaseJVector
DESCRIPTION :   Set a vector to Oy base vector : VectDest = ( 0, 1, 0 )
INPUT :         VectDest: address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vSetBaseJVector( VectDest )     { (VectDest)->xX = MTH_C_ZERO; (VectDest)->xY = MTH_C_ONE; (VectDest)->xZ = MTH_C_ZERO; }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSetBaseKVector
DESCRIPTION :   Set a vector to Oz base vector : VectDest = ( 0, 0, 1 )
INPUT :         VectDest: address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vSetBaseKVector( VectDest )     { (VectDest)->xY = (VectDest)->xX = MTH_C_ZERO; (VectDest)->xZ = MTH_C_ONE; }
 
/* ##M==================================================================================
NAME :          MTH3D_M_xNorm1Vector
DESCRIPTION :   Return the norm 1 of a vector
INPUT :         VectA : address of MTH3D_tdstVector
OUTPUT :        |VectA->x| + |VectA->y| + |VectA->z| : MTH_tdxReal
=======================================================================================*/
#define MTH3D_M_xNorm1Vector( VectA )     MTH_M_xAdd3( MTH_M_xAbs((VectA)->xX) , MTH_M_xAbs((VectA)->xY) , MTH_M_xAbs((VectA)->xZ) )
 
/* ##-########################### 
   ## Matrix operations
   ############################## */   
 
 
/* ##M==================================================================================
NAME :          MTH3D_M_vCopyMatrix
DESCRIPTION :   Copy MatA in MatDest
INPUT :         MatDest, MatA: address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS)
/* 9 clocks when good pairing else always less than 18 clocks : much better than memcpy*/
/* doesn't use FPU but only the "mov" instructions*/
#define MTH3D_M_vCopyMatrix( MatDest, MatA)                             \
     {  MTH3D_M_vCopyVector(&((MatDest)->stCol_0),&((MatA)->stCol_0) ); \
		MTH3D_M_vCopyVector(&((MatDest)->stCol_1),&((MatA)->stCol_1) ); \
		MTH3D_M_vCopyVector(&((MatDest)->stCol_2),&((MatA)->stCol_2) ); \
	 }
#else
#define MTH3D_M_vCopyMatrix( MatDest, MatA)                             \
     {  memcpy(MatDest, MatA, sizeof(MTH3D_tdstMatrix)); }
#endif
 
/* ##M==================================================================================
NAME :          MTH3D_M_vAddMatrix
DESCRIPTION :   Add two matrix : MatDest= MatA + MatB
INPUT :         MatDest, MatA, MatB: address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vAddMatrix( MatDest, MatA, MatB)                                \
        {  MTH3D_M_vAddVector( &((MatDest)->stCol_0),                           \
                                &((MatA)->stCol_0), &((MatB)->stCol_0));        \
           MTH3D_M_vAddVector( &((MatDest)->stCol_1),                           \
                                &((MatA)->stCol_1), &((MatB)->stCol_1));        \
           MTH3D_M_vAddVector( &((MatDest)->stCol_2),                           \
                                       &((MatA)->stCol_2), &((MatB)->stCol_2)); }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSubMatrix
DESCRIPTION :   Sub two matrix : MatDest= MatA - MatB
INPUT :         MatDest, MatA, MatB: address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vSubMatrix( MatDest, MatA, MatB)                                \
        {  MTH3D_M_vSubVector( &((MatDest)->stCol_0),                           \
                                &((MatA)->stCol_0), &((MatB)->stCol_0));        \
           MTH3D_M_vSubVector( &((MatDest)->stCol_1),                           \
                                &((MatA)->stCol_1), &((MatB)->stCol_1));        \
           MTH3D_M_vSubVector( &((MatDest)->stCol_2),                           \
                               &((MatA)->stCol_2), &((MatB)->stCol_2)); }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vNegMatrix
DESCRIPTION :   Make the Nagation of a matrix : MatDest= -MatA
INPUT :         MatDest, MatA: address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vNegMatrix( MatDest, MatA)                      \
        {  MTH3D_M_vNegVector( &((MatDest)->stCol_0),           \
                                &((MatA)->stCol_0));            \
           MTH3D_M_vNegVector( &((MatDest)->stCol_1),           \
                                &((MatA)->stCol_1));            \
           MTH3D_M_vNegVector( &((MatDest)->stCol_2),           \
                               &((MatA)->stCol_2)); }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vMulMatrixMatrixWithoutBuffer
DESCRIPTION :   Multiply two matrix : MatDest= MatA*MatB, MatDest must be a other matrix
INPUT :         MatDest, MatA, MatB: address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS) 
	#if defined(OPTIMIZED_FOR_PC_FLOATS_WITH_ASM)
		#define MTH3D_M_vMulMatrixMatrixWithoutBuffer(MatDest, MatA, MatB)    MTH3D_M_vMulMatrixMatrixWithoutBufferASM(MatDest, MatA, MatB)
	#elif defined(OPTIMIZED_FOR_U64_ASM)
		#define MTH3D_M_vMulMatrixMatrixWithoutBuffer(MatDest, MatA, MatB)    MTH3D_M_vMulMatrixMatrixWithoutBufferU64ASM(MatDest, MatA, MatB)
	#else	
		#define MTH3D_M_vMulMatrixMatrixWithoutBuffer(MatDest, MatA, MatB)    MTH3D_M_vMulMatrixMatrixWithoutBufferC(MatDest, MatA, MatB)
	#endif
#else
		#define MTH3D_M_vMulMatrixMatrixWithoutBuffer(MatDest, MatA, MatB)    MTH3D_M_vMulMatrixMatrixWithoutBufferORG(MatDest, MatA, MatB)
#endif
 
/* ##M==================================================================================
NAME :          MTH3D_M_vMulMatrixMatrix
DESCRIPTION :   Multiply two matrix : MatDest= MatA*MatB
INPUT :         MatDest, MatA, MatB: address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS) 
	#if defined(OPTIMIZED_FOR_PC_FLOATS_WITH_ASM)
		#define MTH3D_M_vMulMatrixMatrix(MatDest, MatA, MatB)    MTH3D_M_vMulMatrixMatrixASM(MatDest, MatA, MatB)
	#else	
		#define MTH3D_M_vMulMatrixMatrix(MatDest, MatA, MatB)    MTH3D_M_vMulMatrixMatrixC(MatDest, MatA, MatB)
	#endif
#else
		#define MTH3D_M_vMulMatrixMatrix(MatDest, MatA, MatB)    MTH3D_M_vMulMatrixMatrixORG(MatDest, MatA, MatB)
#endif
 
 
/* ##M==================================================================================
NAME :          MTH3D_M_vMulTranspMatrixMatrixWithoutBuffer
DESCRIPTION :   Multiply the transposed matrix to a other: MatDest= (transp MatA)*MatB,
                 MatDest must be a other matrix
INPUT :         MatDest, MatA, MatB: address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vMulTranspMatrixMatrixWithoutBuffer(MatDest, MatA, MatB)                \
    {                                                                                   \
            (MatDest)->stCol_0.xX =  MTH_M_xMulAddMulAddMul(                            \
                (MatA)->stCol_0.xX, (MatB)->stCol_0.xX,                                 \
                (MatA)->stCol_0.xY, (MatB)->stCol_0.xY,                                 \
                (MatA)->stCol_0.xZ, (MatB)->stCol_0.xZ );                               \
            (MatDest)->stCol_0.xY =  MTH_M_xMulAddMulAddMul(                            \
                (MatA)->stCol_1.xX, (MatB)->stCol_0.xX,                                 \
                (MatA)->stCol_1.xY, (MatB)->stCol_0.xY,                                 \
                (MatA)->stCol_1.xZ, (MatB)->stCol_0.xZ );                               \
            (MatDest)->stCol_0.xZ =  MTH_M_xMulAddMulAddMul(                            \
                (MatA)->stCol_2.xX, (MatB)->stCol_0.xX,                                 \
                (MatA)->stCol_2.xY, (MatB)->stCol_0.xY,                                 \
                (MatA)->stCol_2.xZ, (MatB)->stCol_0.xZ );                               \
                                                                                        \
            (MatDest)->stCol_1.xX =  MTH_M_xMulAddMulAddMul(                            \
                (MatA)->stCol_0.xX, (MatB)->stCol_1.xX,                                 \
                (MatA)->stCol_0.xY, (MatB)->stCol_1.xY,                                 \
                (MatA)->stCol_0.xZ, (MatB)->stCol_1.xZ );                               \
            (MatDest)->stCol_1.xY =  MTH_M_xMulAddMulAddMul(                            \
                (MatA)->stCol_1.xX, (MatB)->stCol_1.xX,                                 \
                (MatA)->stCol_1.xY, (MatB)->stCol_1.xY,                                 \
                (MatA)->stCol_1.xZ, (MatB)->stCol_1.xZ );                               \
            (MatDest)->stCol_1.xZ =  MTH_M_xMulAddMulAddMul(                            \
                (MatA)->stCol_2.xX, (MatB)->stCol_1.xX,                                 \
                (MatA)->stCol_2.xY, (MatB)->stCol_1.xY,                                 \
                (MatA)->stCol_2.xZ, (MatB)->stCol_1.xZ );                               \
                                                                                        \
            (MatDest)->stCol_2.xX =  MTH_M_xMulAddMulAddMul(                            \
                (MatA)->stCol_0.xX, (MatB)->stCol_2.xX,                                 \
                (MatA)->stCol_0.xY, (MatB)->stCol_2.xY,                                 \
                (MatA)->stCol_0.xZ, (MatB)->stCol_2.xZ );                               \
            (MatDest)->stCol_2.xY =  MTH_M_xMulAddMulAddMul(                            \
                (MatA)->stCol_1.xX, (MatB)->stCol_2.xX,                                 \
                (MatA)->stCol_1.xY, (MatB)->stCol_2.xY,                                 \
                (MatA)->stCol_1.xZ, (MatB)->stCol_2.xZ );                               \
            (MatDest)->stCol_2.xZ =  MTH_M_xMulAddMulAddMul(                            \
                (MatA)->stCol_2.xX, (MatB)->stCol_2.xX,                                 \
                (MatA)->stCol_2.xY, (MatB)->stCol_2.xY,                                 \
                (MatA)->stCol_2.xZ, (MatB)->stCol_2.xZ );                               \
      }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vMulTranspMatrixMatrix
DESCRIPTION :   Multiply the transposed matrix to a other: MatDest= (transp MatA)*MatB,
INPUT :         MatDest, MatA, MatB: address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vMulTranspMatrixMatrix(Mat_Dest, Mat_A, Mat_B)          \
            if( (Mat_Dest==Mat_A) || (Mat_Dest==Mat_B) )                \
            {                                                           \
              MTH3D_tdstMatrix Mtemp;                                   \
                                                                        \
              MTH3D_M_vMulTranspMatrixMatrixWithoutBuffer(              \
                                        &Mtemp, Mat_A, Mat_B);          \
              MTH3D_M_vCopyMatrix( Mat_Dest, &Mtemp);                   \
            }                                                           \
            else                                                        \
            {                                                           \
             MTH3D_M_vMulTranspMatrixMatrixWithoutBuffer(Mat_Dest,      \
                                              Mat_A,  Mat_B);           \
             }
 
 
 
/* ##M==================================================================================
NAME :          MTH3D_M_vMulScalarMatrix
DESCRIPTION :   Multiply a scalar with a matrix : MatDest= a*MatA
INPUT :         MatDest : address of MTH3D_tdstMatrix
                a: MTH_tdxReal, MatA : address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS)
/* only one computation of a*/
#define MTH3D_M_vMulScalarMatrix(MatDest, a, MatA)											   \
   {	    register MTH_tdxReal xTempMTH3D_M_vMulScalarMatrix=(a);													   \
		    MTH3D_M_vMulScalarVector( &((MatDest)->stCol_0), xTempMTH3D_M_vMulScalarMatrix, &((MatA)->stCol_0));       \
            MTH3D_M_vMulScalarVector( &((MatDest)->stCol_1), xTempMTH3D_M_vMulScalarMatrix, &((MatA)->stCol_1));       \
            MTH3D_M_vMulScalarVector( &((MatDest)->stCol_2), xTempMTH3D_M_vMulScalarMatrix, &((MatA)->stCol_2)); }
#else
#define MTH3D_M_vMulScalarMatrix(MatDest, a, MatA)											   \
   {	    MTH3D_M_vMulScalarVector( &((MatDest)->stCol_0), (a), &((MatA)->stCol_0));         \
            MTH3D_M_vMulScalarVector( &((MatDest)->stCol_1), (a), &((MatA)->stCol_1));         \
            MTH3D_M_vMulScalarVector( &((MatDest)->stCol_2), (a), &((MatA)->stCol_2)); }
#endif
 
/* ##M==================================================================================
NAME :          MTH3D_M_vDivScalarMatrix
DESCRIPTION :   Divide a matrix by a scalar : MatDest= MatA/a
INPUT :         MatDest : address of MTH3D_tdstMatrix
                MatA : address of MTH3D_tdstMatrix, a: MTH_tdxReal
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS)
/* only one division and one computation of 1/a*/
#define MTH3D_M_vDivScalarMatrix(MatDest, MatA, a)											   \
			MTH3D_M_vMulScalarMatrix(MatDest, MTH_M_xDiv(MTH_C_ONE,(a)), MatA);
#else
#define MTH3D_M_vDivScalarMatrix(MatDest, MatA, a)                              \
   {                    MTH3D_M_vDivScalarVector( &((MatDest)->stCol_0),        \
                                        &((MatA)->stCol_0), (a));               \
                        MTH3D_M_vDivScalarVector( &((MatDest)->stCol_1),        \
                                        &((MatA)->stCol_1), (a));               \
                        MTH3D_M_vDivScalarVector( &((MatDest)->stCol_2),        \
                                                  &((MatA)->stCol_2), (a)); }
#endif
 
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSqrMatrix
DESCRIPTION :   Square a matrix : MatDest= MatA*MatA
INPUT :         MatDest : address of MTH3D_tdstMatrix
                MatA : address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vSqrMatrix(MatDest, MatA)       { MTH3D_M_vMulMatrixMatrix( MatDest, MatA, MatA); }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vTranspMatrixWithoutBuffer
DESCRIPTION :   Transpose a matrix : MatDest= transp MatA, Matdest must be a other matrix
INPUT :         MatDest : address of MTH3D_tdstMatrix
                MatA : address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vTranspMatrixWithoutBuffer(MatDest, MatA)               \
        {   (MatDest)->stCol_0.xX = (MatA)->stCol_0.xX;                 \
            (MatDest)->stCol_0.xY = (MatA)->stCol_1.xX;                 \
            (MatDest)->stCol_0.xZ = (MatA)->stCol_2.xX;                 \
            (MatDest)->stCol_1.xX = (MatA)->stCol_0.xY;                 \
            (MatDest)->stCol_1.xY = (MatA)->stCol_1.xY;                 \
            (MatDest)->stCol_1.xZ = (MatA)->stCol_2.xY;                 \
            (MatDest)->stCol_2.xX = (MatA)->stCol_0.xZ;                 \
            (MatDest)->stCol_2.xY = (MatA)->stCol_1.xZ;                 \
            (MatDest)->stCol_2.xZ = (MatA)->stCol_2.xZ; }
 
/* MTH3D_M_vTranpMatrixWithoutBuffer(MatDest, MatA) : MatDest= transp MatA */
#define MTH3D_M_vTranpMatrixWithoutBuffer MTH3D_M_vTranspMatrixWithoutBuffer
 
/* ##M==================================================================================
NAME :          MTH3D_M_vTranspMatrix
DESCRIPTION :   Transpose a matrix : MatDest= transp MatA
INPUT :         MatDest : address of MTH3D_tdstMatrix
                MatA : address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS)
/* no copy, direct transposition => swap coefficients*/
#define MTH3D_M_vTranspMatrix(Mat_Dest, Mat_A)                    \
            if( Mat_Dest==Mat_A )                                 \
            {                                                     \
			  long lTemp0=*((long*) &((Mat_Dest)->stCol_0.xY));	  \
			  long lTemp1=*((long*) &((Mat_Dest)->stCol_0.xZ));	  \
			  long lTemp2=*((long*) &((Mat_Dest)->stCol_1.xZ));   \
			  (Mat_Dest)->stCol_0.xY=(Mat_Dest)->stCol_1.xX;	  \
			  (Mat_Dest)->stCol_0.xZ=(Mat_Dest)->stCol_2.xX;	  \
			  (Mat_Dest)->stCol_1.xZ=(Mat_Dest)->stCol_2.xY;	  \
			  *((long*) &((Mat_Dest)->stCol_1.xX))=lTemp0;		  \
			  *((long*) &((Mat_Dest)->stCol_2.xX))=lTemp1;		  \
			  *((long*) &((Mat_Dest)->stCol_2.xY))=lTemp2;		  \
            }                                                     \
            else                                                  \
            {                                                     \
	             MTH3D_M_vTranspMatrixWithoutBuffer(Mat_Dest, Mat_A); \
            }
#else
#define MTH3D_M_vTranspMatrix(Mat_Dest, Mat_A)                    \
            if( Mat_Dest==Mat_A )                                 \
            {                                                     \
              MTH3D_tdstMatrix Mtemp;                             \
                                                                  \
              MTH3D_M_vTranspMatrixWithoutBuffer(&Mtemp, Mat_A);  \
              MTH3D_M_vCopyMatrix( Mat_Dest, &Mtemp);             \
            }                                                     \
            else                                                  \
            {                                                     \
	             MTH3D_M_vTranspMatrixWithoutBuffer(Mat_Dest, Mat_A); \
            }
#endif
 
/* MTH3D_M_vTranpMatrix(MatDest, MatA)          : MatDest= transp MatA */
#define MTH3D_M_vTranpMatrix MTH3D_M_vTranspMatrix
 
/* ##M==================================================================================
NAME :          MTH3D_M_xTraceMatrix
DESCRIPTION :   Return the trace of a matrix
INPUT :         MatA : address of MTH3D_tdstMatrix
OUTPUT :        trace MatA : MTH_tdxReal
=======================================================================================*/
#define MTH3D_M_xTraceMatrix(MatA)    MTH_M_xAdd3((MatA)->stCol_0.xX, (MatA)->stCol_1.xY, (MatA)->stCol_2.xZ)
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSetIdentityMatrix
DESCRIPTION :   Set a matrix to the Identity matrix : MatDest= Id
INPUT :         MatDest : address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vSetIdentityMatrix(MatDest)                                     \
        {   (MatDest)->stCol_0.xX = MTH_C_ONE;                                  \
            (MatDest)->stCol_0.xY = MTH_C_ZERO;                                 \
            (MatDest)->stCol_0.xZ = MTH_C_ZERO;                                 \
            (MatDest)->stCol_1.xX = MTH_C_ZERO;                                 \
            (MatDest)->stCol_1.xY = MTH_C_ONE;                                  \
            (MatDest)->stCol_1.xZ = MTH_C_ZERO;                                 \
            (MatDest)->stCol_2.xX = MTH_C_ZERO;                                 \
            (MatDest)->stCol_2.xY = MTH_C_ZERO;                                 \
            (MatDest)->stCol_2.xZ = MTH_C_ONE; }
 
/* ##M==================================================================================
NAME :          MTH3D_M_bEqualMatrix
DESCRIPTION :   Test if two matrix are equal
INPUT :         MatA, MatB : address of MTH3D_tdstMatrix
OUTPUT :        MatA==MatB : Boolean
=======================================================================================*/
#define MTH3D_M_bEqualMatrix(MatA, MatB)                                \
                        (                                               \
            MTH_M_bEqual( (MatA)->stCol_0.xX, (MatB)->stCol_0.xX) &&    \
            MTH_M_bEqual( (MatA)->stCol_0.xY, (MatB)->stCol_0.xY) &&    \
            MTH_M_bEqual( (MatA)->stCol_0.xZ, (MatB)->stCol_0.xZ) &&    \
            MTH_M_bEqual( (MatA)->stCol_1.xX, (MatB)->stCol_1.xX) &&    \
            MTH_M_bEqual( (MatA)->stCol_1.xY, (MatB)->stCol_1.xY) &&    \
            MTH_M_bEqual( (MatA)->stCol_1.xZ, (MatB)->stCol_1.xZ) &&    \
            MTH_M_bEqual( (MatA)->stCol_2.xX, (MatB)->stCol_2.xX) &&    \
            MTH_M_bEqual( (MatA)->stCol_2.xY, (MatB)->stCol_2.xY) &&    \
            MTH_M_bEqual( (MatA)->stCol_2.xZ, (MatB)->stCol_2.xZ)       \
            )
 
 
/* ##M==================================================================================
NAME :          MTH3D_M_bMatchMatrix
DESCRIPTION :   Test if two matrix are neary equal
INPUT :         MatA, MatB : address of MTH3D_tdstMatrix
                eps : MTH_tdxReal
OUTPUT :        (MatA match MatB to within about eps) : Boolean
=======================================================================================*/
#define MTH3D_M_bMatchMatrix(MatA, MatB, eps)                                           \
                        (                                                               \
            MTH_M_bEqualWithEpsilon( (MatA)->stCol_0.xX, (MatB)->stCol_0.xX, eps) &&    \
            MTH_M_bEqualWithEpsilon( (MatA)->stCol_0.xY, (MatB)->stCol_0.xY, eps) &&    \
            MTH_M_bEqualWithEpsilon( (MatA)->stCol_0.xZ, (MatB)->stCol_0.xZ, eps) &&    \
            MTH_M_bEqualWithEpsilon( (MatA)->stCol_1.xX, (MatB)->stCol_1.xX, eps) &&    \
            MTH_M_bEqualWithEpsilon( (MatA)->stCol_1.xY, (MatB)->stCol_1.xY, eps) &&    \
            MTH_M_bEqualWithEpsilon( (MatA)->stCol_1.xZ, (MatB)->stCol_1.xZ, eps) &&    \
            MTH_M_bEqualWithEpsilon( (MatA)->stCol_2.xX, (MatB)->stCol_2.xX, eps) &&    \
            MTH_M_bEqualWithEpsilon( (MatA)->stCol_2.xY, (MatB)->stCol_2.xY, eps) &&    \
            MTH_M_bEqualWithEpsilon( (MatA)->stCol_2.xZ, (MatB)->stCol_2.xZ, eps)       \
            )
     
 
/* ##M==================================================================================
NAME :          MTH3D_M_vFillMatrix
DESCRIPTION :   Fill each matrix element with "a" value
INPUT :         MatDest : address of MTH3D_tdstMatrix
                a       : MTH_tdxReal
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS)
/* avoid recomputation of a*/
#define MTH3D_M_vFillMatrix(MatDest, b)																 \
    {		register MTH_tdxReal a=(b);															 \
            (MatDest)->stCol_0.xX = (a); (MatDest)->stCol_0.xY = (a); (MatDest)->stCol_0.xZ = (a);   \
            (MatDest)->stCol_1.xX = (a); (MatDest)->stCol_1.xY = (a); (MatDest)->stCol_1.xZ = (a);   \
            (MatDest)->stCol_2.xX = (a); (MatDest)->stCol_2.xY = (a); (MatDest)->stCol_2.xZ = (a);   \
    }
#else
#define MTH3D_M_vFillMatrix(MatDest, a)																 \
    {       (MatDest)->stCol_0.xX = (a); (MatDest)->stCol_0.xY = (a); (MatDest)->stCol_0.xZ = (a);   \
            (MatDest)->stCol_1.xX = (a); (MatDest)->stCol_1.xY = (a); (MatDest)->stCol_1.xZ = (a);   \
			(MatDest)->stCol_2.xX = (a); (MatDest)->stCol_2.xY = (a); (MatDest)->stCol_2.xZ = (a);   }
#endif
 
/* ##M==================================================================================
NAME :          MTH3D_M_xDetMatrix
DESCRIPTION :   Return the determinant of a matrix
INPUT :         MatA     : address of MTH3D_tdstMatrix
OUTPUT :        det MatA : MTH_tdxReal
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS)
	#if defined(OPTIMIZED_FOR_PC_FLOATS_WITH_ASM)
		#define MTH3D_M_xDetMatrix(MatA)				MTH3D_M_xDetMatrixASM(MatA)
	#else
		#define MTH3D_M_xDetMatrix(MatA)				MTH3D_M_xDetMatrixC(MatA)
	#endif 
#else
	#define MTH3D_M_xDetMatrix(MatA)					MTH3D_M_xDetMatrixORG(MatA)
#endif
 
/* ##M==================================================================================
NAME :          MTH3D_M_vComMatrixWithoutBuffer
DESCRIPTION :   Calculate the Cofactor Matrix of a matrix : MatDest= Cofactor Matrix of MatA
INPUT :         Matdest, MatA : address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
 
#if defined(OPTIMIZED_FOR_PC_FLOATS)
/* avoid 4 MTH_M_xNeg : 8 clocks*/
#define MTH3D_M_vComMatrixWithoutBuffer(MatDest, MatA)                                                                                         \
    {       (MatDest)->stCol_0.xX= MTH_M_xMulSubMul((MatA)->stCol_1.xY,(MatA)->stCol_2.xZ,(MatA)->stCol_1.xZ,(MatA)->stCol_2.xY);              \
			(MatDest)->stCol_0.xY= MTH_M_xMulSubMul((MatA)->stCol_1.xZ,(MatA)->stCol_2.xX,(MatA)->stCol_1.xX,(MatA)->stCol_2.xZ);			   \
			(MatDest)->stCol_0.xZ= MTH_M_xMulSubMul((MatA)->stCol_1.xX,(MatA)->stCol_2.xY,(MatA)->stCol_1.xY,(MatA)->stCol_2.xX);              \
			(MatDest)->stCol_1.xX= MTH_M_xMulSubMul((MatA)->stCol_0.xZ,(MatA)->stCol_2.xY,(MatA)->stCol_0.xY,(MatA)->stCol_2.xZ);			   \
			(MatDest)->stCol_1.xY= MTH_M_xMulSubMul((MatA)->stCol_0.xX,(MatA)->stCol_2.xZ,(MatA)->stCol_0.xZ,(MatA)->stCol_2.xX);              \
		    (MatDest)->stCol_1.xZ= MTH_M_xMulSubMul((MatA)->stCol_0.xY,(MatA)->stCol_2.xX,(MatA)->stCol_0.xX,(MatA)->stCol_2.xY);			   \
			(MatDest)->stCol_2.xX= MTH_M_xMulSubMul((MatA)->stCol_0.xY,(MatA)->stCol_1.xZ,(MatA)->stCol_0.xZ,(MatA)->stCol_1.xY);              \
            (MatDest)->stCol_2.xY= MTH_M_xMulSubMul((MatA)->stCol_0.xZ,(MatA)->stCol_1.xX,(MatA)->stCol_0.xX,(MatA)->stCol_1.xZ);			   \
			(MatDest)->stCol_2.xZ= MTH_M_xMulSubMul((MatA)->stCol_0.xX,(MatA)->stCol_1.xY,(MatA)->stCol_0.xY,(MatA)->stCol_1.xX); }
#else
#define MTH3D_M_vComMatrixWithoutBuffer(MatDest, MatA)                                                                                         \
    {       (MatDest)->stCol_0.xX= MTH_M_xMulSubMul((MatA)->stCol_1.xY,(MatA)->stCol_2.xZ,(MatA)->stCol_1.xZ,(MatA)->stCol_2.xY);              \
            (MatDest)->stCol_0.xY= MTH_M_xNeg( MTH_M_xMulSubMul((MatA)->stCol_1.xX,(MatA)->stCol_2.xZ,(MatA)->stCol_1.xZ,(MatA)->stCol_2.xX)); \
            (MatDest)->stCol_0.xZ= MTH_M_xMulSubMul((MatA)->stCol_1.xX,(MatA)->stCol_2.xY,(MatA)->stCol_1.xY,(MatA)->stCol_2.xX);              \
            (MatDest)->stCol_1.xX= MTH_M_xNeg(MTH_M_xMulSubMul((MatA)->stCol_0.xY,(MatA)->stCol_2.xZ,(MatA)->stCol_0.xZ,(MatA)->stCol_2.xY));  \
            (MatDest)->stCol_1.xY= MTH_M_xMulSubMul((MatA)->stCol_0.xX,(MatA)->stCol_2.xZ,(MatA)->stCol_0.xZ,(MatA)->stCol_2.xX);              \
            (MatDest)->stCol_1.xZ= MTH_M_xNeg(MTH_M_xMulSubMul((MatA)->stCol_0.xX,(MatA)->stCol_2.xY,(MatA)->stCol_0.xY,(MatA)->stCol_2.xX));  \
            (MatDest)->stCol_2.xX= MTH_M_xMulSubMul((MatA)->stCol_0.xY,(MatA)->stCol_1.xZ,(MatA)->stCol_0.xZ,(MatA)->stCol_1.xY);              \
            (MatDest)->stCol_2.xY= MTH_M_xNeg( MTH_M_xMulSubMul((MatA)->stCol_0.xX,(MatA)->stCol_1.xZ,(MatA)->stCol_0.xZ,(MatA)->stCol_1.xX)); \
            (MatDest)->stCol_2.xZ= MTH_M_xMulSubMul((MatA)->stCol_0.xX,(MatA)->stCol_1.xY,(MatA)->stCol_0.xY,(MatA)->stCol_1.xX); }
#endif
 
/* the same but already transposed*/
#if defined(OPTIMIZED_FOR_PC_FLOATS)
/* avoid 4 MTH_M_xNeg : 8 clocks*/
#define MTH3D_M_vTransComMatrixWithoutBuffer(MatDest, MatA)                                                                                    \
    {       (MatDest)->stCol_0.xX= MTH_M_xMulSubMul((MatA)->stCol_1.xY,(MatA)->stCol_2.xZ,(MatA)->stCol_1.xZ,(MatA)->stCol_2.xY);              \
			(MatDest)->stCol_0.xY= MTH_M_xMulSubMul((MatA)->stCol_0.xZ,(MatA)->stCol_2.xY,(MatA)->stCol_0.xY,(MatA)->stCol_2.xZ);			   \
			(MatDest)->stCol_0.xZ= MTH_M_xMulSubMul((MatA)->stCol_0.xY,(MatA)->stCol_1.xZ,(MatA)->stCol_0.xZ,(MatA)->stCol_1.xY);              \
			(MatDest)->stCol_1.xX= MTH_M_xMulSubMul((MatA)->stCol_1.xZ,(MatA)->stCol_2.xX,(MatA)->stCol_1.xX,(MatA)->stCol_2.xZ);			   \
			(MatDest)->stCol_1.xY= MTH_M_xMulSubMul((MatA)->stCol_0.xX,(MatA)->stCol_2.xZ,(MatA)->stCol_0.xZ,(MatA)->stCol_2.xX);              \
            (MatDest)->stCol_1.xZ= MTH_M_xMulSubMul((MatA)->stCol_0.xZ,(MatA)->stCol_1.xX,(MatA)->stCol_0.xX,(MatA)->stCol_1.xZ);			   \
			(MatDest)->stCol_2.xX= MTH_M_xMulSubMul((MatA)->stCol_1.xX,(MatA)->stCol_2.xY,(MatA)->stCol_1.xY,(MatA)->stCol_2.xX);              \
		    (MatDest)->stCol_2.xY= MTH_M_xMulSubMul((MatA)->stCol_0.xY,(MatA)->stCol_2.xX,(MatA)->stCol_0.xX,(MatA)->stCol_2.xY);			   \
			(MatDest)->stCol_2.xZ= MTH_M_xMulSubMul((MatA)->stCol_0.xX,(MatA)->stCol_1.xY,(MatA)->stCol_0.xY,(MatA)->stCol_1.xX); }
#else
#define MTH3D_M_vTransComMatrixWithoutBuffer(MatDest, MatA)                                                                                    \
    {       (MatDest)->stCol_0.xX= MTH_M_xMulSubMul((MatA)->stCol_1.xY,(MatA)->stCol_2.xZ,(MatA)->stCol_1.xZ,(MatA)->stCol_2.xY);              \
            (MatDest)->stCol_1.xX= MTH_M_xNeg( MTH_M_xMulSubMul((MatA)->stCol_1.xX,(MatA)->stCol_2.xZ,(MatA)->stCol_1.xZ,(MatA)->stCol_2.xX)); \
            (MatDest)->stCol_2.xX= MTH_M_xMulSubMul((MatA)->stCol_1.xX,(MatA)->stCol_2.xY,(MatA)->stCol_1.xY,(MatA)->stCol_2.xX);              \
            (MatDest)->stCol_0.xY= MTH_M_xNeg(MTH_M_xMulSubMul((MatA)->stCol_0.xY,(MatA)->stCol_2.xZ,(MatA)->stCol_0.xZ,(MatA)->stCol_2.xY));  \
            (MatDest)->stCol_1.xY= MTH_M_xMulSubMul((MatA)->stCol_0.xX,(MatA)->stCol_2.xZ,(MatA)->stCol_0.xZ,(MatA)->stCol_2.xX);              \
            (MatDest)->stCol_2.xY= MTH_M_xNeg(MTH_M_xMulSubMul((MatA)->stCol_0.xX,(MatA)->stCol_2.xY,(MatA)->stCol_0.xY,(MatA)->stCol_2.xX));  \
            (MatDest)->stCol_0.xZ= MTH_M_xMulSubMul((MatA)->stCol_0.xY,(MatA)->stCol_1.xZ,(MatA)->stCol_0.xZ,(MatA)->stCol_1.xY);              \
            (MatDest)->stCol_1.xZ= MTH_M_xNeg( MTH_M_xMulSubMul((MatA)->stCol_0.xX,(MatA)->stCol_1.xZ,(MatA)->stCol_0.xZ,(MatA)->stCol_1.xX)); \
            (MatDest)->stCol_2.xZ= MTH_M_xMulSubMul((MatA)->stCol_0.xX,(MatA)->stCol_1.xY,(MatA)->stCol_0.xY,(MatA)->stCol_1.xX); }
#endif
 
#define MTH3D_M_vTranspComMatrixWithoutBuffer(MatDest, MatA)   MTH3D_M_vTransComMatrixWithoutBuffer(MatDest, MatA)                                                                                      \
 
 
/* ##M==================================================================================
NAME :          MTH3D_M_vInverMatrix
DESCRIPTION :   Invert a matrix : MatDest= Inv MatA
INPUT :         Matdest, MatA : address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS)
	#if defined(OPTIMIZED_FOR_PC_FLOATS_WITH_ASM)
		#define MTH3D_M_vInverMatrix(MatDest, MatA)		MTH3D_M_vInverMatrixASM(MatDest, MatA)   
	#else
		#define MTH3D_M_vInverMatrix(MatDest, MatA)		MTH3D_M_vInverMatrixC(MatDest, MatA)   
	#endif
#else
	#define MTH3D_M_vInverMatrix(MatDest, MatA)			MTH3D_M_vInverMatrixORG(MatDest, MatA) 
#endif
 
 
/* ##M==================================================================================
NAME :          MTH3D_M_vGetMatrixColumnElements
DESCRIPTION :   Get x, y, z column col values in MatA
INPUT :         x, y, z : MTH_tdxReal
                col     : int
                MatA : address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vGetMatrixColumnElements( Vx, Vy, Vz, col, MatA)                            \
      if( (col)==0 )                                                                        \
        { *Vx= (MatA)->stCol_0.xX; *Vy= (MatA)->stCol_0.xY; *Vz= (MatA)->stCol_0.xZ; }      \
      else                                                                                  \
        if( (col)==1 )                                                                      \
          { *Vx= (MatA)->stCol_1.xX; *Vy= (MatA)->stCol_1.xY; *Vz= (MatA)->stCol_1.xZ;  }   \
        else                                                                                \
          { *Vx= (MatA)->stCol_2.xX; *Vy= (MatA)->stCol_2.xY; *Vz= (MatA)->stCol_2.xZ;  }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSetMatrixColumnElements
DESCRIPTION :   Set column col x, y, z values in MatDest
INPUT :         MatDest : address of MTH3D_tdstMatrix
                x, y, z : MTH_tdxReal
                col : int
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vSetMatrixColumnElements( MatDest, Vx, Vy, Vz, col)                                   \
      if( (col)==0 )                                                                                  \
        {(MatDest)->stCol_0.xX= (Vx); (MatDest)->stCol_0.xY= (Vy); (MatDest)->stCol_0.xZ= (Vz); }     \
      else                                                                                            \
        if( (col)==1 )                                                                                \
         {(MatDest)->stCol_1.xX= (Vx); (MatDest)->stCol_1.xY= (Vy); (MatDest)->stCol_1.xZ= (Vz); }    \
        else                                                                                          \
         {(MatDest)->stCol_2.xX= (Vx); (MatDest)->stCol_2.xY= (Vy); (MatDest)->stCol_2.xZ= (Vz); }
 
/* ##M==================================================================================
NAME :          MTH3D_M_xGetMatrixElement
DESCRIPTION :   Return element at (lin, col) in MatASet
INPUT :         MatA : address of MTH3D_tdstMatrix
                lin, col : int
OUTPUT :        a : MTH_tdxReal
=======================================================================================*/
#define MTH3D_M_xGetMatrixElement( lin, col, MatA)                                                                        \
      ( (col)==0 ) ?                                                                                                      \
      (/* col 0 : */( (lin)==0 ) ? (MatA)->stCol_0.xX : ( ( (lin)==1 ) ? (MatA)->stCol_0.xY : (MatA)->stCol_0.xZ ) ) :    \
      (                                                                                                                   \
       ( (col)==1 ) ?                                                                                                     \
         (/* col 1 : */( (lin)==0 ) ? (MatA)->stCol_1.xX : ( ( (lin)==1 ) ? (MatA)->stCol_1.xY : (MatA)->stCol_1.xZ ) ) : \
         (/* col 2 : */( (lin)==0 ) ? (MatA)->stCol_2.xX : ( ( (lin)==1 ) ? (MatA)->stCol_2.xY : (MatA)->stCol_2.xZ ) )   \
      )
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSetMatrixElement
DESCRIPTION :   Set a element in MatDest at (lin, col)
INPUT :         MatDest : address of MTH3D_tdstMatrix
                a : MTH_tdxReal
                lin, col : int
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vSetMatrixElement( MatDest, a, lin, col)                                                                  \
 if( (col)==0 )                                                                                                           \
 { if((lin)==0){(MatDest)->stCol_0.xX=(a);}else if((lin)==1){(MatDest)->stCol_0.xY=(a);}else{(MatDest)->stCol_0.xZ=(a);}} \
 else                                                                                                                     \
  if( (col)==1)                                                                                                           \
 { if((lin)==0){(MatDest)->stCol_1.xX=(a);}else if((lin)==1){(MatDest)->stCol_1.xY=(a);}else{(MatDest)->stCol_1.xZ=(a);}} \
  else                                                                                                                    \
 { if((lin)==0){(MatDest)->stCol_2.xX=(a);}else if((lin)==1){(MatDest)->stCol_2.xY=(a);}else{(MatDest)->stCol_2.xZ=(a);}}
 
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSetMatrixCol0Elements
DESCRIPTION :   Set  x, y, z values of column 0 in MatDest
INPUT :         MatDest : address of MTH3D_tdstMatrix
                Vx, Vy, Vz : MTH_tdxReal
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vSetMatrixCol0Elements( MatDest, Vx, Vy, Vz)                                    \
            {(MatDest)->stCol_0.xX= (Vx); (MatDest)->stCol_0.xY= (Vy); (MatDest)->stCol_0.xZ= (Vz); }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSetMatrixCol1Elements
DESCRIPTION :   Set  x, y, z values of column 1 in MatDest
INPUT :         MatDest : address of MTH3D_tdstMatrix
                Vx, Vy, Vz : MTH_tdxReal
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vSetMatrixCol1Elements( MatDest, Vx, Vy, Vz)                                    \
            {(MatDest)->stCol_1.xX= (Vx); (MatDest)->stCol_1.xY= (Vy); (MatDest)->stCol_1.xZ= (Vz); }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSetMatrixCol2Elements
DESCRIPTION :   Set  x, y, z values of column 2 in MatDest
INPUT :         MatDest : address of MTH3D_tdstMatrix
                Vx, Vy, Vz : MTH_tdxReal
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vSetMatrixCol2Elements( MatDest, Vx, Vy, Vz)                                    \
            {(MatDest)->stCol_2.xX= (Vx); (MatDest)->stCol_2.xY= (Vy); (MatDest)->stCol_2.xZ= (Vz); }
 
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSetMatrixLineXElements
DESCRIPTION :   Set  x elements of all columns in MatDest
INPUT :         MatDest : address of MTH3D_tdstMatrix
                V0, V0, V0 : MTH_tdxReal
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vSetMatrixLineXElements( MatDest, V0, V1, V2)                                   \
            {(MatDest)->stCol_0.xX= (V0); (MatDest)->stCol_1.xX= (V1); (MatDest)->stCol_2.xX= (V2); }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSetMatrixLineYElements
DESCRIPTION :   Set  y elements of all columns in MatDest
INPUT :         MatDest : address of MTH3D_tdstMatrix
                V0, V0, V0 : MTH_tdxReal
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vSetMatrixLineYElements( MatDest, V0, V1, V2)                                   \
            {(MatDest)->stCol_0.xY= (V0); (MatDest)->stCol_1.xY= (V1); (MatDest)->stCol_2.xY= (V2); }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSetMatrixLineZElements
DESCRIPTION :   Set  z elements of all columns in MatDest
INPUT :         MatDest : address of MTH3D_tdstMatrix
                V0, V0, V0 : MTH_tdxReal
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vSetMatrixLineZElements( MatDest, V0, V1, V2)                                   \
            {(MatDest)->stCol_0.xZ= (V0); (MatDest)->stCol_1.xZ= (V1); (MatDest)->stCol_2.xZ= (V2); }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vGetMatrixCol0Elements
DESCRIPTION :   Get  x, y, z values of column 0 in MatA
                Vx, Vy, Vz : MTH_tdxReal
INPUT :         MatA : address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vGetMatrixCol0Elements( Vx, Vy, Vz, MatA)                                       \
            {Vx= (MatA)->stCol_0.xX; Vy= (MatA)->stCol_0.xY; Vz= (MatA)->stCol_0.xZ; }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vGetMatrixCol1Elements
DESCRIPTION :   Get  x, y, z values of column 1 in MatA
                Vx, Vy, Vz : MTH_tdxReal
INPUT :         MatA : address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vGetMatrixCol1Elements( Vx, Vy, Vz, MatA)                                       \
            {Vx= (MatA)->stCol_1.xX; Vy= (MatA)->stCol_1.xY; Vz= (MatA)->stCol_1.xZ; }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vGetMatrixCol2Elements
DESCRIPTION :   Get  x, y, z values of column 2 in MatA
                Vx, Vy, Vz : MTH_tdxReal
INPUT :         MatA : address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vGetMatrixCol2Elements( Vx, Vy, Vz, MatA)                                       \
            {Vx= (MatA)->stCol_2.xX; Vy= (MatA)->stCol_2.xY; Vz= (MatA)->stCol_2.xZ; }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vGetMatrixLineXElements
DESCRIPTION :   Get  x elements of all columns in MatA
                V0, V0, V0 : MTH_tdxReal
INPUT :         MatA : address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vGetMatrixLineXElements( V0, V1, V2, MatA)                                      \
            {V0= (MatA)->stCol_0.xX; V1= (MatA)->stCol_1.xX; V2= (MatA)->stCol_2.xX; }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vGetMatrixLineYElements
DESCRIPTION :   Get  y elements of all columns in MatA
                V0, V0, V0 : MTH_tdxReal
INPUT :         MatA : address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vGetMatrixLineYElements( V0, V1, V2, MatA)                                      \
            {V0= (MatA)->stCol_0.xY; V1= (MatA)->stCol_1.xY; V2= (MatA)->stCol_2.xY; }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vGetMatrixLineZElements
DESCRIPTION :   Get  z elements of all columns in MatA
                V0, V0, V0 : MTH_tdxReal
INPUT :         MatA : address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vGetMatrixLineZElements( V0, V1, V2, MatA)                                      \
            {V0= (MatA)->stCol_0.xZ; V1= (MatA)->stCol_1.xZ; V2= (MatA)->stCol_2.xZ; }
 
 
 
/* ##-########################### 
   ## Matrix-Vector operations
   ############################## */   
 
 
/* ##M==================================================================================
NAME :          MTH3D_M_vMulMatrixVectorWithoutBuffer
DESCRIPTION :   Multiply a Matrix to a Vector : VectDest= MatA*VectA, VectDest must be
                a other vector
INPUT :         VectDest : address of MTH3D_tdstVector
                MatA : address of MTH3D_tdstMatrix
                VectA : address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS)
	#if defined(OPTIMIZED_FOR_PC_FLOATS_WITH_ASM)
		#define MTH3D_M_vMulMatrixVectorWithoutBuffer( VectDest, MatA, VectA)	MTH3D_M_vMulMatrixVectorWithoutBufferASM(VectDest, MatA, VectA) 
	#elif defined(OPTIMIZED_FOR_U64_ASM)
		#define MTH3D_M_vMulMatrixVectorWithoutBuffer( VectDest, MatA, VectA)	MTH3D_M_vMulMatrixVectorWithoutBufferU64ASM(VectDest, MatA, VectA) 
	#else
		#define MTH3D_M_vMulMatrixVectorWithoutBuffer( VectDest, MatA, VectA)	MTH3D_M_vMulMatrixVectorWithoutBufferC(VectDest, MatA, VectA) 
	#endif
#else
	#define MTH3D_M_vMulMatrixVectorWithoutBuffer( VectDest, MatA, VectA)		MTH3D_M_vMulMatrixVectorWithoutBufferORG(VectDest, MatA, VectA) 
#endif
 
/* ##M==================================================================================
NAME :          MTH3D_M_vMulMatrixVector
DESCRIPTION :   Multiply a Matrix to a Vector : VectDest= MatA*VectA
INPUT :         VectDest : address of MTH3D_tdstVector
                MatA : address of MTH3D_tdstMatrix
                VectA : address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#if defined(OPTIMIZED_FOR_PC_FLOATS)
	#if defined(OPTIMIZED_FOR_PC_FLOATS_WITH_ASM)
		#define MTH3D_M_vMulMatrixVector( VectDest, MatA, VectA)	MTH3D_M_vMulMatrixVectorASM(VectDest, MatA, VectA) 
	#elif defined(OPTIMIZED_FOR_U64_ASM)
		#define MTH3D_M_vMulMatrixVector( VectDest, MatA, VectA)	MTH3D_M_vMulMatrixVectorU64ASM(VectDest, MatA, VectA) 
	#else
		#define MTH3D_M_vMulMatrixVector( VectDest, MatA, VectA)	MTH3D_M_vMulMatrixVectorC(VectDest, MatA, VectA) 
	#endif
#else
	#define MTH3D_M_vMulMatrixVector( VectDest, MatA, VectA)		MTH3D_M_vMulMatrixVectorORG(VectDest, MatA, VectA) 
#endif
/* ##M==================================================================================
NAME :          MTH3D_M_vGetColumn0InMatrix
DESCRIPTION :   Get a Vector column of a Matrix to a Vector : VectDest= columm 0 of MatA
INPUT :         VectDest : address of MTH3D_tdstVector
                MatA : address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vGetColumn0InMatrix( VectDest, MatA)                       \
            { (VectDest)->xX=(MatA)->stCol_0.xX;                                \
              (VectDest)->xY=(MatA)->stCol_0.xY;                                \
              (VectDest)->xZ=(MatA)->stCol_0.xZ; }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vGetColumn1InMatrix
DESCRIPTION :   Get a Vector column of a Matrix to a Vector : VectDest= columm 1 of MatA
INPUT :         VectDest : address of MTH3D_tdstVector
                MatA : address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vGetColumn1InMatrix( VectDest, MatA)                       \
             { (VectDest)->xX=(MatA)->stCol_1.xX;                               \
               (VectDest)->xY=(MatA)->stCol_1.xY;                               \
               (VectDest)->xZ=(MatA)->stCol_1.xZ; }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vGetColumn2InMatrix
DESCRIPTION :   Get a Vector column of a Matrix to a Vector : VectDest= columm 2 of MatA
INPUT :         VectDest : address of MTH3D_tdstVector
                MatA : address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vGetColumn2InMatrix( VectDest, MatA)                       \
             { (VectDest)->xX=(MatA)->stCol_2.xX;                               \
               (VectDest)->xY=(MatA)->stCol_2.xY;                               \
               (VectDest)->xZ=(MatA)->stCol_2.xZ; }
 
          
/* ##M==================================================================================
NAME :          MTH3D_M_vGetColumnInMatrix
DESCRIPTION :   Get a Vector column of a Matrix to a Vector : VectDest= columm col of MatA
INPUT :         VectDest : address of MTH3D_tdstVector
                MatA : address of MTH3D_tdstMatrix
                col : int
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vGetColumnInMatrix( VectDest, MatA, col )                       \
            if( col==0 )                                                        \
            { (VectDest)->xX=(MatA)->stCol_0.xX;                                \
              (VectDest)->xY=(MatA)->stCol_0.xY;                                \
              (VectDest)->xZ=(MatA)->stCol_0.xZ; }                              \
            else                                                                \
             if( col==1 )                                                       \
             { (VectDest)->xX=(MatA)->stCol_1.xX;                               \
               (VectDest)->xY=(MatA)->stCol_1.xY;                               \
               (VectDest)->xZ=(MatA)->stCol_1.xZ; }                             \
             else                                                               \
             { (VectDest)->xX=(MatA)->stCol_2.xX;                               \
               (VectDest)->xY=(MatA)->stCol_2.xY;                               \
               (VectDest)->xZ=(MatA)->stCol_2.xZ; }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSetColumnInMatrix
DESCRIPTION :   Put a Vector to a column of a Matrix : Set columm col of MatDest with VectA
INPUT :         MatDest : address of MTH3D_tdstMatrix
                VectA : address of MTH3D_tdstVector
                col : int
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vSetColumnInMatrix( MatDest, VectA, col)                        \
            if( col==0 )                                                        \
            { (MatDest)->stCol_0.xX=(VectA)->xX;                                \
              (MatDest)->stCol_0.xY=(VectA)->xY;                                \
              (MatDest)->stCol_0.xZ=(VectA)->xZ; }                              \
            else                                                                \
             if( col==1 )                                                       \
             { (MatDest)->stCol_1.xX=(VectA)->xX;                               \
               (MatDest)->stCol_1.xY=(VectA)->xY;                               \
               (MatDest)->stCol_1.xZ=(VectA)->xZ; }                             \
             else                                                               \
             { (MatDest)->stCol_2.xX=(VectA)->xX;                               \
               (MatDest)->stCol_2.xY=(VectA)->xY;                               \
               (MatDest)->stCol_2.xZ=(VectA)->xZ; }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vGetLineInMatrix
DESCRIPTION :   Get a Vector line of a Matrix to a Vector : VectDest= line lin of MatA
INPUT :         VectDest : address of MTH3D_tdstVector
                MatA : address of MTH3D_tdstMatrix
                lin : int
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vGetLineInMatrix( VectDest, MatA, lin )                         \
            if( lin==0 )                                                        \
            { (VectDest)->xX=(MatA)->stCol_0.xX;                                \
              (VectDest)->xY=(MatA)->stCol_1.xX;                                \
              (VectDest)->xZ=(MatA)->stCol_2.xX; }                              \
            else                                                                \
             if( lin==1 )                                                       \
             { (VectDest)->xX=(MatA)->stCol_0.xY;                               \
               (VectDest)->xY=(MatA)->stCol_1.xY;                               \
               (VectDest)->xZ=(MatA)->stCol_2.xY; }                             \
             else                                                               \
             { (VectDest)->xX=(MatA)->stCol_0.xZ;                               \
               (VectDest)->xY=(MatA)->stCol_1.xZ;                               \
               (VectDest)->xZ=(MatA)->stCol_2.xZ; }
 
 
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSetLineInMatrix
DESCRIPTION :   Put a Vector to a line of a Matrix : Set line lin of MatDest with VectA
INPUT :         MatDest : address of MTH3D_tdstMatrix
                VectA : address of MTH3D_tdstVector
                lin : int
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vSetLineInMatrix( MatDest, VectA, lin)                          \
            if( lin==0 )                                                        \
            { (MatDest)->stCol_0.xX=(VectA)->xX;                                \
              (MatDest)->stCol_1.xX=(VectA)->xY;                                \
              (MatDest)->stCol_2.xX=(VectA)->xZ; }                              \
            else                                                                \
             if( lin==1 )                                                       \
             { (MatDest)->stCol_0.xY=(VectA)->xX;                               \
               (MatDest)->stCol_1.xY=(VectA)->xY;                               \
               (MatDest)->stCol_2.xY=(VectA)->xZ; }                             \
             else                                                               \
             { (MatDest)->stCol_0.xZ=(VectA)->xX;                               \
               (MatDest)->stCol_1.xZ=(VectA)->xY;                               \
               (MatDest)->stCol_2.xZ=(VectA)->xZ; }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vGetDiagInMatrix
DESCRIPTION :   Get a Vector diagonal of a Matrix to a Vector : VectDest= diagonal of MatA
INPUT :         VectDest : address of MTH3D_tdstVector
                MatA : address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vGetDiagInMatrix( VectDest, MatA)                               \
        {               (VectDest)->xX= (MatA)->stCol_0.xX;                     \
                        (VectDest)->xY= (MatA)->stCol_1.xY;                     \
                        (VectDest)->xZ= (MatA)->stCol_2.xZ; }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSetDiagInMatrix
DESCRIPTION :   Put a Vector to a diagonal of a Matrix : Set diagonal of MatDest with VectA
INPUT :         MatDest : address of MTH3D_tdstMatrix
                VectA : address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vSetDiagInMatrix( MatDest, VectA)                               \
        {               (MatDest)->stCol_0.xX= (VectA)->xX;                     \
                        (MatDest)->stCol_1.xY= (VectA)->xY;                     \
                        (MatDest)->stCol_2.xZ= (VectA)->xZ; }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vGetVectorsInMatrix
DESCRIPTION :   Get all column Matrix to two Vectors
INPUT :         VaDest, VbDest, VcDest: address of MTH3D_tdstVector
                MatA : address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vGetVectorsInMatrix( VaDest, VbDest, VcDest, MatA)                      \
   {          (VaDest)->xX=(MatA)->stCol_0.xX;                                          \
              (VaDest)->xY=(MatA)->stCol_0.xY;                                          \
              (VaDest)->xZ=(MatA)->stCol_0.xZ;                                          \
              (VbDest)->xX=(MatA)->stCol_1.xX;                                          \
              (VbDest)->xY=(MatA)->stCol_1.xY;                                          \
              (VbDest)->xZ=(MatA)->stCol_1.xZ;                                          \
              (VcDest)->xX=(MatA)->stCol_2.xX;                                          \
              (VcDest)->xY=(MatA)->stCol_2.xY;                                          \
              (VcDest)->xZ=(MatA)->stCol_2.xZ; }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vSetVectorsInMatrix
DESCRIPTION :   Set all column Matrix with two Vectors
INPUT :         MatDest : address of MTH3D_tdstMatrix
                VectA, VectB, VectC : address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vSetVectorsInMatrix( MatDest, VectA, VectB, VectC)              \
  {          (MatDest)->stCol_0.xX=(VectA)->xX;                                 \
             (MatDest)->stCol_0.xY=(VectA)->xY;                                 \
             (MatDest)->stCol_0.xZ=(VectA)->xZ;                                 \
             (MatDest)->stCol_1.xX=(VectB)->xX;                                 \
             (MatDest)->stCol_1.xY=(VectB)->xY;                                 \
             (MatDest)->stCol_1.xZ=(VectB)->xZ;                                 \
             (MatDest)->stCol_2.xX=(VectC)->xX;                                 \
             (MatDest)->stCol_2.xY=(VectC)->xY;                                 \
             (MatDest)->stCol_2.xZ=(VectC)->xZ; }
 
 
/* ##M==================================================================================
NAME :          MTH3D_M_vPrintfVector
DESCRIPTION :   Print a Vector : Name + its values
INPUT :         Name : string
                VectA : address of MTH3D_tdstVector
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vPrintfVector( Name, VectA)                                     \
        {   printf("%s = \n |%e", (Name), (VectA)->xX);                         \
            printf("\n |%e", (VectA)->xY);                                      \
            printf("\n |%e\n", (VectA)->xZ); }
 
/* ##M==================================================================================
NAME :          MTH3D_M_vPrintfMatrix
DESCRIPTION :   Print a Matrix : Name + its values
INPUT :         Name : string
                MatA : address of MTH3D_tdstMatrix
OUTPUT :        void
=======================================================================================*/
#define MTH3D_M_vPrintfMatrix( Name, MatA)                                                                      \
        {   printf("%s = \n |%e %e %e|", (Name), (MatA)->stCol_0.xX, (MatA)->stCol_1.xX, (MatA)->stCol_2.xX);   \
            printf("\n |%e %e %e|", (MatA)->stCol_0.xY, (MatA)->stCol_1.xY, (MatA)->stCol_2.xY );               \
            printf("\n |%e %e %e|\n", (MatA)->stCol_0.xZ, (MatA)->stCol_1.xZ, (MatA)->stCol_2.xZ ); }
 
#define MTH3D_M_vPrintfReal( Name, RealA)                                     \
	{   printf("%s = \n %e\n", (Name), (RealA) ); }                         
 
 
#if defined(OPTIMIZED_FOR_PC_FLOATS)
	#if defined(OPTIMIZED_FOR_PC_FLOATS_WITH_ASM)
		#define MTH3D_M_vTransformVectorWithoutBuffer( VectDest, MatA, VectA, VectB)	MTH3D_M_vTransformVectorWithoutBufferASM(VectDest, MatA, VectA, VectB) 
	#elif defined(OPTIMIZED_FOR_U64_ASM)
		#define MTH3D_M_vTransformVectorWithoutBuffer( VectDest, MatA, VectA, VectB)	MTH3D_M_vTransformVectorWithoutBufferU64ASM(VectDest, MatA, VectA, VectB) 
	#else
		#define MTH3D_M_vTransformVectorWithoutBuffer( VectDest, MatA, VectA, VectB)	MTH3D_M_vTransformVectorWithoutBufferC(VectDest, MatA, VectA, VectB) 
	#endif
#else
	#define MTH3D_M_vTransformVectorWithoutBuffer( VectDest, MatA, VectA, VectB)		MTH3D_M_vTransformVectorWithoutBufferORG(VectDest, MatA, VectA, VectB) 
#endif
 
 
#include "MTH3dopt.h"
 
#endif /*  MTH3D_H */
