// Basic vec2/vec3/vec4 operations.
// Written by Nils Liaaen Corneliusen 2019.
// https://www.ignorantus.com
// License: CC0 1.0 Universal (CC0 1.0) Public Domain Dedication license
#ifndef VECH
#define VECH

#include <math.h>

#define PI 3.14159265f

typedef struct {
	float x, y, z, w;
} v4;

typedef struct {
	float x, y, z;
} v3;

typedef struct {
	float x, y;
} v2;

static inline v2 v2_set( float x, float y )
{
	v2 r;
	r.x = x;
	r.y = y;
	return r;
}

static inline v2 v2_sub( v2 a, v2 b )
{
	v2 v;
	v.x = a.x - b.x;
	v.y = a.y - b.y;
	return v;
}

static inline float v2_length( v2 a )
{
    return sqrtf( a.x * a.x + a.y * a.y );
}

static inline float v2_dot( v2 a, v2 b )
{
    return a.x * b.x + a.y * b.y;
}

static inline float v2_dots( v2 a )
{
    return a.x * a.x + a.y * a.y;
}

static inline v4 v4_set( float x, float y, float z, float w )
{
	v4 v;
	v.x = x;
	v.y = y;
	v.z = z;
	v.w = w;
	return v;
}

static inline v4 v4_mul1( 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 * b;
    return v;
}

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 float v4_dot( v4 a, v4 b )
{
    return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
}

static inline float v4_dots( v4 a )
{
    return a.x * a.x + a.y * a.y + a.z * a.z + a.w * a.w;
}

static inline float v4_length( v4 a )
{
    return sqrtf( a.x * a.x + a.y * a.y + a.z * a.z + a.w * a.w );
}

static inline v4 v4_mix( v4 a, v4 b, float f )
{
	v4 out;

	out.x = a.x*(1-f)+b.x*f;
	out.y = a.y*(1-f)+b.y*f;
	out.z = a.z*(1-f)+b.z*f;
	out.w = a.w*(1-f)+b.w*f;

	return out;
}

static inline v3 v3_mix( v3 a, v3 b, float f )
{
	v3 out;

	out.x = a.x*(1-f)+b.x*f;
	out.y = a.y*(1-f)+b.y*f;
	out.z = a.z*(1-f)+b.z*f;

	return out;
}

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_set( float x, float y, float z )
{
	v3 v;
	v.x = x;
	v.y = y;
	v.z = z;
	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_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_mul( 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_sub1( 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 float v3_dot( v3 a, v3 b )
{
	return a.x * b.x + a.y * b.y + a.z * b.z;
}

static inline float v3_dots( v3 a )
{
    return a.x * a.x + a.y * a.y + a.z * a.z;
}

#endif
