#ifndef MATRIX_MATH_H
#define MATRIX_MATH_H

#include <GL/gl.h>

/**
 * !!! ALL matrices are in column major
 */

typedef GLfloat vec4[4];
typedef GLfloat vec3[3];
typedef GLfloat vec2[2];

typedef GLfloat mat4[16];
typedef GLfloat mat3[9];


extern void mat4Identity(mat4 mat);
extern void mat4Copy(mat4 src, mat4 dst);
extern void mat4Empty(mat4 mat);
extern void mat4Multiply(mat4 result, mat4 A, mat4 B);
extern void mat4Print(mat4 m);
extern void mat4Translate(mat4 out, mat4 in, vec3 v);
extern void mat4Scale(mat4 out, mat4 in, vec3 v);
extern void mat4RotateX(mat4 out, mat4 in, GLfloat a);
extern void mat4RotateY(mat4 out, mat4 in, GLfloat a);
extern void mat4RotateZ(mat4 out, mat4 in, GLfloat a);
extern void mat4BuildLookAt(mat4 out, vec3 eye, vec3 center, vec3 up);
extern void mat4BuildProjection(mat4 out, GLfloat r, GLfloat l, GLfloat t, GLfloat b, GLfloat n, GLfloat f);
extern void mat4BuildPerspective(mat4 out, GLfloat fovy, GLfloat aspect, GLfloat n, GLfloat f);
extern void mat4Interpolate(mat4 out, mat4 a, mat4 b, GLfloat f);
extern void mat4From3(mat4 out, mat3 in);
extern void mat4Inverse(mat4 m, mat4 out);

extern void vec3Subtract(vec3 out, vec3 a, vec3 b);
extern void vec3CrossProduct(vec3 out, vec3 a, vec3 b);
extern void vec3Normalise(vec3 out, vec3 in);
extern GLfloat vec3Length(vec3 in);
extern GLfloat vec3DotProduct(vec3 a, vec3 b);
extern void vec3Set(vec3 out, GLfloat x, GLfloat y, GLfloat z);
extern void vec3Multiply(vec3 out, vec3 in, GLfloat x);

extern void vec2Subtract(vec2 out, vec2 a, vec2 b);

extern void mat3Copy(mat3 src, mat3 dst);
extern void mat3Inverse(mat3 out, mat3 in);
extern GLfloat mat3Determinant(mat3 m);
extern void mat3MultiplyScalar(mat3 out, mat3 in, GLfloat x);
extern void mat3Adjoint(mat3 out, mat3 in);
extern void mat3Cofactor(mat3 out, mat3 in);
extern void mat3Minor(mat3 out, mat3 in);
extern void mat3Transpose(mat3 out, mat3 in);
extern void mat3From4(mat3 out, mat4 in);

#endif