]> git.leonardobizzoni.com Git - CBuild/commitdiff
Fuck C++ and github master
authorLeonardoBizzoni <leo2002714@gmail.com>
Sun, 18 Jan 2026 19:58:33 +0000 (20:58 +0100)
committerLeonardoBizzoni <leo2002714@gmail.com>
Sun, 18 Jan 2026 20:00:15 +0000 (21:00 +0100)
cbuild.h
examples/01-basics/cbuild.c [moved from examples/01-basics/build.c with 100% similarity]
examples/02-async-commands/cbuild.c [moved from examples/02-async-commands/build.c with 100% similarity]
examples/03-stream-redirection/cbuild.c [moved from examples/03-stream-redirection/build.c with 100% similarity]
examples/04-multiple-build-files-and-rebuild-opt/cbuild.c [moved from examples/04-multiple-build-files-and-rebuild-opt/build.c with 100% similarity]
examples/XX-generic-codebase-build/cbuild.c [moved from examples/XX-generic-codebase-build/build.c with 100% similarity]
extra/cbuild_linagen.h
extra/cbuild_tests.h

index 236d62103ce52c837f8a8ffe4174a6322f1817b0..0651bbd5817c7ea777f01452e24874471fcc7978 100644 (file)
--- a/cbuild.h
+++ b/cbuild.h
 #  error Unknown operating system
 #endif
 
-#if defined(__cplusplus)
-#  define CPP 1
-#else
-#  define CPP 0
-#endif
-
 #if !defined(COMPILER_GCC)
 #  define COMPILER_GCC 0
 #endif
 #  define OS_NONE 0
 #endif
 
-#if !CPP
-#  define BOOL_DEFINED 1
-#  if __STDC_VERSION__ >= 199901L
-#    include <stdbool.h>
-#  else
-typedef enum {false, true} bool;
-#  endif
+#define BOOL_DEFINED 1
+#if __STDC_VERSION__ >= 199901L
+#  include <stdbool.h>
+#else
+   typedef enum {false, true} bool;
 #endif
 
 #include <stdlib.h>
@@ -120,13 +112,13 @@ typedef enum {false, true} bool;
 #endif
 
 
-internal void cb_assertion_break(const char *condition,
-                                 const char *file, int32_t line) {
+internal void cb_assertion_break(char *condition,
+                                 char *file, int32_t line) {
   _assert_break();
 }
 
-typedef void (*cb_assertion_handler_fn)(const char *condition,
-                                        const char *file, int32_t line);
+typedef void (*cb_assertion_handler_fn)(char *condition,
+                                        char *file, int32_t line);
 internal cb_assertion_handler_fn cb_assertion_handler = cb_assertion_break;
 
 #define cb_assert(COND)                                \
@@ -149,14 +141,9 @@ internal cb_assertion_handler_fn cb_assertion_handler = cb_assertion_break;
   (!(Head) ? (Head) = (Last) = (Nodeptr)                                       \
            : ((Last) ? ((Last)->Next = (Nodeptr), (Last) = (Nodeptr))          \
                      : ((Head)->Next = (Last) = (Nodeptr))))
-#if __cplusplus
-#  define TYPE_CAST(ThingOfType, Thing) reinterpret_cast<decltype(ThingOfType)>(Thing)
-#else
-#  define TYPE_CAST(ThingOfType, Thing) (Thing)
-#endif
 
 struct CB_PathList {
-  const char **values;
+  char **values;
   size_t count;
   size_t capacity;
 };
@@ -220,10 +207,10 @@ enum {
 #define cb_cmd_push(Dynarr, Value) cb_dyn_push(Dynarr, Value)
 #define cb_cmd_append_dyn(Dynarr, Values, Count) cb_dyn_append((Dynarr), (Values), (Count));
 #define cb_cmd_append(Dynarr, ...) cb_dyn_append((Dynarr),                                               \
-                                                 ((const char*[]){__VA_ARGS__}),                         \
-                                                 (sizeof((const char*[]){__VA_ARGS__}) / sizeof(char*)))
+                                                 ((char*[]){__VA_ARGS__}),                         \
+                                                 (sizeof((char*[]){__VA_ARGS__}) / sizeof(char*)))
 #define cb_println(Level, Fmt, ...) cb_print((Level), Fmt "\n", ##__VA_ARGS__)
-#define cb_rebuild_self(argc, argv) _cb_rebuild(argc, argv, __FILE__, 0)
+#define cb_rebuild_self(argc, argv) _cb_rebuild(argc, argv, __FILE__, (char *)0)
 #define cb_rebuild_self_with(argc, argv, ...) _cb_rebuild(argc, argv, __FILE__, __VA_ARGS__, (char*)0)
 #define cb_is_outdated(OutputFile, ...) _cb_is_outdated((OutputFile), __VA_ARGS__, 0)
 #define cb_cmd_run(Cmd, ...) _cb_cmd_run((Cmd), (struct Cb_Cmd_RunArgs) { \
@@ -238,18 +225,17 @@ enum {
     free((Dynarr)->Values);                       \
     (Dynarr)->Count = 0;                          \
   } while (0)
