#ifndef VEC4_H
#define VEC4_H

struct vec4 {
	double x, y, z, w;
};


struct vec4 vec4(double x, double y, double z, double w);
struct vec4 vec4s(double x);

struct vec4 vec4_add(struct vec4 a, struct vec4 b);
struct vec4 vec4_sub(struct vec4 a, struct vec4 b);
struct vec4 vec4_mul(struct vec4 a, struct vec4 b);
struct vec4 vec4_div(struct vec4 a, struct vec4 b);

struct vec4f {
	float x, y, z, w;
};


struct vec4f vec4f(float x, float y, float z, float w);
struct vec4f vec4fs(float x);

struct vec4f vec4f_add(struct vec4f a, struct vec4f b);
struct vec4f vec4f_sub(struct vec4f a, struct vec4f b);
struct vec4f vec4f_mul(struct vec4f a, struct vec4f b);
struct vec4f vec4f_div(struct vec4f a, struct vec4f b);

#if defined(VEC4_IMP) || defined(IMP)

struct vec4
vec4(double x, double y, double z, double w) {
	return (struct vec4) {.x = x, .y = y, .z = z, .w = w};
}

struct vec4
vec4s(double x) {
	return (struct vec4) {.x = x, .y = x, .z = x, .w = x};
}

struct vec4
vec4_add(struct vec4 a, struct vec4 b)
{
	return (struct vec4){
		.x = a.x + b.x,
		.y = a.y + b.y,
		.z = a.z + b.z,
		.w = a.w + b.w
	};
}

struct vec4
vec4_sub(struct vec4 a, struct vec4 b)
{
	return (struct vec4){
		.x = a.x - b.x,
		.y = a.y - b.y,
		.z = a.z - b.z,
		.w = a.w - b.w
	};
}

struct vec4
vec4_mul(struct vec4 a, struct vec4 b)
{
	return (struct vec4){
		.x = a.x * b.x,
		.y = a.y * b.y,
		.z = a.z * b.z,
		.w = a.w * b.w
	};
}

struct vec4
vec4_div(struct vec4 a, struct vec4 b)
{
	return (struct vec4){
		.x = a.x / b.x,
		.y = a.y / b.y,
		.z = a.z / b.z,
		.w = a.w / b.w
	};
}


struct vec4f
vec4f(float x, float y, float z, float w) {
	return (struct vec4f) {.x = x, .y = y, .z = z, .w = w};
}

struct vec4f
vec4fs(float x) {
	return (struct vec4f) {.x = x, .y = x, .z = x, .w = x};
}

struct vec4f
vec4f_add(struct vec4f a, struct vec4f b)
{
	return (struct vec4f){
		.x = a.x + b.x,
		.y = a.y + b.y,
		.z = a.z + b.z,
		.w = a.w + b.w
	};
}

struct vec4f
vec4f_sub(struct vec4f a, struct vec4f b)
{
	return (struct vec4f){
		.x = a.x - b.x,
		.y = a.y - b.y,
		.z = a.z - b.z,
		.w = a.w - b.w
	};
}

struct vec4f
vec4f_mul(struct vec4f a, struct vec4f b)
{
	return (struct vec4f){
		.x = a.x * b.x,
		.y = a.y * b.y,
		.z = a.z * b.z,
		.w = a.w * b.w
	};
}

struct vec4f
vec4f_div(struct vec4f a, struct vec4f b)
{
	return (struct vec4f){
		.x = a.x / b.x,
		.y = a.y / b.y,
		.z = a.z / b.z,
		.w = a.w / b.w
	};
}

#endif /* defined(VEC4_IMP) || defined(IMP) */

#endif	/* VEC4_H */
