// The Xmas Demo 2025: Semi-useful float and vector operations.
// This file magically adapts to the project and contains only stuff that's in use.
// Author: Corneliusen
// More info here: https://www.ignorantus.com/xmasdemo/
// License: https://creativecommons.org/publicdomain/zero/1.0/
#ifndef VECH
#define VECH

#include <math.h>

#define PIF ((float)PI)
#define MAXX(a,b) ((a)>(b)?(a):(b))
#define MIIN(a,b) ((a)<(b)?(a):(b))
#define CLAAMP(a,lo,hi) ((a)<(lo)?(lo):(a)>(hi)?(hi):(a))

typedef struct {
    float x, y, z;
} v3;
typedef struct {
    float x, y, z, w;
} v4;

static inline float fract( float f )
{
    return f - floorf( f );
}
static float sinf01( float f )
{
    return (sinf( f )+1.0f)*0.5f;
}

static inline v3 v3_set( float x, float y, float z )
{
    return (v3){ x, y, z };
}
static inline v3 v3_set1( float f )
{
    return (v3){ f, f, f };
}
static inline v3 v3_cross( v3 a, v3 b )
{
    v3 v;
    v.x = a.y*b.z - b.y*a.z;
    v.y = a.z*b.x - b.z*a.x;
    v.z = a.x*b.y - b.x*a.y;
    return v;
}
static inline v3 v3_normalize( v3 a )
{
    v3 v;
    float b = 1.0f / sqrtf( a.x * a.x + a.y * a.y + a.z * a.z );
    v.x = a.x * b;
    v.y = a.y * b;
    v.z = a.z * b;
    return v;
}
static inline v3 v3_add( v3 a, v3 b )
{
    v3 v;
    v.x = a.x + b.x;
    v.y = a.y + b.y;
    v.z = a.z + b.z;
    return v;
}
static inline v3 v3_add1( v3 a, float b )
{
    v3 v;
    v.x = a.x + b;
    v.y = a.y + b;
    v.z = a.z + b;
    return v;
}
static inline v3 v3_sub( v3 a, v3 b )
{
    v3 v;
    v.x = a.x - b.x;
    v.y = a.y - b.y;
    v.z = a.z - b.z;
    return v;
}
static inline v3 v3_mul1( v3 a, float b )
{
    v3 v;
    v.x = a.x * b;
    v.y = a.y * b;
    v.z = a.z * b;
    return v;
}
static inline v3 v3_div1( v3 a, float b )
{
    v3 v;
    v.x = a.x / b;
    v.y = a.y / b;
    v.z = a.z / b;
    return v;
}
static inline v3 v3_cos( v3 a )
{
    v3 v;
    v.x = cosf( a.x );
    v.y = cosf( a.y );
    v.z = cosf( a.z );
    return v;
}
static inline float v3_dot( v3 a, v3 b )
{
    return a.x * b.x + a.y * b.y + a.z * b.z;
}

static inline v4 v4_set( float x, float y, float z, float w )
{
    return (v4){ x, y, z, w };
}
static inline v4 v4_set1( float f )
{
    return (v4){ f, f, f, f };
}
static inline v4 v4_add( v4 a, v4 b )
{
    v4 v;
    v.x = a.x + b.x;
    v.y = a.y + b.y;
    v.z = a.z + b.z;
    v.w = a.w + b.w;
    return v;
}
static inline v4 v4_mul3( v4 a, float b )
{
    v4 v;
    v.x = a.x * b;
    v.y = a.y * b;
    v.z = a.z * b;
    v.w = a.w;
    return v;
}
static inline v4 v4_mix( v4 a, v4 b, float f )
{
    v4 v;
    v.x = a.x*(1.0f-f)+b.x*f;
    v.y = a.y*(1.0f-f)+b.y*f;
    v.z = a.z*(1.0f-f)+b.z*f;
    v.w = a.w*(1.0f-f)+b.w*f;
    return v;
}
static inline v4 v4_cos( v4 a )
{
    v4 v;
    v.x = cosf( a.x );
    v.y = cosf( a.y );
    v.z = cosf( a.z );
    v.w = cosf( a.w );
    return v;
}
#endif
