diff --git a/04_codegen/codegen.c b/04_codegen/codegen.c new file mode 100644 index 0000000..c7347ae --- /dev/null +++ b/04_codegen/codegen.c @@ -0,0 +1,498 @@ +#include "codegen.h" +#include "../mem_arena/arena.h" +#include +#include + +#define ARR_LEN(ARR) sizeof(ARR) / sizeof(ARR[0]) +#define MEM_ARENA_LENGTH 10 * 1024 * 1024 +#define LONG_BUFFER_LENGTH 8192 +#define MEDIUM_BUFFER_LENGTH 4096 +#define SHORT_BUFFER_LENGTH 1024 + +enum vec_funcs { + VEC_FUNC_ADD, + VEC_FUNC_SUB, + VEC_FUNC_MUL, + VEC_FUNC_DOT, + VEC_FUNC_MAGNITUDE, + VEC_FUNC_PRINT, + + COUNT_VEC_FUNCS, +}; + +void write_vec_func_implementation(arena_t *arena, func_data_t *func, + const struct_def_t *s, char *body, + const char *operator, const char * separator, + const char *end); + +int main(int argc, char *argv[]) { + const char *output_file = "vec.h"; + FILE *temp = fopen(output_file, "w"); + fclose(temp); + + FILE *fp = fopen(output_file, "a"); + + arena_t main_mem = {0}; + arena_init(&main_mem, MEM_ARENA_LENGTH); + + arena_t temp_mem = {0}; + arena_init(&temp_mem, MEM_ARENA_LENGTH); + + const char *header_name = "VEC_H"; + + write_header_guard_open(&temp_mem, fp, header_name); + + include_header_t headers[] = { + {.type = INCLUDE_TYPE_USER, .header = "../aliases.h"}, + {.type = INCLUDE_TYPE_SYSTEM, .header = "stdio.h"}, + {.type = INCLUDE_TYPE_SYSTEM, .header = "math.h"}, + }; + + for (u64 i = 0; i < ARR_LEN(headers); ++i) { + write_include(&temp_mem, fp, &(headers[i])); + } + + fwrite("\n", 1, 1, fp); + + type_info_t base_types[] = { + (type_info_t){.name = "i32", .short_name = 'i', .printf_spec = 'd'}, + (type_info_t){.name = "f32", .short_name = 'f', .printf_spec = 'f'}, + }; + + u64 dimensions[] = {2, 3}; + + const char *member_names[] = {"x", "y", "z"}; + + const char *arg_names[] = {"v1", "v2"}; + + func_data_t funcs[COUNT_VEC_FUNCS] = { + [VEC_FUNC_ADD] = + (func_data_t){ + .base_name = "vec_add", + .arg_count = 2, + .arg_names = arg_names, + }, + [VEC_FUNC_SUB] = + (func_data_t){ + .base_name = "vec_sub", + .arg_count = 2, + .arg_names = arg_names, + }, + [VEC_FUNC_MUL] = + (func_data_t){ + .base_name = "vec_mul", + .arg_count = 2, + .arg_names = arg_names, + }, + [VEC_FUNC_DOT] = + (func_data_t){ + .base_name = "vec_dot", + .arg_count = 2, + .arg_names = arg_names, + }, + [VEC_FUNC_MAGNITUDE] = + (func_data_t){ + .base_name = "vec_magnitude", + .arg_count = 1, + .arg_names = arg_names, + }, + [VEC_FUNC_PRINT] = + (func_data_t){ + .base_name = "vec_print", + .arg_count = 1, + .arg_names = arg_names, + }, + }; + + for (u64 i = 0; i < COUNT_VEC_FUNCS; ++i) { + write_macro_func(&temp_mem, fp, &(funcs[i])); + } + + data_type_t void_data_type = (data_type_t){ + .type = DATA_TYPE_NORMAL, + .type_info = (type_info_t){.name = "void"}, + }; + + for (u64 i = 0; i < ARR_LEN(base_types); ++i) { + for (u64 j = 0; j < ARR_LEN(dimensions); ++j) { + type_info_t base_type = base_types[i]; + data_type_t base_data_type = + (data_type_t){.type = DATA_TYPE_NORMAL, .type_info = base_type}; + u64 mem_count = dimensions[j]; + + char *typename = (char *)arena_alloc(&main_mem, SHORT_BUFFER_LENGTH); + sprintf(typename, "vec%lu%c_t", mem_count, base_type.short_name); + + identifier_t members[mem_count]; + memset(members, 0, sizeof(identifier_t) * mem_count); + + for (u64 k = 0; k < mem_count; ++k) { + members[k] = (identifier_t){ + .name = member_names[k], + .type = base_data_type, + }; + } + + struct_def_t s = (struct_def_t){ + .name = typename, + .mem_count = mem_count, + .members = members, + }; + + data_type_t vec_data_type = + (data_type_t){.type = DATA_TYPE_STRUCT, .struct_def = s}; + + write_struct(&temp_mem, fp, &s); + + funcs[VEC_FUNC_ADD].func.ret_type = vec_data_type; + funcs[VEC_FUNC_SUB].func.ret_type = vec_data_type; + funcs[VEC_FUNC_MUL].func.ret_type = vec_data_type; + funcs[VEC_FUNC_DOT].func.ret_type = base_data_type; + funcs[VEC_FUNC_MAGNITUDE].func.ret_type = base_data_type; + funcs[VEC_FUNC_PRINT].func.ret_type = void_data_type; + + for (u64 k = 0; k < COUNT_VEC_FUNCS; ++k) { + func_data_t *func = &(funcs[k]); + + char *name = (char *)arena_alloc(&main_mem, SHORT_BUFFER_LENGTH); + sprintf(name, "%s_%s", func->base_name, typename); + + u64 alloc_size = sizeof(identifier_t) * func->arg_count; + identifier_t *args = (identifier_t *)arena_alloc(&main_mem, alloc_size); + + for (u64 l = 0; l < func->arg_count; ++l) { + args[l] = + (identifier_t){.type = vec_data_type, .name = func->arg_names[l]}; + } + + func->func.name = name; + func->func.args = args; + + write_func_declaration(&temp_mem, fp, func); + } + + const char *vec_impl_begin = "#ifdef VEC_IMPLEMENTATION\n\n"; + fwrite(vec_impl_begin, strlen(vec_impl_begin), 1, fp); + + const char *operators[VEC_FUNC_DOT] = { + [VEC_FUNC_ADD] = "+", + [VEC_FUNC_SUB] = "-", + [VEC_FUNC_MUL] = "*", + }; + + for (u64 k = 0; k < VEC_FUNC_DOT; ++k) { + func_data_t *func = &(funcs[k]); + + char *body = (char *)arena_alloc(&main_mem, MEDIUM_BUFFER_LENGTH); + sprintf(body, "\treturn (%s) {", typename); + + write_vec_func_implementation(&main_mem, func, &s, body, operators[k], + ", ", "};\n"); + + write_func_defintion(&temp_mem, fp, func); + } + + func_data_t *vec_dot_func = &(funcs[VEC_FUNC_DOT]); + char *vec_dot_body = (char *)arena_alloc(&main_mem, MEDIUM_BUFFER_LENGTH); + strcat(vec_dot_body, "\treturn "); + + write_vec_func_implementation(&main_mem, vec_dot_func, &s, vec_dot_body, + operators[VEC_FUNC_MUL], " +", " 0;\n"); + + write_func_defintion(&temp_mem, fp, vec_dot_func); + + func_data_t *vec_magnitude_func = &(funcs[VEC_FUNC_MAGNITUDE]); + char *vec_magnitude_body = + (char *)arena_alloc(&main_mem, MEDIUM_BUFFER_LENGTH); + sprintf(vec_magnitude_body, "\t%s dotproduct = %s(%s, %s);\n", + base_type.name, vec_dot_func->func.name, + vec_magnitude_func->arg_names[0], + vec_magnitude_func->arg_names[0]); + strcat(vec_magnitude_body, "\treturn ("); + strcat(vec_magnitude_body, base_type.name); + strcat(vec_magnitude_body, ")sqrtf(dotproduct);\n"); + + vec_magnitude_func->func.body = vec_magnitude_body; + + write_func_defintion(&temp_mem, fp, vec_magnitude_func); + + func_data_t *vec_print_func = &(funcs[VEC_FUNC_PRINT]); + char *vec_print_body = + (char *)arena_alloc(&main_mem, MEDIUM_BUFFER_LENGTH); + strcat(vec_print_body, "\tprintf(\"{%"); + + for (u64 k = 0; k < s.mem_count; ++k) { + if (k > 0) { + strcat(vec_print_body, ", %"); + } + + strcat(vec_print_body, &(base_type.printf_spec)); + } + + strcat(vec_print_body, "}\\n\","); + + for (u64 k = 0; k < s.mem_count; ++k) { + if (k > 0) { + strcat(vec_print_body, ","); + } + + for (u64 l = 0; l < vec_print_func->arg_count; ++l) { + char *arg = (char *)arena_alloc(&main_mem, SHORT_BUFFER_LENGTH); + sprintf(arg, " %s.%s", vec_print_func->arg_names[l], + s.members[k].name); + + strcat(vec_print_body, arg); + } + } + + strcat(vec_print_body, ");\n"); + + vec_print_func->func.body = vec_print_body; + + write_func_defintion(&temp_mem, fp, vec_print_func); + + const char *vec_impl_end = "#endif // VEC_IMPLEMENTATION\n\n"; + fwrite(vec_impl_end, strlen(vec_impl_end), 1, fp); + } + + arena_clear(&main_mem); + } + + write_header_guard_close(&temp_mem, fp, header_name); + + arena_free(&temp_mem); + arena_free(&main_mem); + + fclose(fp); + + return 0; +} + +void write_header_guard_open(arena_t *arena, FILE *fp, const char *header_id) { + char header_guard[LONG_BUFFER_LENGTH] = {0}; + + sprintf(header_guard, "#ifndef %s\n#define %s\n\n", header_id, header_id); + + u64 length = strlen(header_guard); + + fwrite(header_guard, length, 1, fp); +} + +void write_header_guard_close(arena_t *arena, FILE *fp, const char *header_id) { + char *header_guard = (char *)arena_alloc(arena, LONG_BUFFER_LENGTH); + if (!header_guard) { + return; + } + + sprintf(header_guard, "#endif // %s", header_id); + + u64 length = strlen(header_guard); + + fwrite(header_guard, length, 1, fp); + + arena_clear(arena); +} + +void write_include(arena_t *arena, FILE *fp, const include_header_t *header) { + u64 length = 0; + + char *include_line = (char *)arena_alloc(arena, LONG_BUFFER_LENGTH); + if (!include_line) { + return; + } + + switch (header->type) { + case INCLUDE_TYPE_SYSTEM: + sprintf(include_line, "#include <%s>\n", header->header); + + length = strlen(include_line); + + fwrite(include_line, length, 1, fp); + + break; + case INCLUDE_TYPE_USER: + sprintf(include_line, "#include \"%s\"\n", header->header); + + length = strlen(include_line); + + fwrite(include_line, length, 1, fp); + + break; + default: + break; + } + + arena_clear(arena); +} + +void write_data_type(char *dst, const data_type_t *data_type) { + switch (data_type->type) { + case DATA_TYPE_NORMAL: + strcat(dst, data_type->type_info.name); + + break; + case DATA_TYPE_STRUCT: + strcat(dst, data_type->struct_def.name); + + break; + default: + break; + } +} + +void write_identifier(char *dst, const identifier_t *identifier) { + write_data_type(dst, &(identifier->type)); + + strcat(dst, " "); + strcat(dst, identifier->name); +} + +void write_struct(arena_t *arena, FILE *fp, const struct_def_t *struct_def) { + char *struct_output = (char *)arena_alloc(arena, LONG_BUFFER_LENGTH); + if (!struct_output) { + return; + } + + strcat(struct_output, "typedef struct {"); + + for (u64 i = 0; i < struct_def->mem_count; ++i) { + strcat(struct_output, "\n\t"); + + const identifier_t *member = &(struct_def->members[i]); + + write_identifier(struct_output, member); + + strcat(struct_output, ";"); + } + + strcat(struct_output, "\n} "); + strcat(struct_output, struct_def->name); + strcat(struct_output, ";\n\n"); + + u64 length = strlen(struct_output); + + fwrite(struct_output, length, 1, fp); + + arena_clear(arena); +} + +void write_func_prototype(char *dst, const func_data_t *func) { + strcat(dst, "INTERNAL "); + + write_data_type(dst, &(func->func.ret_type)); + + strcat(dst, " "); + strcat(dst, func->func.name); + strcat(dst, "("); + + for (u64 i = 0; i < func->arg_count; ++i) { + if (i > 0) { + strcat(dst, ", "); + } + + const identifier_t *arg = &(func->func.args[i]); + + write_identifier(dst, arg); + } + + strcat(dst, ")"); +} + +void write_func_declaration(arena_t *arena, FILE *fp, const func_data_t *func) { + char *func_declaration = (char *)arena_alloc(arena, LONG_BUFFER_LENGTH); + if (!func_declaration) { + return; + } + + write_func_prototype(func_declaration, func); + + strcat(func_declaration, ";\n\n"); + + u64 length = strlen(func_declaration); + + fwrite(func_declaration, length, 1, fp); + + arena_clear(arena); +} + +void write_func_defintion(arena_t *arena, FILE *fp, const func_data_t *func) { + char *func_definition = (char *)arena_alloc(arena, LONG_BUFFER_LENGTH); + if (!func_definition) { + return; + } + + write_func_prototype(func_definition, func); + + strcat(func_definition, " {\n"); + + strcat(func_definition, func->func.body); + + strcat(func_definition, "}\n\n"); + + u64 length = strlen(func_definition); + + fwrite(func_definition, length, 1, fp); + + arena_clear(arena); +} + +void write_macro_func(arena_t *arena, FILE *fp, const func_data_t *func) { + char *func_definition = (char *)arena_alloc(arena, LONG_BUFFER_LENGTH); + if (!func_definition) { + return; + } + + strcat(func_definition, "#define "); + strcat(func_definition, func->base_name); + strcat(func_definition, "(T"); + + for (u64 i = 0; i < func->arg_count; ++i) { + strcat(func_definition, ", "); + strcat(func_definition, func->arg_names[i]); + } + + strcat(func_definition, ") "); + strcat(func_definition, func->base_name); + strcat(func_definition, "_##T("); + + for (u64 i = 0; i < func->arg_count; ++i) { + if (i > 0) { + strcat(func_definition, ", "); + } + + strcat(func_definition, func->arg_names[i]); + } + + strcat(func_definition, ")\n\n"); + + u64 length = strlen(func_definition); + + fwrite(func_definition, length, 1, fp); + + arena_clear(arena); +} + +void write_vec_func_implementation(arena_t *arena, func_data_t *func, + const struct_def_t *s, char *body, + const char *operator, const char * separator, + const char *end) { + for (u64 l = 0; l < s->mem_count; ++l) { + for (u64 m = 0; m < func->arg_count; ++m) { + if (m > 0) { + strcat(body, " "); + strcat(body, operator); + } + + char *arg = (char *)arena_alloc(arena, SHORT_BUFFER_LENGTH); + sprintf(arg, " %s.%s", func->arg_names[m], s->members[l].name); + + strcat(body, arg); + } + + strcat(body, separator); + } + + strcat(body, end); + + func->func.body = body; +} diff --git a/04_codegen/codegen.h b/04_codegen/codegen.h new file mode 100644 index 0000000..50c7113 --- /dev/null +++ b/04_codegen/codegen.h @@ -0,0 +1,77 @@ +#ifndef CODEGEN_H +#define CODEGEN_H + +#include "../aliases.h" +#include "../mem_arena/arena.h" +#include + +typedef enum { + INCLUDE_TYPE_SYSTEM, + INCLUDE_TYPE_USER, + COUNT_INCLUDE_TYPES, +} include_type; + +typedef struct { + include_type type; + const char *header; +} include_header_t; + +typedef struct { + const char *name; + char short_name; + char printf_spec; +} type_info_t; + +typedef struct identifier_s identifier_t; + +typedef struct { + const char *name; + u64 mem_count; + identifier_t *members; +} struct_def_t; + +typedef enum { + DATA_TYPE_NORMAL, + DATA_TYPE_STRUCT, + COUNT_DATA_TYPE, +} data_type; + +typedef struct { + data_type type; + union { + type_info_t type_info; + struct_def_t struct_def; + }; +} data_type_t; + +struct identifier_s { + data_type_t type; + const char *name; +}; + +typedef struct { + data_type_t ret_type; + const char *name; + identifier_t *args; + const char *body; +} func_t; + +typedef struct { + const char *base_name; + u64 arg_count; + const char **arg_names; + func_t func; +} func_data_t; + +void write_header_guard_open(arena_t *arena, FILE *fp, const char *header_id); +void write_header_guard_close(arena_t *arena, FILE *fp, const char *header_id); +void write_include(arena_t *arena, FILE *fp, const include_header_t *header); +void write_data_type(char *dst, const data_type_t *data_type); +void write_identifier(char *dst, const identifier_t *identifier); +void write_struct(arena_t *arena, FILE *fp, const struct_def_t *struct_def); +void write_func_prototype(char *dst, const func_data_t *func); +void write_func_declaration(arena_t *arena, FILE *fp, const func_data_t *func); +void write_func_defintion(arena_t *arena, FILE *fp, const func_data_t *func); +void write_macro_func(arena_t *arena, FILE *fp, const func_data_t *func); + +#endif // !CODEGEN_H diff --git a/04_codegen/main.c b/04_codegen/main.c new file mode 100644 index 0000000..4b7f6d3 --- /dev/null +++ b/04_codegen/main.c @@ -0,0 +1,18 @@ +#define VEC_IMPLEMENTATION +#include "vec.h" +#undef VEC_IMPLEMENTATION +#include + +int main(int argc, char *argv[]) { + vec2i_t v1 = (vec2i_t){2, 3}; + vec2i_t v2 = (vec2i_t){4, 5}; + + vec_print(vec2i_t, vec_add(vec2i_t, v1, v2)); + vec_print(vec2i_t, vec_sub(vec2i_t, v1, v2)); + vec_print(vec2i_t, vec_mul(vec2i_t, v1, v2)); + printf("%d\n", vec_dot(vec2i_t, v1, v2)); + printf("%d\n", vec_magnitude(vec2i_t, v1)); + printf("%d\n", vec_magnitude(vec2i_t, v2)); + + return 0; +} diff --git a/04_codegen/vec.h b/04_codegen/vec.h new file mode 100644 index 0000000..0a1da10 --- /dev/null +++ b/04_codegen/vec.h @@ -0,0 +1,206 @@ +#ifndef VEC_H +#define VEC_H + +#include "../aliases.h" +#include +#include + +#define vec_add(T, v1, v2) vec_add_##T(v1, v2) + +#define vec_sub(T, v1, v2) vec_sub_##T(v1, v2) + +#define vec_mul(T, v1, v2) vec_mul_##T(v1, v2) + +#define vec_dot(T, v1, v2) vec_dot_##T(v1, v2) + +#define vec_magnitude(T, v1) vec_magnitude_##T(v1) + +#define vec_print(T, v1) vec_print_##T(v1) + +typedef struct { + i32 x; + i32 y; +} vec2i_t; + +INTERNAL vec2i_t vec_add_vec2i_t(vec2i_t v1, vec2i_t v2); + +INTERNAL vec2i_t vec_sub_vec2i_t(vec2i_t v1, vec2i_t v2); + +INTERNAL vec2i_t vec_mul_vec2i_t(vec2i_t v1, vec2i_t v2); + +INTERNAL i32 vec_dot_vec2i_t(vec2i_t v1, vec2i_t v2); + +INTERNAL i32 vec_magnitude_vec2i_t(vec2i_t v1); + +INTERNAL void vec_print_vec2i_t(vec2i_t v1); + +#ifdef VEC_IMPLEMENTATION + +INTERNAL vec2i_t vec_add_vec2i_t(vec2i_t v1, vec2i_t v2) { + return (vec2i_t) { v1.x + v2.x, v1.y + v2.y, }; +} + +INTERNAL vec2i_t vec_sub_vec2i_t(vec2i_t v1, vec2i_t v2) { + return (vec2i_t) { v1.x - v2.x, v1.y - v2.y, }; +} + +INTERNAL vec2i_t vec_mul_vec2i_t(vec2i_t v1, vec2i_t v2) { + return (vec2i_t) { v1.x * v2.x, v1.y * v2.y, }; +} + +INTERNAL i32 vec_dot_vec2i_t(vec2i_t v1, vec2i_t v2) { + return v1.x * v2.x + v1.y * v2.y + 0; +} + +INTERNAL i32 vec_magnitude_vec2i_t(vec2i_t v1) { + i32 dotproduct = vec_dot_vec2i_t(v1, v1); + return (i32)sqrtf(dotproduct); +} + +INTERNAL void vec_print_vec2i_t(vec2i_t v1) { + printf("{%d, %d}\n", v1.x, v1.y); +} + +#endif // VEC_IMPLEMENTATION + +typedef struct { + i32 x; + i32 y; + i32 z; +} vec3i_t; + +INTERNAL vec3i_t vec_add_vec3i_t(vec3i_t v1, vec3i_t v2); + +INTERNAL vec3i_t vec_sub_vec3i_t(vec3i_t v1, vec3i_t v2); + +INTERNAL vec3i_t vec_mul_vec3i_t(vec3i_t v1, vec3i_t v2); + +INTERNAL i32 vec_dot_vec3i_t(vec3i_t v1, vec3i_t v2); + +INTERNAL i32 vec_magnitude_vec3i_t(vec3i_t v1); + +INTERNAL void vec_print_vec3i_t(vec3i_t v1); + +#ifdef VEC_IMPLEMENTATION + +INTERNAL vec3i_t vec_add_vec3i_t(vec3i_t v1, vec3i_t v2) { + return (vec3i_t) { v1.x + v2.x, v1.y + v2.y, v1.z + v2.z, }; +} + +INTERNAL vec3i_t vec_sub_vec3i_t(vec3i_t v1, vec3i_t v2) { + return (vec3i_t) { v1.x - v2.x, v1.y - v2.y, v1.z - v2.z, }; +} + +INTERNAL vec3i_t vec_mul_vec3i_t(vec3i_t v1, vec3i_t v2) { + return (vec3i_t) { v1.x * v2.x, v1.y * v2.y, v1.z * v2.z, }; +} + +INTERNAL i32 vec_dot_vec3i_t(vec3i_t v1, vec3i_t v2) { + return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + 0; +} + +INTERNAL i32 vec_magnitude_vec3i_t(vec3i_t v1) { + i32 dotproduct = vec_dot_vec3i_t(v1, v1); + return (i32)sqrtf(dotproduct); +} + +INTERNAL void vec_print_vec3i_t(vec3i_t v1) { + printf("{%d, %d, %d}\n", v1.x, v1.y, v1.z); +} + +#endif // VEC_IMPLEMENTATION + +typedef struct { + f32 x; + f32 y; +} vec2f_t; + +INTERNAL vec2f_t vec_add_vec2f_t(vec2f_t v1, vec2f_t v2); + +INTERNAL vec2f_t vec_sub_vec2f_t(vec2f_t v1, vec2f_t v2); + +INTERNAL vec2f_t vec_mul_vec2f_t(vec2f_t v1, vec2f_t v2); + +INTERNAL f32 vec_dot_vec2f_t(vec2f_t v1, vec2f_t v2); + +INTERNAL f32 vec_magnitude_vec2f_t(vec2f_t v1); + +INTERNAL void vec_print_vec2f_t(vec2f_t v1); + +#ifdef VEC_IMPLEMENTATION + +INTERNAL vec2f_t vec_add_vec2f_t(vec2f_t v1, vec2f_t v2) { + return (vec2f_t) { v1.x + v2.x, v1.y + v2.y, }; +} + +INTERNAL vec2f_t vec_sub_vec2f_t(vec2f_t v1, vec2f_t v2) { + return (vec2f_t) { v1.x - v2.x, v1.y - v2.y, }; +} + +INTERNAL vec2f_t vec_mul_vec2f_t(vec2f_t v1, vec2f_t v2) { + return (vec2f_t) { v1.x * v2.x, v1.y * v2.y, }; +} + +INTERNAL f32 vec_dot_vec2f_t(vec2f_t v1, vec2f_t v2) { + return v1.x * v2.x + v1.y * v2.y + 0; +} + +INTERNAL f32 vec_magnitude_vec2f_t(vec2f_t v1) { + f32 dotproduct = vec_dot_vec2f_t(v1, v1); + return (f32)sqrtf(dotproduct); +} + +INTERNAL void vec_print_vec2f_t(vec2f_t v1) { + printf("{%f, %f}\n", v1.x, v1.y); +} + +#endif // VEC_IMPLEMENTATION + +typedef struct { + f32 x; + f32 y; + f32 z; +} vec3f_t; + +INTERNAL vec3f_t vec_add_vec3f_t(vec3f_t v1, vec3f_t v2); + +INTERNAL vec3f_t vec_sub_vec3f_t(vec3f_t v1, vec3f_t v2); + +INTERNAL vec3f_t vec_mul_vec3f_t(vec3f_t v1, vec3f_t v2); + +INTERNAL f32 vec_dot_vec3f_t(vec3f_t v1, vec3f_t v2); + +INTERNAL f32 vec_magnitude_vec3f_t(vec3f_t v1); + +INTERNAL void vec_print_vec3f_t(vec3f_t v1); + +#ifdef VEC_IMPLEMENTATION + +INTERNAL vec3f_t vec_add_vec3f_t(vec3f_t v1, vec3f_t v2) { + return (vec3f_t) { v1.x + v2.x, v1.y + v2.y, v1.z + v2.z, }; +} + +INTERNAL vec3f_t vec_sub_vec3f_t(vec3f_t v1, vec3f_t v2) { + return (vec3f_t) { v1.x - v2.x, v1.y - v2.y, v1.z - v2.z, }; +} + +INTERNAL vec3f_t vec_mul_vec3f_t(vec3f_t v1, vec3f_t v2) { + return (vec3f_t) { v1.x * v2.x, v1.y * v2.y, v1.z * v2.z, }; +} + +INTERNAL f32 vec_dot_vec3f_t(vec3f_t v1, vec3f_t v2) { + return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + 0; +} + +INTERNAL f32 vec_magnitude_vec3f_t(vec3f_t v1) { + f32 dotproduct = vec_dot_vec3f_t(v1, v1); + return (f32)sqrtf(dotproduct); +} + +INTERNAL void vec_print_vec3f_t(vec3f_t v1) { + printf("{%f, %f, %f}\n", v1.x, v1.y, v1.z); +} + +#endif // VEC_IMPLEMENTATION + +#endif // VEC_H \ No newline at end of file