#ifndef BASE_MATH_H
#define BASE_MATH_H

//////////////////////////
//~ Macros

#define floor_F32(f)        floorf(f)


//////////////////////////
//~ Vector types

//- 2-vectors
typedef union Vec2_S32 Vec2_S32;
union Vec2_S32
{
  struct
  {
    S32 x;
    S32 y;
  };
  S32 v[2];
};

typedef union Vec2_S64 Vec2_S64;
union Vec2_S64
{
  struct
  {
    S64 x;
    S64 y;
  };
  S64 v[2];
};

typedef union Vec2_F32 Vec2_F32;
union Vec2_F32
{
  struct
  {
    F32 x;
    F32 y;
  };
  F32 v[2];
};

//- 3-vectors

typedef union Vec3_F32 Vec3_F32;
union Vec3_F32
{
  struct
  {
    F32 x;
    F32 y;
    F32 z;
  };
  F32 v[3];
};

//- 4-vectors
typedef union Vec4_F32 Vec4_F32;
union Vec4_F32
{
  struct
  {
    F32 x;
    F32 y;
    F32 z;
    F32 w;
  };
  struct
  {
    Vec2_F32 xy;
    Vec2_F32 zw;
  };
  F32 v[4];
};

//- vector macros 
#define vec2_F32_from_vec(v) vec2_F32((F32)(v).x, (F32)(v).y);
#define vec2_S32_from_vec(v) vec2_S32((S32)(v).x, (S32)(v).y);
#define vec2_S64_from_vec(v) vec2_S64((S64)(v).x, (S64)(v).y);
//////////////////////////
//~ Matrix types
typedef struct Mat3x3_F32 Mat3x3_F32;
struct Mat3x3_F32 
{
  F32 elements[3][3];
};

typedef struct Mat4x4_F32 Mat4x4_F32;
struct Mat4x4_F32 
{
  F32 elements[4][4];
};

//////////////////////////
//~ Range types

//- 2D interval
//
typedef union Rng2_F32 Rng2_F32;
union Rng2_F32
{
  struct
  {
    Vec2_F32 min;
    Vec2_F32 max;
  };
  struct
  {
    Vec2_F32 p0;
    Vec2_F32 p1;
  };
  struct
  {
    F32 x0;
    F32 y0;
    F32 x1;
    F32 y1;
  };
  Vec2_F32 v[2];
};

//~ Vector functions

//- Vec2 F32
root_function Vec2_F32 vec2_F32(F32 x, F32 y);
root_function Vec2_F32 add2_F32(Vec2_F32 a, Vec2_F32 b);
root_function Vec2_F32 sub2_F32(Vec2_F32 a, Vec2_F32 b);

//- Vec2 S32 
root_function Vec2_S32 vec2_S32(S32 x, S32 y);

root_function Vec2_S64 vec2_S64(S64 x, S64 y);

root_function Vec3_F32 vec3_F32(F32 x, F32 y, F32 z);

root_function Vec4_F32 vec4_F32(F32 x, F32 y, F32 z, F32 w);

//~ Range functions
root_function Rng2_F32 rng2_F32(Vec2_F32 min, Vec2_F32 max);
root_function Rng2_F32 shift2_F32(Rng2_F32 r, Vec2_F32 v);
root_function Rng2_F32 pad2_F32(Rng2_F32 r, F32 x);
root_function Vec2_F32 dim2_F32(Rng2_F32 rng);
root_function B32 rng2_contains_vec2_F32(Rng2_F32 r, Vec2_F32 x);
root_function Rng2_F32 rng2_intersect_f32(Rng2_F32 a, Rng2_F32 b);
#endif //BASE_MATH_H
