/// matrix4d.h
///
/// (c) 2008 by Carsten Busse <carsten.busse@googlemail.com>
///             Bastian Spiegel <bs@tkscript.de> (additional coding)
///     - Distributed under terms of the Lesser GNU General Public License (LGPL).
///       See COPYING and <http://www.gnu.org/licenses/licenses.html#LGPL> for further information.
///
///

#ifndef __MATRIX4D_H_
#define __MATRIX4D_H_


YG("Math");


/* @class Matrix4d,Object
This class represents a double precision 4x4 square matrix.
 */
YC class _Matrix4d : public YAC_Object {
  public:
   sF64 doubles[16];

  public:
   _Matrix4d(void);
   ~_Matrix4d();
   YAC_POOLED(_Matrix4d,YAC_POOL_PRIORITY_HIGH);
   sUI YAC_VCALL yacArrayGetNumElements(void);
   sUI YAC_VCALL yacArrayGetMaxElements(void);
   sUI YAC_VCALL yacArrayGetElementType(void);
   sUI YAC_VCALL yacArrayGetElementByteSize(void);
   void YAC_VCALL yacArraySet(YAC_ContextHandle, sUI, YAC_Value *);
   void YAC_VCALL yacArrayGet(YAC_ContextHandle, sUI, YAC_Value *);
   void *YAC_VCALL yacArrayGetPointer(void);
   sUI YAC_VCALL yacArrayGetWidth(void);
   sUI YAC_VCALL yacArrayGetHeight(void);
   sUI YAC_VCALL yacArrayGetStride(void);
   sSI YAC_VCALL yacTensorRank(void);
   void YAC_VCALL yacSerialize(YAC_Object *, sUI);
   sUI YAC_VCALL yacDeserialize(YAC_Object *, sUI);
   void YAC_VCALL yacOperatorClamp(YAC_Object *, YAC_Object *);
   void YAC_VCALL yacOperatorWrap(YAC_Object *, YAC_Object *);
//YAC_OP_CEQ, YAC_OP_CNE, YAC_OP_ASSIGN, YAC_OP_ADD = _add,
//YAC_OP_SUB = _sub, YAC_OP_MUL = _mul, YAC_OP_NEG, YAC_OP_INIT
   void YAC_VCALL yacOperator(sSI, YAC_Object *, YAC_Value *);
   void YAC_VCALL yacOperatorI(sSI, sSI, YAC_Value *);
   void YAC_VCALL yacOperatorF32(sSI, sF32, YAC_Value *);
   void YAC_VCALL yacOperatorF64(sSI, sF64, YAC_Value *);
   sBool YAC_VCALL yacToString(YAC_String*);

   // Helper methods
   void assignFloats(sF32 *_fv, sUI _ne);
   void assignFloatArray(YAC_FloatArray *_fa);
   void assignGeneric(YAC_ContextHandle _ctx, YAC_Object *_o);

//element access methods

   /* @method setA,Double v
      Set a element to v
      @arg v new value for a
    */
   YM void _setA(YAC_Object *);
   /* @method setB,Double v
      Set b element to v
      @arg v new value for b
    */
   YM void _setB(YAC_Object *);
   /* @method setC,Double v
      Set c element to v
      @arg v new value for c
    */
   YM void _setC(YAC_Object *);
   /* @method setD,Double v
      Set d element to v
      @arg v new value for d
    */
   YM void _setD(YAC_Object *);
   /* @method setE,Double v
      Set e element to v
      @arg v new value for e
    */
   YM void _setE(YAC_Object *);
   /* @method setF,Double v
      Set f element to v
      @arg v new value for f
    */
   YM void _setF(YAC_Object *);
   /* @method setG,Double v
      Set g element to v
      @arg v new value for g
    */
   YM void _setG(YAC_Object *);
   /* @method setH,Double v
      Set h element to v
      @arg v new value for h
    */
   YM void _setH(YAC_Object *);
   /* @method setI,Double v
      Set i element to v
      @arg v new value for i
    */
   YM void _setI(YAC_Object *);
   /* @method setJ,Double v
      Set j element to v
      @arg v new value for j
    */
   YM void _setJ(YAC_Object *);
   /* @method setK,Double v
      Set k element to v
      @arg v new value for k
    */
   YM void _setK(YAC_Object *);
   /* @method setL,Double v
      Set l element to v
      @arg v new value for l
    */
   YM void _setL(YAC_Object *);
   /* @method setM,Double v
      Set m element to v
      @arg v new value for m
    */
   YM void _setM(YAC_Object *);
   /* @method setN,Double v
      Set n element to v
      @arg v new value for n
    */
   YM void _setN(YAC_Object *);
   /* @method setO,Double v
      Set o element to v
      @arg v new value for o
    */
   YM void _setO(YAC_Object *);
   /* @method setP,Double v
      Set p element to v
      @arg v new value for p
    */
   YM void _setP(YAC_Object *);


   /* @method getA:Double
      Get value of a element
      @return value of a element
    */
   YM void _getA_YAC_RVAL(YAC_Value *);
   YM void _getA_YAC_RARG(YAC_Object *);

   /* @method getB:Double
      Get value of b element
      @return value of b element
    */
   YM void _getB_YAC_RVAL(YAC_Value *);
   YM void _getB_YAC_RARG(YAC_Object *);
   /* @method getC:Double
      Get value of c element
      @return value of c element
    */
   YM void _getC_YAC_RVAL(YAC_Value *);
   YM void _getC_YAC_RARG(YAC_Object *);
   /* @method getD:Double
      Get value of d element
      @return value of d element
    */
   YM void _getD_YAC_RVAL(YAC_Value *);
   YM void _getD_YAC_RARG(YAC_Object *);
   /* @method getE:Double
      Get value of e element
      @return value of e element
    */
   YM void _getE_YAC_RVAL(YAC_Value *);
   YM void _getE_YAC_RARG(YAC_Object *);
   /* @method getF:Double
      Get value of f element
      @return value of f element
    */
   YM void _getF_YAC_RVAL(YAC_Value *);
   YM void _getF_YAC_RARG(YAC_Object *);
   /* @method getG:Double
      Get value of g element
      @return value of g element
    */
   YM void _getG_YAC_RVAL(YAC_Value *);
   YM void _getG_YAC_RARG(YAC_Object *);
   /* @method getH:Double
      Get value of h element
      @return value of h element
    */
   YM void _getH_YAC_RVAL(YAC_Value *);
   YM void _getH_YAC_RARG(YAC_Object *);
   /* @method getI:Double
      Get value of i element
      @return value of i element
    */
   YM void _getI_YAC_RVAL(YAC_Value *);
   YM void _getI_YAC_RARG(YAC_Object *);
   /* @method getJ:Double
      Get value of j element
      @return value of j element
    */
   YM void _getJ_YAC_RVAL(YAC_Value *);
   YM void _getJ_YAC_RARG(YAC_Object *);
   /* @method getK:Double
      Get value of k element
      @return value of k element
    */
   YM void _getK_YAC_RVAL(YAC_Value *);
   YM void _getK_YAC_RARG(YAC_Object *);
   /* @method getL:Double
      Get value of l element
      @return value of l element
    */
   YM void _getL_YAC_RVAL(YAC_Value *);
   YM void _getL_YAC_RARG(YAC_Object *);
   /* @method getM:Double
      Get value of m element
      @return value of m element
    */
   YM void _getM_YAC_RVAL(YAC_Value *);
   YM void _getM_YAC_RARG(YAC_Object *);
   /* @method getN:Double
      Get value of n element
      @return value of n element
    */
   YM void _getN_YAC_RVAL(YAC_Value *);
   YM void _getN_YAC_RARG(YAC_Object *);
   /* @method getO:Double
      Get value of o element
      @return value of o element
    */
   YM void _getO_YAC_RVAL(YAC_Value *);
   YM void _getO_YAC_RARG(YAC_Object *);
   /* @method getP:Double
      Get value of p element
      @return value of p element
    */
   YM void _getP_YAC_RVAL(YAC_Value *);
   YM void _getP_YAC_RARG(YAC_Object *);

//produce string representation
   /* @method getString:String
      Get string representation of matrix ((a, b, c, d), (e, f, g, h), (i, j, k, l), (m, n, o, p))
      @return string representation of matrix
    */
   YM void _getString(YAC_Value *);

//arithmetics
   /* @method add,Matrix4d m
      Add another matrix m to this instance
      @arg m matrix to add
    */
   YM void _add_YAC_RSELF(YAC_Object *);
   YM void _add_YAC_RVAL(YAC_Object *, YAC_Value *);
   YM void _add_YAC_RARG(YAC_Object *, YAC_Object *);

   /* @method sub,Matrix4d m
      Substract another matrix m from this instance
      @arg m matrix to substract
    */
   YM void _sub_YAC_RSELF(YAC_Object *);
   YM void _sub_YAC_RVAL(YAC_Object *, YAC_Value *);
   YM void _sub_YAC_RARG(YAC_Object *, YAC_Object *);

//multiply with scalar
   /* @method mulf,Double v
      Multiply this instance with scalar value v
      @arg v value to multiply
    */
   void muld(sF64);
   YM void _muld_YAC_RSELF(YAC_Object *);
   YM void _muld_YAC_RVAL(YAC_Object *, YAC_Value *);
   YM void _muld_YAC_RARG(YAC_Object *, YAC_Object *);

//matrix multiplication
   /* @method mul,Matrix4d m
      Multiply this instance with matrix m
      @arg m matrix to multiply
    */
   YM void _mul_YAC_RSELF(YAC_Object *);
   YM void _mul_YAC_RVAL(YAC_Object *, YAC_Value *);
   YM void _mul_YAC_RARG(YAC_Object *, YAC_Object *);

//multiply matrix with vector (result is a vector)
   /* @method mulv,Vector4d v:Vector4d
      Multiply this instance with a 4dim vector
      @arg v vector to multiply
      @return resulting vector
    */
   YM void _mulv_YAC_RVAL(YAC_Object *, YAC_Value *);
   YM void _mulv_YAC_RARG(YAC_Object *, YAC_Object *);

//get "absolute" value for matrix
   /* @method getAbs:Double
      Calculate the Hilbert-Schmidt norm of the matrix
      @return scalar matrix norm value
    */
   sF64 getAbs(void);
   YM void _getAbs_YAC_RVAL(YAC_Value *);
   YM void _getAbs_YAC_RARG(YAC_Object *);
   /* @method getAbsSqr:Double
      Calculate the squared Hilbert-Schmidt norm of the matrix
      @return scalar matrix norm value
    */
   sF64 getAbsSqr(void);
   YM void _getAbsSqr_YAC_RVAL(YAC_Value *);
   YM void _getAbsSqr_YAC_RARG(YAC_Object *);

//normalize matrix
   /* @method unit
      Normalise matrix with Hilbert-Schmidt norm
    */
   YM void _unit_YAC_RSELF(void); /* unit */
   YM void _unit_YAC_RVAL(YAC_Value *);
   YM void _unit_YAC_RARG(YAC_Object *);

//normalize and scale matrix
   /* @method unitScale,Double v
      Normalise matrix with Hilbert-Schmidt norm and multiply with v afterwards
      @arg v value to scale matrix
    */
   void unitScale(sF64);
   YM void _unitScale_YAC_RSELF(YAC_Object *);
   YM void _unitScale_YAC_RVAL(YAC_Object *, YAC_Value *);
   YM void _unitScale_YAC_RARG(YAC_Object *, YAC_Object *);

//get scalar determinabt
   /* @method det:Double
      Calculate determinant of matrix
      @return value of determinant
    */
   sF64 det(void);
   void _det_YAC_RVAL(YAC_Value *);
   void _det_YAC_RARG(YAC_Object *);
//invert matrix so the A*A^-1=E
   /* @method invert
      Calculate inversion of matrix, so that A*A<sup>-1</sup>=U
    */
   YM void _invert_YAC_RSELF(void);
   YM void _invert_YAC_RVAL(YAC_Value *);
   YM void _invert_YAC_RARG(YAC_Object *);

//   YM void _invert2_YAC_RSELF(void);
//   YM void _invert2_YAC_RVAL(YAC_Value *);
//   YM void _invert2_YAC_RARG(YAC_Object *);

//transpose matrix
   /* @method transpose
      Transpose matrix
    */
   YM void _transpose_YAC_RSELF(void);
   YM void _transpose_YAC_RVAL(YAC_Value *);
   YM void _transpose_YAC_RARG(YAC_Object *);

//access row and column vectors
   /* @method setRow,int r,Vector4d v
      Set row r with values from v
      @arg r row number
      @arg v Vector4d instance
    */
   YM void _setRow(sUI, YAC_Object*);
   /* @method getRow,int r:Vector4d
      Get row r values
      @arg r row number
      @return vector with values from row r
    */
   YM void _getRow_YAC_RVAL(sUI, YAC_Value*);
   YM void _getRow_YAC_RARG(sUI, YAC_Object*);
   /* @method setCol,int c,Vector4d v
      Set column c with values from v
      @arg c column number
      @arg v Vector4d instance
    */
   YM void _setCol(sUI, YAC_Object*);
   /* @method getCol,int c:Vector4d
      Get column c values
      @arg c column number
      @return vector with values from column c
    */
   YM void _getCol_YAC_RVAL(sUI, YAC_Value*);
   YM void _getCol_YAC_RARG(sUI, YAC_Object*);
//init matrix values
   /* @method initf,float va,float vb,float vc,float vd,float ve,float vf,float vg,float vh,float vi,float vj,float vk,float vl,float vm,float vn,float vo,float vp
      Initialise matrix
      @arg va value for a
      @arg vb value for b
      @arg vc value for c
      @arg vd value for d
      @arg ve value for e
      @arg vf value for f
      @arg vg value for g
      @arg vh value for h
      @arg vi value for i
      @arg vj value for j
      @arg vk value for k
      @arg vl value for l
      @arg vm value for m
      @arg vn value for n
      @arg vo value for o
      @arg vp value for p
    */
   YM void _initf(sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32);
   /* @method init,Double va,Double vb,Double vc,Double vd,Double ve,Double vf,Double vg,Double vh,Double vi,Double vj,Double vk,Double vl,Double vm,Double vn,Double vo,Double vp
      Initialise matrix
      @arg va value for a
      @arg vb value for b
      @arg vc value for c
      @arg vd value for d
      @arg ve value for e
      @arg vf value for f
      @arg vg value for g
      @arg vh value for h
      @arg vi value for i
      @arg vj value for j
      @arg vk value for k
      @arg vl value for l
      @arg vm value for m
      @arg vn value for n
      @arg vo value for o
      @arg vp value for p
    */
   YM void _init(YAC_Object *,YAC_Object *,YAC_Object *,YAC_Object *,YAC_Object *,YAC_Object *,YAC_Object *,YAC_Object *,YAC_Object *,YAC_Object *,YAC_Object *,YAC_Object *,YAC_Object *,YAC_Object *,YAC_Object *,YAC_Object *);
//row, x, y, z
   /* @method initRow,int r,Double va,Double vb,Double vc,Double vd
      Initialise row r of matrix
      @arg r row number
      @arg va value for first element
      @arg vb value for second element
      @arg vc value for third element
      @arg vd value for fourth element
    */
   YM void _initRow(sUI,YAC_Object *,YAC_Object *,YAC_Object *,YAC_Object *);
//col, x, y, z
   /* @method initCol,int c,Double va,Double vb,Double vc,Double vd
      Initialise column c of matrix
      @arg c column number
      @arg va value for first element
      @arg vb value for second element
      @arg vc value for third element
      @arg vd value for fourth element
    */
   YM void _initCol(sUI,YAC_Object *,YAC_Object *,YAC_Object *,YAC_Object *);
   /* @method initRowV,int r,Vector4d v
      Initialise row r of matrix
      @arg r row number
      @arg v vector with values
    */
   YM void _initRowV(sUI,YAC_Object*);
   /* @method initColV,int c,Vector4d v
      Initialise column c of matrix
      @arg c column number
      @arg v vector with values
    */
   YM void _initColV(sUI,YAC_Object*);
   

   /* @method initEulerXYX,Double a,Double b,Double c
      Initialise with euler roation matrix
      @arg a first rotation
      @arg b second rotation
      @arg c third rotation
    */
   YM void _initEulerXYX(YAC_Object *, YAC_Object *, YAC_Object *);
   /* @method initEulerXZX,Double a,Double b,Double c
      Initialise with euler roation matrix
      @arg a first rotation
      @arg b second rotation
      @arg c third rotation
    */
   YM void _initEulerXZX(YAC_Object *, YAC_Object *, YAC_Object *);
   /* @method initEulerYXY,Double a,Double b,Double c
      Initialise with euler roation matrix
      @arg a first rotation
      @arg b second rotation
      @arg c third rotation
    */
   YM void _initEulerYXY(YAC_Object *, YAC_Object *, YAC_Object *);
   /* @method initEulerYZY,Double a,Double b,Double c
      Initialise with euler roation matrix
      @arg a first rotation
      @arg b second rotation
      @arg c third rotation
    */
   YM void _initEulerYZY(YAC_Object *, YAC_Object *, YAC_Object *);
   /* @method initEulerZXZ,Double a,Double b,Double c
      Initialise with euler roation matrix
      @arg a first rotation
      @arg b second rotation
      @arg c third rotation
    */
   YM void _initEulerZXZ(YAC_Object *, YAC_Object *, YAC_Object *);
   /* @method initEulerZYZ,Double a,Double b,Double c
      Initialise with euler roation matrix
      @arg a first rotation
      @arg b second rotation
      @arg c third rotation
    */
   YM void _initEulerZYZ(YAC_Object *, YAC_Object *, YAC_Object *);
   /* @method initEulerXYZ,Double a,Double b,Double c
      Initialise with euler roation matrix
      @arg a first rotation
      @arg b second rotation
      @arg c third rotation
    */
   YM void _initEulerXYZ(YAC_Object *, YAC_Object *, YAC_Object *);
   /* @method initEulerXZY,Double a,Double b,Double c
      Initialise with euler roation matrix
      @arg a first rotation
      @arg b second rotation
      @arg c third rotation
    */
   YM void _initEulerXZY(YAC_Object *, YAC_Object *, YAC_Object *);
   /* @method initEulerYXZ,Double a,Double b,Double c
      Initialise with euler roation matrix
      @arg a first rotation
      @arg b second rotation
      @arg c third rotation
    */
   YM void _initEulerYXZ(YAC_Object *, YAC_Object *, YAC_Object *);
   /* @method initEulerYZX,Double a,Double b,Double c
      Initialise with euler roation matrix
      @arg a first rotation
      @arg b second rotation
      @arg c third rotation
    */
   YM void _initEulerYZX(YAC_Object *, YAC_Object *, YAC_Object *);
   /* @method initEulerZXY,Double a,Double b,Double c
      Initialise with euler roation matrix
      @arg a first rotation
      @arg b second rotation
      @arg c third rotation
    */
   YM void _initEulerZXY(YAC_Object *, YAC_Object *, YAC_Object *);
   /* @method initEulerZYX,Double a,Double b,Double c
      Initialise with euler roation matrix
      @arg a first rotation
      @arg b second rotation
      @arg c third rotation
    */
   YM void _initEulerZYX(YAC_Object *, YAC_Object *, YAC_Object *);

   /* @method New,Object o:Matrix4d
      Initialise from an array and return new instance of Matrix4d
      @arg o array with values
      @return new instance of Matrix4d
    */
   YM void _New(YAC_Object *, YAC_Value *);
//   YM void _New(sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,YAC_Value*);

   /* @method BuildPerspectiveMatrix4d,Double fov,Double aspect,Double zNear,Double zFar:Matrix4d
      Builds a perspective matrix
      @arg fov field of view in degrees
      @arg aspect aspect ratio
      @arg zNear zNear value
      @arg zFar zFar value
      @return generated matrix
    */
   YM void _BuildPerspectiveMatrix4d_YAC_RVAL(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Object *, YAC_Value*);
   YM void _BuildPerspectiveMatrix4d_YAC_RARG(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Object *, YAC_Object*);

   /* @method BuildLookAtMatrix4d,Vector3d eye,Vector3d center,Vector3d up:Matrix4d
      Build a look at matrix
      @arg eye eye direction vector
      @arg center center of camera vector
      @arg up vector for up direction
      @return generated matrix
    */
   YM void _BuildLookAtMatrix4d_YAC_RVAL(YAC_Object*, YAC_Object*, YAC_Object*, YAC_Value*);
   YM void _BuildLookAtMatrix4d_YAC_RARG(YAC_Object*, YAC_Object*, YAC_Object*, YAC_Object*);

   /* @method BuildRotateMatrix4d,Double angle,Vector3d axis:Matrix4d
      Build a rotation matrix
      @arg angle rotation angle
      @arg axis rotation axis
      @return generated matrix
    */
   YM void _BuildRotateMatrix4d_YAC_RVAL(YAC_Object *, YAC_Object*, YAC_Value*);
   YM void _BuildRotateMatrix4d_YAC_RARG(YAC_Object *, YAC_Object*, YAC_Object*);

   /* @method BuildTranslateMatrix4d,Vector3d move:Matrix4d
      Build a translation matrix
      @arg move movement vector
      @return generated matrix
    */
   YM void _BuildTranslateMatrix4d_YAC_RVAL(YAC_Object*, YAC_Value*);
   YM void _BuildTranslateMatrix4d_YAC_RARG(YAC_Object*, YAC_Object*);

   /* @method BuildEulerXZX4d,Double a,Double b,Double c:Matrix4d
      Build an euler rotation matrix with XZX convention
      @arg a first angle in radians
      @arg b second angle in radians
      @arg c third angle in radians
      @return generated matrix
    */
   YM void _BuildEulerXZX4d_YAC_RVAL(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Value*);
   YM void _BuildEulerXZX4d_YAC_RARG(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Object *);

   /* @method BuildEulerXYX4d,Double a,Double b,Double c:Matrix4d
      Build an euler rotation matrix with XYX convention
      @arg a first angle in radians
      @arg b second angle in radians
      @arg c third angle in radians
      @return generated matrix
    */
   YM void _BuildEulerXYX4d_YAC_RVAL(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Value*);
   YM void _BuildEulerXYX4d_YAC_RARG(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Object *);

   /* @method BuildEulerYXY4d,Double a,Double b,Double c:Matrix4d
      Build an euler rotation matrix with YXY convention
      @arg a first angle in radians
      @arg b second angle in radians
      @arg c third angle in radians
      @return generated matrix
    */
   YM void _BuildEulerYXY4d_YAC_RVAL(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Value*);
   YM void _BuildEulerYXY4d_YAC_RARG(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Object *);

   /* @method BuildEulerYZY4d,Double a,Double b,Double c:Matrix4d
      Build an euler rotation matrix with YZY convention
      @arg a first angle in radians
      @arg b second angle in radians
      @arg c third angle in radians
      @return generated matrix
    */
   YM void _BuildEulerYZY4d_YAC_RVAL(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Value*);
   YM void _BuildEulerYZY4d_YAC_RARG(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Object *);

   /* @method BuildEulerZYZ4d,Double a,Double b,Double c:Matrix4d
      Build an euler rotation matrix with ZYZ convention
      @arg a first angle in radians
      @arg b second angle in radians
      @arg c third angle in radians
      @return generated matrix
    */
   YM void _BuildEulerZYZ4d_YAC_RVAL(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Value*);
   YM void _BuildEulerZYZ4d_YAC_RARG(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Object *);

   /* @method BuildEulerZXZ4d,Double a,Double b,Double c:Matrix4d
      Build an euler rotation matrix with ZXZ convention
      @arg a first angle in radians
      @arg b second angle in radians
      @arg c third angle in radians
      @return generated matrix
    */
   YM void _BuildEulerZXZ4d_YAC_RVAL(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Value*);
   YM void _BuildEulerZXZ4d_YAC_RARG(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Object *);

   /* @method BuildEulerXZY4d,Double a,Double b,Double c:Matrix4d
      Build an euler rotation matrix with XZY convention
      @arg a first angle in radians
      @arg b second angle in radians
      @arg c third angle in radians
      @return generated matrix
    */
   YM void _BuildEulerXZY4d_YAC_RVAL(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Value*);
   YM void _BuildEulerXZY4d_YAC_RARG(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Object *);

   /* @method BuildEulerXYZ4d,Double a,Double b,Double c:Matrix4d
      Build an euler rotation matrix with XYZ convention
      @arg a first angle in radians
      @arg b second angle in radians
      @arg c third angle in radians
      @return generated matrix
    */
   YM void _BuildEulerXYZ4d_YAC_RVAL(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Value*);
   YM void _BuildEulerXYZ4d_YAC_RARG(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Object *);

   /* @method BuildEulerYXZ4d,Double a,Double b,Double c:Matrix4d
      Build an euler rotation matrix with YXZ convention
      @arg a first angle in radians
      @arg b second angle in radians
      @arg c third angle in radians
      @return generated matrix
    */
   YM void _BuildEulerYXZ4d_YAC_RVAL(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Value*);
   YM void _BuildEulerYXZ4d_YAC_RARG(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Object *);

   /* @method BuildEulerYZX4d,Double a,Double b,Double c:Matrix4d
      Build an euler rotation matrix with YZX convention
      @arg a first angle in radians
      @arg b second angle in radians
      @arg c third angle in radians
      @return generated matrix
    */
   YM void _BuildEulerYZX4d_YAC_RVAL(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Value*);
   YM void _BuildEulerYZX4d_YAC_RARG(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Object *);

   /* @method BuildEulerZYX4d,Double a,Double b,Double c:Matrix4d
      Build an euler rotation matrix with ZYX convention
      @arg a first angle in radians
      @arg b second angle in radians
      @arg c third angle in radians
      @return generated matrix
    */
   YM void _BuildEulerZYX4d_YAC_RVAL(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Value*);
   YM void _BuildEulerZYX4d_YAC_RARG(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Object *);

   /* @method BuildEulerZXY4d,Double a,Double b,Double c:Matrix4d
      Build an euler rotation matrix with ZXY convention
      @arg a first angle in radians
      @arg b second angle in radians
      @arg c third angle in radians
      @return generated matrix
    */
   YM void _BuildEulerZXY4d_YAC_RVAL(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Value*);
   YM void _BuildEulerZXY4d_YAC_RARG(YAC_Object *, YAC_Object *, YAC_Object *, YAC_Object *);

   /* @method initIdentity
      Initialize with identity matrix.
   */
   YM void _initIdentity(void);
};

//YF void YAC_CALL _matrix4d(sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,sF32,YAC_Value*);
   /* @function matrix4d,Object o:Matrix4d
      Initialise from an array and return new instance of Matrix4d
      @arg o array with values
      @return new instance of Matrix4d
    */
YF void YAC_CALL _matrix4d(YAC_Object *, YAC_Value *);


#endif
