#if !defined(LD_CORE_MATH_H_)
#define LD_CORE_MATH_H_

#define PI_F32  (3.14159265358979323846264338f)
#define TAU_F32 (2.0f * PI_F32)

#define Abs(x) (((x) < 0 ? -(x) : (x)))

typedef struct Random Random;
struct Random {
	U64 state;
};

typedef union V2f V2f;
union V2f {
	struct {
		F32 x, y;
	};

	struct {
		F32 u, v;
	};

	struct {
		F32 w, h;
	};

	F32 e[2];
};

typedef union V2i V2i;
union V2i {
	struct {
		U32 x, y;
	};

	struct {
		U32 w, h;
	};

	U32 e[2];
};

typedef union V3f V3f;
union V3f {
	struct {
		F32 x, y, z;
	};

	struct {
		F32 r, g, b;
	};

	struct {
		F32 w, h, d;
	};

	struct {
		V2f xy;
		F32 _z;
	};

	F32 e[3];
};

typedef union V4f V4f;
union V4f {
	struct {
		F32 x, y, z, w;
	};

	struct {
		F32 r, g, b, a;
	};

	struct {
		V3f xyz;
		F32 _w;
	};

	F32 e[4];
};

typedef union Mat4x4F Mat4x4F;
union Mat4x4F {
	F32 m[4][4];
	F32 e[16];
	V4f r[4];
};

typedef struct Mat4x4FInv Mat4x4FInv;
struct Mat4x4FInv {
	Mat4x4F fwd;
	Mat4x4F inv;
};

typedef struct R2f R2f;
struct R2f {
	V2f min;
	V2f max;
};

typedef struct R3f R3f;
struct R3f {
	V3f min;
	V3f max;
};

function V2f V2F(F32 x, F32 y);
function V3f V3F(F32 x, F32 y, F32 z);
function V4f V4F(F32 x, F32 y, F32 z, F32 w);

function R2f R2F(V2f min, V2f max);

function V2f V2f_Scale(V2f x, F32 s);

function V3f V3f_Neg(V3f x);
function V3f V3f_Scale(V3f x, F32 s);
function V3f V3f_Sub(V3f a, V3f b);

function F32 V3f_Dot(V3f a, V3f b);
function F32 V4f_Dot(V4f a, V4f b);

function Mat4x4F M4x4F_Rows(V3f x, V3f y, V3f z);
function Mat4x4F M4x4F_Columns(V3f x, V3f y, V3f z);

function V4f M4x4F_VMul4(Mat4x4F m, V4f v);
function V3f M4x4F_VMul3(Mat4x4F m, V3f v);

function Mat4x4FInv M4x4F_Perspective(F32 fov, F32 aspect, F32 nearp, F32 farp);
function Mat4x4FInv M4x4F_CameraView(V3f x, V3f y, V3f z, V3f p);

function V2f NormaliseV2F(V2f x);
function V2f V2f_Scale(V2f x, F32 scale);

// Random

function Random Random_Seed(U64 seed);

function U64 Random_Next(Random *rnd);

function F32 Random_F32(Random *rnd, F32 min, F32 max);
function F64 Random_F64(Random *rnd, F64 min, F64 max);

function U32 Random_U32(Random *rnd, U32 min, U32 max);

function F32 Random_Unilateral(Random *rnd);
function F32 Random_Bilateral(Random *rnd);

V2f V2f_Clip(V2f screen_xy, V2f screen_size);

#endif  // LD_CORE_MATH_H_