-#define cb_dyn_reserve_custom(Dynarr, HowMany, Values, Count, Capacity)                      \
-  do {                                                                                       \
-    if (!(Dynarr)->Capacity) {                                                               \
-      (Dynarr)->Capacity = CB_DYN_DEFAULT_CAPACITY;                                          \
-    }                                                                                        \
-    while ((HowMany) > (Dynarr)->Capacity) {                                                 \
-      (Dynarr)->Capacity *= 2;                                                               \
-    }                                                                                        \
-    (Dynarr)->Values = TYPE_CAST((Dynarr)->Values,                                           \
-                                 realloc((Dynarr)->Values,                                   \
-                                         (Dynarr)->Capacity * sizeof((Dynarr)->Values[0]))); \
-    cb_assert((Dynarr)->Values);                                                             \
+#define cb_dyn_reserve_custom(Dynarr, HowMany, Values, Count, Capacity)           \
+  do {                                                                            \
+    if (!(Dynarr)->Capacity) {                                                    \
+      (Dynarr)->Capacity = CB_DYN_DEFAULT_CAPACITY;                               \
+    }                                                                             \
+    while ((HowMany) > (Dynarr)->Capacity) {                                      \
+      (Dynarr)->Capacity *= 2;                                                    \
+    }                                                                             \
+    (Dynarr)->Values = realloc((Dynarr)->Values,                                  \
+                               (Dynarr)->Capacity * sizeof((Dynarr)->Values[0])); \
+    cb_assert((Dynarr)->Values);                                                  \
   } while(0)
 #define cb_dyn_push_custom(Dynarr, Node, Values, Count, Capacity) \
   do {                                                            \
@@ -273,8 +259,8 @@ enum {
 #define _is_literal(x) _is_literal_(x)
 #define _is_literal_(x) _is_literal_f(#x, sizeof(#x) - 1)
 
-static char* cb_format(const char *format, ...);
-static void cb_print(CB_LogLevel level, const char *fmt, ...);
+static char* cb_format(char *format, ...);
+static void cb_print(CB_LogLevel level, char *fmt, ...);
 static char* cb_getenv(char *varname);
 static bool cb_setenv(char *varname, char *value);
 static void cb_cmd_print(CB_Cmd *cmd);
@@ -288,11 +274,12 @@ static void cb_dir_delete(char *path);
 static void cb_file_delete(char *path);
 static bool cb_file_rename(char *path, char *to);
 static bool cb_file_exists(char *path);
+static bool cb_cli_contains(int32_t argc, char **argv, char *target);
 
 internal void _cb_handle_write(CB_Handle fd, char *buffer, size_t buffsize);
-internal char* _cb_format(const char *format, va_list args);
-internal bool _cb_need_rebuild(const char *output_path, struct CB_PathList sources);
-internal void _cb_rebuild(int argc, char **argv, const char *cb_src, ...);
+internal char* _cb_format(char *format, va_list args);
+internal bool _cb_need_rebuild(char *output_path, struct CB_PathList sources);
+internal void _cb_rebuild(int argc, char **argv, char *cb_src, ...);
 internal bool _cb_is_outdated(char *output, ...);
 internal CB_Process _cb_cmd_run(CB_Cmd *cmd, struct Cb_Cmd_RunArgs args);
 internal size_t _last_occurance_of(char *string, char ch);
@@ -301,7 +288,7 @@ internal bool _is_literal_f(char *str, size_t l);
 
 // ==============================================================================
 // Implementation
-static char* cb_format(const char *format, ...) {
+static char* cb_format(char *format, ...) {
   va_list args;
   va_start(args, format);
   char *res = _cb_format(format, args);
@@ -309,7 +296,7 @@ static char* cb_format(const char *format, ...) {
   return res;
 }
 
-static void cb_print(CB_LogLevel level, const char *fmt, ...) {
+static void cb_print(CB_LogLevel level, char *fmt, ...) {
   va_list args;
   switch (level) {
     case CB_LogLevel_Info: {
@@ -368,7 +355,7 @@ static void cb_process_wait(CB_Process *proc) {
 
 #if OS_WINDOWS
   WaitForSingleObject(proc->handle, INFINITE);
-  GetExitCodeProcess(proc->handle, &proc->status_code);
+  GetExitCodeProcess(proc->handle, (LPDWORD)&proc->status_code);
   CloseHandle(proc->handle);
 #else
   int32_t status = 0;
@@ -476,7 +463,7 @@ static char* cb_handle_read(CB_Handle fd) {
   struct stat file_stat;
   if (!fstat(fd, &file_stat)) {
     char *res = (char *)malloc(file_stat.st_size);
-    if(pread(fd, res, file_stat.st_size, 0) >= 0) {
+    if (pread(fd, res, file_stat.st_size, 0) >= 0) {
       return res;
     }
   }
@@ -533,6 +520,15 @@ static bool cb_file_exists(char *path) {
   return access(path, F_OK) == 0;
 }
 
+static bool cb_cli_contains(int32_t argc, char **argv, char *target) {
+  for (int32_t i = 0; i < argc; ++i) {
+    if (!strcmp(argv[i], target)) {
+      return true;
+    }
+  }
+  return false;
+}
+
 
 internal bool _cb_is_outdated(char *output, ...) {
   struct CB_PathList sources = {};
@@ -571,7 +567,7 @@ internal void _cb_handle_write(CB_Handle fd, char *buffer, size_t buffsize) {
 #endif
 }
 
-internal char* _cb_format(const char *format, va_list args) {
+internal char* _cb_format(char *format, va_list args) {
   va_list args2;
   va_copy(args2, args);
   uint32_t needed_bytes = vsnprintf(0, 0, format, args2) + 1;
@@ -635,7 +631,7 @@ internal CB_Process _cb_cmd_run(CB_Cmd *cmd, struct Cb_Cmd_RunArgs args) {
     CB_Cmd _cmd = {};
     cb_cmd_append_dyn(&_cmd, cmd->values, cmd->count);
     cb_cmd_push(&_cmd, 0);
-    if (execvp(_cmd.values[0], (char *const *)_cmd.values) < 0) {
+    if (execvp(_cmd.values[0], (char **)_cmd.values) < 0) {
       cb_println(CB_LogLevel_Error, "Child process `%s` creation failed with error %d: %s\n",
                  cmd->values[0], errno, strerror(errno));
       exit(-1);
@@ -654,9 +650,9 @@ internal CB_Process _cb_cmd_run(CB_Cmd *cmd, struct Cb_Cmd_RunArgs args) {
   return res;
 }
 
-internal void _cb_rebuild(int argc, char **argv, const char *builder_src, ...) {
+internal void _cb_rebuild(int argc, char **argv, char *builder_src, ...) {
   cb_assert(argc >= 1);
-  const char *exe_name = argv[0];
+  char *exe_name = argv[0];
 
   struct CB_PathList sources = {};
   cb_dyn_push(&sources, builder_src);
@@ -705,7 +701,7 @@ internal void _cb_rebuild(int argc, char **argv, const char *builder_src, ...) {
   exit(0);
 }
 
-internal bool _cb_need_rebuild(const char *output_path, struct CB_PathList sources) {
+internal bool _cb_need_rebuild(char *output_path, struct CB_PathList sources) {
 #if OS_WINDOWS
   FILETIME output_mtime_large = {};
   HANDLE output_handle = CreateFileA(output_path, GENERIC_READ,
@@ -769,7 +765,7 @@ internal size_t _last_occurance_of(char *string, char ch) {
 }
 
 internal bool _is_literal_f(char *str, size_t l) {
-  const char *e = str + l;
+  char *e = str + l;
   if (str[0] == 'L') str++;
   if (str[0] != '"') return false;
   for (; str != e; str = strchr(str + 1, '"')) {
index 707162b55dc28086136258f3790f342fb2f8dadd..77519a6cbcee4a06631b798b8c859dc1149951fc 100644 (file)
@@ -30,92 +30,90 @@ static void
 cb_linagen_typedef_matnn(CB_Generator *gen, char *type, int32_t n);
 
 static inline void
-cb_linagen_defun_vecn(CB_Generator *gen, char *type,
-                      int32_t n, bool implementation);
+cb_linagen_defun_vecn(CB_Generator *gen, char *type, int32_t n, bool implementation);
 static inline void
-cb_linagen_defun_vecn_add(CB_Generator *gen, char *type,
-                          int32_t n, bool implementation);
+cb_linagen_defun_vecn_add(CB_Generator *gen, char *type, int32_t n, bool implementation);
 static inline void
-cb_linagen_defun_vecn_sub(CB_Generator *gen, char *type,
-                          int32_t n, bool implementation);
+cb_linagen_defun_vecn_sub(CB_Generator *gen, char *type, int32_t n, bool implementation);
 static inline void
-cb_linagen_defun_vecn_hadamard_prod(CB_Generator *gen, char *type,
-                                    int32_t n, bool implementation);
+cb_linagen_defun_vecn_hadamard_prod(CB_Generator *gen, char *type, int32_t n, bool implementation);
 static inline void
-cb_linagen_defun_vecn_hadamard_div(CB_Generator *gen, char *type,
-                                   int32_t n, bool implementation);
+cb_linagen_defun_vecn_hadamard_div(CB_Generator *gen, char *type, int32_t n, bool implementation);
 static inline void
-cb_linagen_defun_vecn_equal(CB_Generator *gen, char *type,
-                            int32_t n, bool implementation);
+cb_linagen_defun_vecn_equal(CB_Generator *gen, char *type, int32_t n, bool implementation);
 static inline void
-cb_linagen_defun_vecn_near(CB_Generator *gen, char *type,
-                            int32_t n, bool implementation);
+cb_linagen_defun_vecn_near(CB_Generator *gen, char *type, int32_t n, bool implementation);
 static inline void
-cb_linagen_defun_vecn_lerp(CB_Generator *gen, char *type,
-                           int32_t n, bool implementation);
+cb_linagen_defun_vecn_lerp(CB_Generator *gen, char *type, int32_t n, bool implementation);
 static void
-cb_linagen_defun_vecn_scale(CB_Generator *gen, char *type,
-                            int32_t n, bool implementation);
+cb_linagen_defun_vecn_scale(CB_Generator *gen, char *type, int32_t n, bool implementation);
 static void
-cb_linagen_defun_vecn_normalize(CB_Generator *gen, char *type,
-                                int32_t n, bool implementation);
+cb_linagen_defun_vecn_normalize(CB_Generator *gen, char *type, int32_t n, bool implementation);
 static void
-cb_linagen_defun_vecn_dot(CB_Generator *gen, char *type,
-                          int32_t n, bool implementation);
+cb_linagen_defun_vecn_dot(CB_Generator *gen, char *type, int32_t n, bool implementation);
 static void
-cb_linagen_defun_vecn_mulm(CB_Generator *gen, char *type,
-                           int32_t n, bool implementation);
+cb_linagen_defun_vecn_mulm(CB_Generator *gen, char *type, int32_t n, bool implementation);
 static void
-cb_linagen_defun_vecn_magnitude(CB_Generator *gen, char *type,
-                                int32_t n, bool implementation);
+cb_linagen_defun_vecn_magnitude(CB_Generator *gen, char *type, int32_t n, bool implementation);
 static void
-cb_linagen_defun_vecn_magnitude64(CB_Generator *gen, char *type,
-                                  int32_t n, bool implementation);
+cb_linagen_defun_vecn_magnitude64(CB_Generator *gen, char *type, int32_t n, bool implementation);
 static void
-cb_linagen_defun_vecn_distance(CB_Generator *gen, char *type,
-                               int32_t n, bool implementation);
+cb_linagen_defun_vecn_distance(CB_Generator *gen, char *type, int32_t n, bool implementation);
 static void
-cb_linagen_defun_vecn_distance2(CB_Generator *gen, char *type,
-                                int32_t n, bool implementation);
+cb_linagen_defun_vecn_distance2(CB_Generator *gen, char *type, int32_t n, bool implementation);
 
 static inline void
 cb_linagen_defun_vec3_cross(CB_Generator *gen, char *type, bool implementation);
 
 static void
-cb_linagen_defun_matnn_scale(CB_Generator *gen, char *type,
-                             int32_t n, bool implementation);
+cb_linagen_defun_matnn_scale(CB_Generator *gen, char *type, int32_t n, bool implementation);
+static inline void
+cb_linagen_defun_matnn_add(CB_Generator *gen, char *type, int32_t n, bool implementation);
+static inline void
+cb_linagen_defun_matnn_sub(CB_Generator *gen, char *type, int32_t n, bool implementation);
+static inline void
+cb_linagen_defun_matnn_hadamard_prod(CB_Generator *gen, char *type, int32_t n, bool implementation);
+static inline void
+cb_linagen_defun_matnn_hadamard_div(CB_Generator *gen, char *type, int32_t n, bool implementation);
+static void
+cb_linagen_defun_matnn_dot(CB_Generator *gen, char *type, int32_t n, bool implementation);
 static void
-cb_linagen_defun_matnn_mulv(CB_Generator *gen, char *type,
-                            int32_t n, bool implementation);
+cb_linagen_defun_matnn_mulv(CB_Generator *gen, char *type, int32_t n, bool implementation);
 static void
-cb_linagen_defun_matnn_identity(CB_Generator *gen, char *type,
-                                int32_t n, bool implementation);
+cb_linagen_defun_matnn_identity(CB_Generator *gen, char *type, int32_t n, bool implementation);
 
 static void
-cb_linagen_defun_mat4_transform_translate(CB_Generator *gen, char *type,
-                                          bool implementation);
+cb_linagen_defun_mat4_transform_translate_by(CB_Generator *gen, char *type, bool implementation);
 static void
-cb_linagen_defun_mat4_transform_rotate(CB_Generator *gen, char *type,
-                                       bool implementation);
+cb_linagen_defun_mat4_transform_translate_to(CB_Generator *gen, char *type, bool implementation);
 static void
-cb_linagen_defun_mat4_transform_scale(CB_Generator *gen, char *type,
-                                      bool implementation);
+cb_linagen_defun_mat4_transform_rotate(CB_Generator *gen, char *type, bool implementation);
+static void
+cb_linagen_defun_mat4_transform_rotate_rad(CB_Generator *gen, char *type, bool implementation);
+static void
+cb_linagen_defun_mat4_transform_scale(CB_Generator *gen, char *type, bool implementation);
+static void
+cb_linagen_defun_mat4_projection_orthographic(CB_Generator *gen, char *type, bool implementation);
 static void
-cb_linagen_defun_mat4_projection_orthographics(CB_Generator *gen, char *type,
-                                               bool implementation);
+cb_linagen_defun_mat4_projection_perspective(CB_Generator *gen, char *type, bool implementation);
+static void
+cb_linagen_defun_mat4_projection_perspective_rad(CB_Generator *gen, char *type, bool implementation);
 
 // ======================================================================
 // Implementations
-
 static void
 cb_linagen_typedef_vecn(CB_Generator *gen, char *type, int32_t n, ...) {
-  va_list args = {0};
+  va_list args = {};
   va_start(args, n);
   char *suffix = strdup(type);
   *suffix = char_toupper(*type);
   cb_gen_push(gen, cb_format("typedef union {"
                              "\n  %s values[%d];"
+#ifdef __cplusplus
+                             "\n  struct Fields {",
+#else
                              "\n  struct {",
+#endif
                              type, n));
   bool found_last_named_field = false;
   for (int32_t i = 0; i < n; ++i) {
@@ -168,8 +166,7 @@ cb_linagen_typedef_matnn(CB_Generator *gen, char *type, int32_t n) {
 }
 
 static inline void
-cb_linagen_defun_vecn(CB_Generator *gen, char *type,
-                      int32_t n, bool implementation) {
+cb_linagen_defun_vecn(CB_Generator *gen, char *type, int32_t n, bool implementation) {
   char *suffix = strdup(type);
   *suffix = char_toupper(*type);
   cb_gen_push_func_begin(gen, cb_format("linagen_fn Vec%d%s vec%d%s",
@@ -188,39 +185,34 @@ cb_linagen_defun_vecn(CB_Generator *gen, char *type,
 }
 
 static inline void
-cb_linagen_defun_vecn_add(CB_Generator *gen, char *type,
-                          int32_t n, bool implementation) {
+cb_linagen_defun_vecn_add(CB_Generator *gen, char *type, int32_t n, bool implementation) {
   cb_linagen_defun_vecn_element_wise(gen, type, n, implementation, "add", '+');
 }
 
 static inline void
-cb_linagen_defun_vecn_sub(CB_Generator *gen, char *type,
-                          int32_t n, bool implementation) {
+cb_linagen_defun_vecn_sub(CB_Generator *gen, char *type, int32_t n, bool implementation) {
   cb_linagen_defun_vecn_element_wise(gen, type, n, implementation, "sub", '-');
 }
 
 static inline void
-cb_linagen_defun_vecn_hadamard_prod(CB_Generator *gen, char *type,
-                                    int32_t n, bool implementation) {
+cb_linagen_defun_vecn_hadamard_prod(CB_Generator *gen, char *type, int32_t n, bool implementation) {
   cb_linagen_defun_vecn_element_wise(gen, type, n, implementation,
                                      "hadamard_prod", '*');
 }
 
 static inline void
-cb_linagen_defun_vecn_hadamard_div(CB_Generator *gen, char *type,
-                                   int32_t n, bool implementation) {
+cb_linagen_defun_vecn_hadamard_div(CB_Generator *gen, char *type, int32_t n, bool implementation) {
   cb_linagen_defun_vecn_element_wise(gen, type, n, implementation,
                                      "hadamard_div", '/');
 }
 
 static inline void
-cb_linagen_defun_vecn_equal(CB_Generator *gen, char *type,
-                            int32_t n, bool implementation) {
+cb_linagen_defun_vecn_equal(CB_Generator *gen, char *type, int32_t n, bool implementation) {
   char *suffix = strdup(type);
   *suffix = char_toupper(*type);
   cb_gen_push_func_begin(gen, cb_format("linagen_fn bool vec%d%s_equal", n, type));
-    cb_gen_push_func_arg(gen, cb_format("const Vec%d%s *restrict v1", n, suffix));
-    cb_gen_push_func_arg(gen, cb_format("const Vec%d%s *restrict v2", n, suffix));
+    cb_gen_push_func_arg(gen, cb_format("Vec%d%s *v1", n, suffix));
+    cb_gen_push_func_arg(gen, cb_format("Vec%d%s *v2", n, suffix));
   cb_gen_push_func_end(gen, implementation);
   if (!implementation) { return; }
 
@@ -233,35 +225,33 @@ cb_linagen_defun_vecn_equal(CB_Generator *gen, char *type,
 }
 
 static inline void
-cb_linagen_defun_vecn_near(CB_Generator *gen, char *type,
-                            int32_t n, bool implementation) {
+cb_linagen_defun_vecn_near(CB_Generator *gen, char *type, int32_t n, bool implementation) {
   char *suffix = strdup(type);
   *suffix = char_toupper(*type);
   cb_gen_push_func_begin(gen, cb_format("linagen_fn bool vec%d%s_near",
                                         n, type));
-    cb_gen_push_func_arg(gen, cb_format("const Vec%d%s *restrict v1", n, suffix));
-    cb_gen_push_func_arg(gen, cb_format("const Vec%d%s *restrict v2", n, suffix));
-    cb_gen_push_func_arg(gen, "float eps");
+    cb_gen_push_func_arg(gen, cb_format("Vec%d%s *v1", n, suffix));
+    cb_gen_push_func_arg(gen, cb_format("Vec%d%s *v2", n, suffix));
+    cb_gen_push_func_arg(gen, cb_format("%s eps", type));
   cb_gen_push_func_end(gen, implementation);
   if (!implementation) { return; }
 
-  cb_gen_push(gen, " {\n  return ((float)v1->values[0] + eps >= v2->values[0] && (float)v1->values[0] - eps <= v2->values[0])");
+  cb_gen_push(gen, " {\n  return (v1->values[0] + eps >= v2->values[0] && v1->values[0] - eps <= v2->values[0])");
   for (int32_t i = 1; i < n; ++i) {
-    cb_gen_push(gen, cb_format(" &&\n         ((float)v1->values[%d] + eps >= v2->values[%d] && (float)v1->values[%d] - eps <= v2->values[%d])",
+    cb_gen_push(gen, cb_format(" &&\n         (v1->values[%d] + eps >= v2->values[%d] && v1->values[%d] - eps <= v2->values[%d])",
                                i, i, i, i));
   }
   cb_gen_push(gen, ";\n}\n\n");
 }
 
 static inline void
-cb_linagen_defun_vecn_lerp(CB_Generator *gen, char *type,
-                           int32_t n, bool implementation) {
+cb_linagen_defun_vecn_lerp(CB_Generator *gen, char *type, int32_t n, bool implementation) {
   char *suffix = strdup(type);
   *suffix = char_toupper(*type);
   if (n <= CB_LINAGEN_VECN_COPY_CAP) {
     cb_gen_push_func_begin(gen, cb_format("linagen_fn Vec%d%s vec%d%s_lerp", n, suffix, n, type));
-      cb_gen_push_func_arg(gen, cb_format("const Vec%d%s *restrict start", n, suffix));
-      cb_gen_push_func_arg(gen, cb_format("const Vec%d%s *restrict end", n, suffix));
+      cb_gen_push_func_arg(gen, cb_format("Vec%d%s *start", n, suffix));
+      cb_gen_push_func_arg(gen, cb_format("Vec%d%s *end", n, suffix));
       cb_gen_push_func_arg(gen, cb_format("%s t", type));
     cb_gen_push_func_end(gen, implementation);
     if (!implementation) { return; }
@@ -272,9 +262,9 @@ cb_linagen_defun_vecn_lerp(CB_Generator *gen, char *type,
     cb_gen_push(gen, "\n  return res;" "\n}\n\n");
   } else {
     cb_gen_push_func_begin(gen, cb_format("linagen_fn void vec%d%s_lerp", n, type));
-      cb_gen_push_func_arg(gen, cb_format("Vec%d%s *restrict res", n, suffix));
-      cb_gen_push_func_arg(gen, cb_format("const Vec%d%s *restrict start", n, suffix));
-      cb_gen_push_func_arg(gen, cb_format("const Vec%d%s *restrict end", n, suffix));
+      cb_gen_push_func_arg(gen, cb_format("Vec%d%s *res", n, suffix));
+      cb_gen_push_func_arg(gen, cb_format("Vec%d%s *start", n, suffix));
+      cb_gen_push_func_arg(gen, cb_format("Vec%d%s *end", n, suffix));
       cb_gen_push_func_arg(gen, cb_format("%s t", type));
     cb_gen_push_func_end(gen, implementation);
     if (!implementation) { return; }
@@ -286,27 +276,8 @@ cb_linagen_defun_vecn_lerp(CB_Generator *gen, char *type,
   }
 }
 
-static inline void
-cb_linagen_defun_vec3_cross(CB_Generator *gen, char *type,
-                            bool implementation) {
-  char *suffix = strdup(type);
-  *suffix = char_toupper(*type);
-  cb_gen_push_func_begin(gen, cb_format("linagen_fn Vec3%s vec3%s_cross", suffix, type));
-    cb_gen_push_func_arg(gen, cb_format("Vec3%s v1", suffix));
-    cb_gen_push_func_arg(gen, cb_format("Vec3%s v2", suffix));
-  cb_gen_push_func_end(gen, implementation);
-  if (!implementation) { return; }
-
-  cb_gen_push(gen, cb_format(" {" "\n  Vec3%s res = {0};", suffix));
-  cb_gen_push(gen, "\n  res.values[0] = v1.values[1] * v2.values[2] - v1.values[2] * v2.values[1];");
-  cb_gen_push(gen, "\n  res.values[1] = v1.values[2] * v2.values[0] - v1.values[0] * v2.values[2];");
-  cb_gen_push(gen, "\n  res.values[2] = v1.values[0] * v2.values[1] - v1.values[1] * v2.values[0];");
-  cb_gen_push(gen, "\n  return res;" "\n}\n\n");
-}
-
 static void
-cb_linagen_defun_vecn_scale(CB_Generator *gen, char *type,
-                            int32_t n, bool implementation) {
+cb_linagen_defun_vecn_scale(CB_Generator *gen, char *type, int32_t n, bool implementation) {
   char *suffix = strdup(type);
   *suffix = char_toupper(*type);
   if (n <= CB_LINAGEN_VECN_COPY_CAP) {
@@ -323,7 +294,7 @@ cb_linagen_defun_vecn_scale(CB_Generator *gen, char *type,
   } else {
     cb_gen_push_func_begin(gen, cb_format("linagen_fn void vec%d%s_scale", n, type));
       cb_gen_push_func_arg(gen, cb_format("Vec%d%s *res", n, suffix));
-      cb_gen_push_func_arg(gen, cb_format("const Vec%d%s *v1", n, suffix));
+      cb_gen_push_func_arg(gen, cb_format("Vec%d%s *v1", n, suffix));
       cb_gen_push_func_arg(gen, cb_format("%s k", type));
     cb_gen_push_func_end(gen, implementation);
     if (!implementation) { return; }
@@ -336,8 +307,7 @@ cb_linagen_defun_vecn_scale(CB_Generator *gen, char *type,
 }
 
 static void
-cb_linagen_defun_vecn_normalize(CB_Generator *gen, char *type,
-                                int32_t n, bool implementation) {
+cb_linagen_defun_vecn_normalize(CB_Generator *gen, char *type, int32_t n, bool implementation) {
   char *suffix = strdup(type);
   *suffix = char_toupper(*type);
   if (n <= CB_LINAGEN_VECN_COPY_CAP) {
@@ -352,13 +322,13 @@ cb_linagen_defun_vecn_normalize(CB_Generator *gen, char *type,
     cb_gen_push(gen, "\n  float magnitude = sqrtf((float)dot);"
                      "\n  if (magnitude == 0.f) { return v; }");
     for (int32_t i = 0; i < n; ++i) {
-      cb_gen_push(gen, cb_format("\n  v.values[%d] /= magnitude;", i, type));
+      cb_gen_push(gen, cb_format("\n  v.values[%d] /= (%s)magnitude;", i, type));
     }
     cb_gen_push(gen, "\n  return v;" "\n}\n\n");
   } else {
     cb_gen_push_func_begin(gen, cb_format("linagen_fn void vec%d%s_normalize", n, type));
       cb_gen_push_func_arg(gen, cb_format("Vec%d%s *res", n, suffix));
-      cb_gen_push_func_arg(gen, cb_format("const Vec%d%s *v1", n, suffix));
+      cb_gen_push_func_arg(gen, cb_format("Vec%d%s *v1", n, suffix));
     cb_gen_push_func_end(gen, implementation);
     if (!implementation) { return; }
     cb_gen_push(gen, cb_format(" {\n  %s dot = {0};", type));
@@ -376,13 +346,12 @@ cb_linagen_defun_vecn_normalize(CB_Generator *gen, char *type,
 }
 
 static void
-cb_linagen_defun_vecn_dot(CB_Generator *gen, char *type,
-                          int32_t n, bool implementation) {
+cb_linagen_defun_vecn_dot(CB_Generator *gen, char *type, int32_t n, bool implementation) {
   char *suffix = strdup(type);
   *suffix = char_toupper(*type);
   cb_gen_push_func_begin(gen, cb_format("linagen_fn %s vec%d%s_dot", type, n, type));
-    cb_gen_push_func_arg(gen, cb_format("const Vec%d%s *v1", n, suffix));
-    cb_gen_push_func_arg(gen, cb_format("const Vec%d%s *v2", n, suffix));
+    cb_gen_push_func_arg(gen, cb_format("Vec%d%s *v1", n, suffix));
+    cb_gen_push_func_arg(gen, cb_format("Vec%d%s *v2", n, suffix));
   cb_gen_push_func_end(gen, implementation);
   if (!implementation) { return; }
 
@@ -394,19 +363,63 @@ cb_linagen_defun_vecn_dot(CB_Generator *gen, char *type,
 }
 
 static void
-cb_linagen_defun_vecn_magnitude(CB_Generator *gen, char *type,
-                                int32_t n, bool implementation) {
+cb_linagen_defun_vecn_mulm(CB_Generator *gen, char *type, int32_t n, bool implementation) {
+  char *suffix = strdup(type);
+  *suffix = char_toupper(*type);
+  if (n < MIN(CB_LINAGEN_VECN_COPY_CAP, CB_LINAGEN_MATNN_COPY_CAP)) {
+    cb_gen_push_func_begin(gen, cb_format("linagen_fn Vec%d%s vec%d%s_mulm", n, suffix, n, type));
+      cb_gen_push_func_arg(gen, cb_format("Vec%d%s v", n, suffix));
+      cb_gen_push_func_arg(gen, cb_format("Mat%d%s m", n, suffix));
+    cb_gen_push_func_end(gen, implementation);
+    if (!implementation) { return; }
+    cb_gen_push(gen, cb_format(" {" "\n  Vec%d%s res = {0};", n, suffix));
+    for (int32_t i = 0; i < n; ++i) {
+      char *prefix = "";
+      cb_gen_push(gen, cb_format("\n  res.values[%d] = ", i));
+      for (int32_t j = 0; j < n; ++j) {
+        cb_gen_push(gen, cb_format("%s(v.values[%d] * m.values[%d][%d])",
+                                   prefix, j, i, j));
+        prefix = " + ";
+      }
+      cb_gen_push(gen, ";");
+    }
+    cb_gen_push(gen, "\n  return res;" "\n}\n\n");
+  } else {
+    cb_gen_push_func_begin(gen, cb_format("linagen_fn void vec%d%s_mulm", n, type));
+      cb_gen_push_func_arg(gen, cb_format("Vec%d%s *res", n, suffix));
+      cb_gen_push_func_arg(gen, cb_format("Vec%d%s *v", n, suffix));
+      cb_gen_push_func_arg(gen, cb_format("Mat%d%s *m", n, suffix));
+    cb_gen_push_func_end(gen, implementation);
+    if (!implementation) { return; }
+
+    cb_gen_push(gen, " {");
+    for (int32_t i = 0; i < n; ++i) {
+      char *prefix = "";
+      cb_gen_push(gen, cb_format("\n  res->values[%d] = ", i));
+      for (int32_t j = 0; j < n; ++j) {
+        cb_gen_push(gen, cb_format("%s(v->values[%d] * m->values[%d][%d])",
+                                   prefix, j, i, j));
+        prefix = " + ";
+      }
+      cb_gen_push(gen, ";");
+    }
+    cb_gen_push(gen, "\n}\n\n");
+  }
+}
+
+static void
+cb_linagen_defun_vecn_magnitude(CB_Generator *gen, char *type, int32_t n, bool implementation) {
   char *suffix = strdup(type);
   *suffix = char_toupper(*type);
   cb_gen_push_func_begin(gen, cb_format("linagen_fn float vec%d%s_magnitude",
                                         n, type));
-    cb_gen_push_func_arg(gen, cb_format("const Vec%d%s *v1", n, suffix));
+    cb_gen_push_func_arg(gen, cb_format("Vec%d%s *v1", n, suffix));
   cb_gen_push_func_end(gen, implementation);
   if (!implementation) { return; }
 
   cb_gen_push(gen, " {\n  float dot = {0};");
   for (int32_t i = 0; i < n; ++i) {
-    cb_gen_push(gen, cb_format("\n  dot += v1->values[%d] * v1->values[%d];",
+    cb_gen_push(gen, cb_format("\n  dot += (float)(v1->values[%d] * v1->values[%d]);",
                                i, i));
   }
   cb_gen_push(gen, "\n  float res = sqrtf(dot);"
@@ -415,19 +428,18 @@ cb_linagen_defun_vecn_magnitude(CB_Generator *gen, char *type,
 }
 
 static void
-cb_linagen_defun_vecn_magnitude64(CB_Generator *gen, char *type,
-                                  int32_t n, bool implementation) {
+cb_linagen_defun_vecn_magnitude64(CB_Generator *gen, char *type, int32_t n, bool implementation) {
   char *suffix = strdup(type);
   *suffix = char_toupper(*type);
   cb_gen_push_func_begin(gen, cb_format("linagen_fn double vec%d%s_magnitude64",
                                         n, type));
-    cb_gen_push_func_arg(gen, cb_format("const Vec%d%s *v1", n, suffix));
+    cb_gen_push_func_arg(gen, cb_format("Vec%d%s *v1", n, suffix));
   cb_gen_push_func_end(gen, implementation);
   if (!implementation) { return; }
 
   cb_gen_push(gen, " {\n  double dot = {0};");
   for (int32_t i = 0; i < n; ++i) {
-    cb_gen_push(gen, cb_format("\n  dot += v1->values[%d] * v1->values[%d];",
+    cb_gen_push(gen, cb_format("\n  dot += (double)(v1->values[%d] * v1->values[%d]);",
                                i, i));
   }
   cb_gen_push(gen, "\n  double res = sqrt(dot);"
@@ -436,14 +448,13 @@ cb_linagen_defun_vecn_magnitude64(CB_Generator *gen, char *type,
 }
 
 static void
-cb_linagen_defun_vecn_distance(CB_Generator *gen, char *type,
-                               int32_t n, bool implementation) {
+cb_linagen_defun_vecn_distance(CB_Generator *gen, char *type, int32_t n, bool implementation) {
   char *suffix = strdup(type);
   *suffix = char_toupper(*type);
   cb_gen_push_func_begin(gen, cb_format("linagen_fn float vec%d%s_distance",
                                         n, type));
-    cb_gen_push_func_arg(gen, cb_format("const Vec%d%s *restrict v1", n, suffix));
-    cb_gen_push_func_arg(gen, cb_format("const Vec%d%s *restrict v2", n, suffix));
+    cb_gen_push_func_arg(gen, cb_format("Vec%d%s *v1", n, suffix));
+    cb_gen_push_func_arg(gen, cb_format("Vec%d%s *v2", n, suffix));
   cb_gen_push_func_end(gen, implementation);
   if (!implementation) { return; }
 
@@ -452,9 +463,9 @@ cb_linagen_defun_vecn_distance(CB_Generator *gen, char *type,
     cb_gen_push(gen, cb_format("\n  diff.values[%d] = v1->values[%d] - v2->values[%d];", i, i, i));
   }
 
-  cb_gen_push(gen, cb_format("\n  %s dot = {0};", type));
+  cb_gen_push(gen, "\n  float dot = {0};");
   for (int32_t i = 0; i < n; ++i) {
-    cb_gen_push(gen, cb_format("\n  dot += diff.values[%d] * diff.values[%d];",
+    cb_gen_push(gen, cb_format("\n  dot += (float)(diff.values[%d] * diff.values[%d]);",
                                i, i));
   }
   cb_gen_push(gen, "\n  float res = sqrtf(dot);"
@@ -463,14 +474,13 @@ cb_linagen_defun_vecn_distance(CB_Generator *gen, char *type,
 }
 
 static void
-cb_linagen_defun_vecn_distance2(CB_Generator *gen, char *type,
-                                int32_t n, bool implementation) {
+cb_linagen_defun_vecn_distance2(CB_Generator *gen, char *type, int32_t n, bool implementation) {
   char *suffix = strdup(type);
   *suffix = char_toupper(*type);
   cb_gen_push_func_begin(gen, cb_format("linagen_fn float vec%d%s_distance2",
                                         n, type));
-    cb_gen_push_func_arg(gen, cb_format("const Vec%d%s *restrict v1", n, suffix));
-    cb_gen_push_func_arg(gen, cb_format("const Vec%d%s *restrict v2", n, suffix));
+    cb_gen_push_func_arg(gen, cb_format("Vec%d%s *v1", n, suffix));
+    cb_gen_push_func_arg(gen, cb_format("Vec%d%s *v2", n, suffix));
   cb_gen_push_func_end(gen, implementation);
   if (!implementation) { return; }
 
@@ -479,64 +489,34 @@ cb_linagen_defun_vecn_distance2(CB_Generator *gen, char *type,
     cb_gen_push(gen, cb_format("\n  diff.values[%d] = v1->values[%d] - v2->values[%d];", i, i, i));
   }
 
-  cb_gen_push(gen, cb_format("\n  %s dot = {0};", type));
+  cb_gen_push(gen, "\n  float dot = {0};");
   for (int32_t i = 0; i < n; ++i) {
-    cb_gen_push(gen, cb_format("\n  dot += diff.values[%d] * diff.values[%d];",
+    cb_gen_push(gen, cb_format("\n  dot += (float)(diff.values[%d] * diff.values[%d]);",
                                i, i));
   }
   cb_gen_push(gen, "\n  return dot;"
                    "\n}\n\n");
 }
 
-static void
-cb_linagen_defun_vecn_mulm(CB_Generator *gen, char *type,
-                           int32_t n, bool implementation) {
+static inline void
+cb_linagen_defun_vec3_cross(CB_Generator *gen, char *type, bool implementation) {
   char *suffix = strdup(type);
   *suffix = char_toupper(*type);
-  if (n < MIN(CB_LINAGEN_VECN_COPY_CAP, CB_LINAGEN_MATNN_COPY_CAP)) {
-    cb_gen_push_func_begin(gen, cb_format("linagen_fn Vec%d%s vec%d%s_mulm", n, suffix, n, type));
-      cb_gen_push_func_arg(gen, cb_format("Vec%d%s v", n, suffix));
-      cb_gen_push_func_arg(gen, cb_format("Mat%d%s m", n, suffix));
-    cb_gen_push_func_end(gen, implementation);
-    if (!implementation) { return; }
-    cb_gen_push(gen, cb_format(" {" "\n  Vec%d%s res = {0};", n, suffix));
-    for (int32_t i = 0; i < n; ++i) {
-      char *prefix = "";
-      cb_gen_push(gen, cb_format("\n  res.values[%d] = ", i));
-      for (int32_t j = 0; j < n; ++j) {
-        cb_gen_push(gen, cb_format("%s(v.values[%d] * m.values[%d][%d])",
-                                   prefix, j, i, j));
-        prefix = " + ";
-      }
-      cb_gen_push(gen, ";");
-    }
-    cb_gen_push(gen, "\n  return res;" "\n}\n\n");
-  } else {
-    cb_gen_push_func_begin(gen, cb_format("linagen_fn void vec%d%s_mulm", n, type));
-      cb_gen_push_func_arg(gen, cb_format("Vec%d%s *restrict res", n, suffix));
-      cb_gen_push_func_arg(gen, cb_format("const Vec%d%s *restrict v", n, suffix));
-      cb_gen_push_func_arg(gen, cb_format("const Mat%d%s *restrict m", n, suffix));
-    cb_gen_push_func_end(gen, implementation);
-    if (!implementation) { return; }
+  cb_gen_push_func_begin(gen, cb_format("linagen_fn Vec3%s vec3%s_cross", suffix, type));
+    cb_gen_push_func_arg(gen, cb_format("Vec3%s v1", suffix));
+    cb_gen_push_func_arg(gen, cb_format("Vec3%s v2", suffix));
+  cb_gen_push_func_end(gen, implementation);
+  if (!implementation) { return; }
 
-    cb_gen_push(gen, " {");
-    for (int32_t i = 0; i < n; ++i) {
-      char *prefix = "";
-      cb_gen_push(gen, cb_format("\n  res->values[%d] = ", i));
-      for (int32_t j = 0; j < n; ++j) {
-        cb_gen_push(gen, cb_format("%s(v->values[%d] * m->values[%d][%d])",
-                                   prefix, j, i, j));
-        prefix = " + ";
-      }
-      cb_gen_push(gen, ";");
-    }
-    cb_gen_push(gen, "\n}\n\n");
-  }
+  cb_gen_push(gen, cb_format(" {" "\n  Vec3%s res = {0};", suffix));
+  cb_gen_push(gen, "\n  res.values[0] = v1.values[1] * v2.values[2] - v1.values[2] * v2.values[1];");
+  cb_gen_push(gen, "\n  res.values[1] = v1.values[2] * v2.values[0] - v1.values[0] * v2.values[2];");
+  cb_gen_push(gen, "\n  res.values[2] = v1.values[0] * v2.values[1] - v1.values[1] * v2.values[0];");
+  cb_gen_push(gen, "\n  return res;" "\n}\n\n");
 }
 
 static void
-cb_linagen_defun_matnn_scale(CB_Generator *gen, char *type,
-                             int32_t n, bool implementation) {
+cb_linagen_defun_matnn_scale(CB_Generator *gen, char *type, int32_t n, bool implementation) {
   char *suffix = strdup(type);
   *suffix = char_toupper(*type);
   if (n < CB_LINAGEN_MATNN_COPY_CAP) {
@@ -556,7 +536,7 @@ cb_linagen_defun_matnn_scale(CB_Generator *gen, char *type,
   } else {
     cb_gen_push_func_begin(gen, cb_format("linagen_fn void mat%d%s_scale", n, type));
       cb_gen_push_func_arg(gen, cb_format("Mat%d%s *res", n, suffix));
-      cb_gen_push_func_arg(gen, cb_format("const Mat%d%s *m1", n, suffix));
+      cb_gen_push_func_arg(gen, cb_format("Mat%d%s *m1", n, suffix));
       cb_gen_push_func_arg(gen, cb_format("%s k", type));
     cb_gen_push_func_end(gen, implementation);
     if (!implementation) { return; }
@@ -573,34 +553,29 @@ cb_linagen_defun_matnn_scale(CB_Generator *gen, char *type,
 }
 
 static inline void
-cb_linagen_defun_matnn_add(CB_Generator *gen, char *type,
-                           int32_t n, bool implementation) {
+cb_linagen_defun_matnn_add(CB_Generator *gen, char *type, int32_t n, bool implementation) {
   cb_linagen_defun_matnn_element_wise(gen, type, n, implementation, "add", '+');
 }
 
 static inline void
-cb_linagen_defun_matnn_sub(CB_Generator *gen, char *type,
-                           int32_t n, bool implementation) {
+cb_linagen_defun_matnn_sub(CB_Generator *gen, char *type, int32_t n, bool implementation) {
   cb_linagen_defun_matnn_element_wise(gen, type, n, implementation, "sub", '-');
 }
 
 static inline void
-cb_linagen_defun_matnn_hadamard_prod(CB_Generator *gen, char *type,
-                                     int32_t n, bool implementation) {
+cb_linagen_defun_matnn_hadamard_prod(CB_Generator *gen, char *type, int32_t n, bool implementation) {
   cb_linagen_defun_matnn_element_wise(gen, type, n, implementation,
                                       "hadamard_prod", '*');
 }
 
 static inline void
-cb_linagen_defun_matnn_hadamard_div(CB_Generator *gen, char *type,
-                                    int32_t n, bool implementation) {
+cb_linagen_defun_matnn_hadamard_div(CB_Generator *gen, char *type, int32_t n, bool implementation) {
   cb_linagen_defun_matnn_element_wise(gen, type, n, implementation,
                                       "hadamard_div", '/');
 }
 
 static void
-cb_linagen_defun_matnn_dot(CB_Generator *gen, char *type,
-                           int32_t n, bool implementation) {
+cb_linagen_defun_matnn_dot(CB_Generator *gen, char *type, int32_t n, bool implementation) {
   char *suffix = strdup(type);
   *suffix = char_toupper(*type);
   if (n <= CB_LINAGEN_MATNN_COPY_CAP) {
@@ -626,9 +601,9 @@ cb_linagen_defun_matnn_dot(CB_Generator *gen, char *type,
     cb_gen_push(gen, "\n  return res;" "\n}\n\n");
   } else {
     cb_gen_push_func_begin(gen, cb_format("linagen_fn void mat%d%s_dot", n, type));
-      cb_gen_push_func_arg(gen, cb_format("Mat%d%s *restrict res", n, suffix));
-      cb_gen_push_func_arg(gen, cb_format("const Mat%d%s *m1", n, suffix));
-      cb_gen_push_func_arg(gen, cb_format("const Mat%d%s *m2", n, suffix));
+      cb_gen_push_func_arg(gen, cb_format("Mat%d%s *res", n, suffix));
+      cb_gen_push_func_arg(gen, cb_format("Mat%d%s *m1", n, suffix));
+      cb_gen_push_func_arg(gen, cb_format("Mat%d%s *m2", n, suffix));
     cb_gen_push_func_end(gen, implementation);
     if (!implementation) { return; }
 
@@ -650,8 +625,7 @@ cb_linagen_defun_matnn_dot(CB_Generator *gen, char *type,
 }
 
 static void
-cb_linagen_defun_matnn_mulv(CB_Generator *gen, char *type,
-                            int32_t n, bool implementation) {
+cb_linagen_defun_matnn_mulv(CB_Generator *gen, char *type, int32_t n, bool implementation) {
   char *suffix = strdup(type);
   *suffix = char_toupper(*type);
   if (n <= CB_LINAGEN_MATNN_COPY_CAP) {
@@ -675,9 +649,9 @@ cb_linagen_defun_matnn_mulv(CB_Generator *gen, char *type,
     cb_gen_push(gen, "\n  return res;" "\n}\n\n");
   } else {
     cb_gen_push_func_begin(gen, cb_format("linagen_fn void mat%d%s_mulv", n, type));
-      cb_gen_push_func_arg(gen, cb_format("Vec%d%s *restrict res", n, suffix));
-      cb_gen_push_func_arg(gen, cb_format("const Mat%d%s *restrict m", n, suffix));
-      cb_gen_push_func_arg(gen, cb_format("const Vec%d%s *restrict v", n, suffix));
+      cb_gen_push_func_arg(gen, cb_format("Vec%d%s *res", n, suffix));
+      cb_gen_push_func_arg(gen, cb_format("Mat%d%s *m", n, suffix));
+      cb_gen_push_func_arg(gen, cb_format("Vec%d%s *v", n, suffix));
     cb_gen_push_func_end(gen, implementation);
     if (!implementation) { return; }
 
@@ -697,8 +671,7 @@ cb_linagen_defun_matnn_mulv(CB_Generator *gen, char *type,
 }
 
 static void
-cb_linagen_defun_matnn_identity(CB_Generator *gen, char *type,
-                                int32_t n, bool implementation) {
+cb_linagen_defun_matnn_identity(CB_Generator *gen, char *type, int32_t n, bool implementation) {
   char *suffix = strdup(type);
   *suffix = char_toupper(*type);
   if (n <= CB_LINAGEN_MATNN_COPY_CAP) {
@@ -892,6 +865,30 @@ cb_linagen_defun_mat4_projection_perspective(CB_Generator *gen, char *type,
   char *suffix = strdup(type);
   *suffix = char_toupper(*type);
   cb_gen_push_func_begin(gen, cb_format("linagen_fn Mat4%s mat4%s_projection_perspective", suffix, type));
+    cb_gen_push_func_arg(gen, cb_format("float yfov_degree, float aspect_ratio, float near, float far"));
+  cb_gen_push_func_end(gen, implementation);
+  if (!implementation) { return; }
+
+  cb_gen_push(gen, cb_format(" {"
+                             "\n  float yfov_radians = yfov_degree * %.16ff / 180.f;"
+                             "\n  %s top = near * tanf(yfov_radians/2);"
+                             "\n  %s right = top * aspect_ratio;"
+                             "\n  Mat4%s res = {0};"
+                             "\n  res.arr[0] =  near / right;"
+                             "\n  res.arr[5] =  near / top;"
+                             "\n  res.arr[10] =  -(far + near) / (far - near);"
+                             "\n  res.arr[11] =  -1;"
+                             "\n  res.arr[14] =  -(2 * far * near) / (far - near);",
+                             M_PI, type, type, suffix, suffix));
+  cb_gen_push(gen, "\n  return res;" "\n}\n\n");
+}
+
+static void
+cb_linagen_defun_mat4_projection_perspective_rad(CB_Generator *gen, char *type,
+                                                 bool implementation) {
+  char *suffix = strdup(type);
+  *suffix = char_toupper(*type);
+  cb_gen_push_func_begin(gen, cb_format("linagen_fn Mat4%s mat4%s_projection_perspective_rad", suffix, type));
     cb_gen_push_func_arg(gen, cb_format("float yfov_radians, float aspect_ratio, float near, float far"));
   cb_gen_push_func_end(gen, implementation);
   if (!implementation) { return; }
@@ -934,8 +931,8 @@ cb_linagen_defun_vecn_element_wise(CB_Generator *gen, char *type,
     cb_gen_push_func_begin(gen, cb_format("linagen_fn void vec%d%s_%s",
                                           n, type, func_name));
     cb_gen_push_func_arg(gen, cb_format("Vec%d%s *res", n, suffix));
-    cb_gen_push_func_arg(gen, cb_format("const Vec%d%s *v1", n, suffix));
-    cb_gen_push_func_arg(gen, cb_format("const Vec%d%s *v2", n, suffix));
+    cb_gen_push_func_arg(gen, cb_format("Vec%d%s *v1", n, suffix));
+    cb_gen_push_func_arg(gen, cb_format("Vec%d%s *v2", n, suffix));
     cb_gen_push_func_end(gen, implementation);
     if (!implementation) { return; }
 
@@ -965,7 +962,7 @@ cb_linagen_defun_matnn_element_wise(CB_Generator *gen, char *type,
     cb_gen_push(gen, cb_format(" {" "\n  Mat%d%s res = {0};", n, suffix));
     for (int32_t i = 0; i < n; ++i) {
       for (int32_t j = 0; j < n; ++j) {
-        cb_gen_push(gen, cb_format("\n  res.values[%d][%d] = m1->values[%d][%d] %c m2->values[%d][%d];",
+        cb_gen_push(gen, cb_format("\n  res.values[%d][%d] = m1.values[%d][%d] %c m2.values[%d][%d];",
                                    i, j, i, j, op, i, j));
       }
     }
@@ -974,8 +971,8 @@ cb_linagen_defun_matnn_element_wise(CB_Generator *gen, char *type,
     cb_gen_push_func_begin(gen, cb_format("linagen_fn void mat%d%s_%s",
                                           n, type, func_name));
       cb_gen_push_func_arg(gen, cb_format("Mat%d%s *res", n, suffix));
-      cb_gen_push_func_arg(gen, cb_format("const Mat%d%s *m1", n, suffix));
-      cb_gen_push_func_arg(gen, cb_format("const Mat%d%s *m2", n, suffix));
+      cb_gen_push_func_arg(gen, cb_format("Mat%d%s *m1", n, suffix));
+      cb_gen_push_func_arg(gen, cb_format("Mat%d%s *m2", n, suffix));
     cb_gen_push_func_end(gen, implementation);
     if (!implementation) { return; }
 
index 49708a75fec112076542d7dbb27e4c7cef91339e..f0a8d41f54d39b804f296adab047131cbfe4dd16 100644 (file)
@@ -6,7 +6,7 @@
 typedef void cb_test_func(void);
 
 struct CB_Test {
-  const char *name;
+  char *name;
   cb_test_func *function;
 };
 
@@ -30,8 +30,8 @@ typedef void cb_w32_test_func_init(void);
   __attribute__((constructor))               \
   internal void register_##FUNC_NAME(void) { \
     cb_test_register((struct CB_Test) {      \
-      .function = &FUNC_NAME,                \
       .name = #FUNC_NAME,                    \
+      .function = &FUNC_NAME,                \
     });                                      \
   }                                          \
   static void FUNC_NAME(void)
@@ -40,20 +40,20 @@ typedef void cb_w32_test_func_init(void);
 static void cb_test_run(void);
 
 internal void cb_test_register(struct CB_Test test);
-internal void cb_assertion_test(const char *condition,
-                                const char *file,
+internal void cb_assertion_test(char *condition,
+                                char *file,
                                 int32_t line);
 
 
 // ======================================================================
 // Implementations
-internal jmp_buf test_runner_jmpbuf = {0};
+internal jmp_buf test_runner_jmpbuf;
 
 internal struct {
   struct CB_Test *tests;
   size_t count;
   size_t capacity;
-} cb_tests = {0};
+} cb_tests;
 
 static void cb_test_run(void) {
   int32_t test_passed_count = 0;
@@ -76,8 +76,8 @@ internal void cb_test_register(struct CB_Test test) {
                      tests, count, capacity);
 }
 
-internal void cb_assertion_test(const char *condition,
-                                const char *file, int32_t line) {
+internal void cb_assertion_test(char *condition,
+                                char *file, int32_t line) {
   printf(ANSI_COLOR_RED "FAILED" ANSI_COLOR_RESET
          ": `%s` (%s:%d)\n", condition, file, line);
   longjmp(test_runner_jmpbuf, 1);