static inline void
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);
+static inline void
+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);
+static inline void
+cb_linagen_defun_vec3_cross(CB_Generator *gen, char *type, bool implementation);
static void
cb_linagen_defun_vecn_scale(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);
+static void
+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);
static inline void
cb_linagen_defun_vecn_add_assign(CB_Generator *gen, char *type,
// ======================================================================
// Implementations
+
static void
cb_linagen_typedef_vecn(CB_Generator *gen, char *type, int32_t n, ...) {
va_list args = {0};
"hadamard_div", '/');
}
+static inline void
+cb_linagen_defun_vecn_equal(CB_Generator *gen, char *type,
+ int32_t n, bool implementation) {
+ char *vec_suffix = strdup(type);
+ *vec_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("Vec%d%s v1", n, vec_suffix));
+ cb_gen_push_func_arg(gen, cb_format("Vec%d%s v2", n, vec_suffix));
+ cb_gen_push_func_end(gen, implementation);
+ if (!implementation) { return; }
+
+ cb_gen_push(gen, " {\n return v1.values[0] == v2.values[0]");
+ for (int32_t i = 1; i < n; ++i) {
+ cb_gen_push(gen, cb_format(" &&\n v1.values[%d] == v2.values[%d]",
+ i, i));
+ }
+ cb_gen_push(gen, ";\n}\n\n");
+}
+
+static inline void
+cb_linagen_defun_vecn_near(CB_Generator *gen, char *type,
+ int32_t n, bool implementation) {
+ char *vec_suffix = strdup(type);
+ *vec_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("Vec%d%s v1", n, vec_suffix));
+ cb_gen_push_func_arg(gen, cb_format("Vec%d%s v2", n, vec_suffix));
+ cb_gen_push_func_arg(gen, "float eps");
+ 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])");
+ 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])",
+ 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) {
+ char *vec_suffix = strdup(type);
+ *vec_suffix = char_toupper(*type);
+ cb_gen_push_func_begin(gen, cb_format("linagen_fn Vec%d%s vec%d%s_lerp",
+ n, vec_suffix, n, type));
+ cb_gen_push_func_arg(gen, cb_format("Vec%d%s start", n, vec_suffix));
+ cb_gen_push_func_arg(gen, cb_format("Vec%d%s end", n, vec_suffix));
+ cb_gen_push_func_arg(gen, cb_format("%s t", type));
+ cb_gen_push_func_end(gen, implementation);
+ if (!implementation) { return; }
+
+ cb_gen_push(gen, cb_format(" {\n Vec%d%s res = {0};", n, vec_suffix));
+ for (int32_t i = 0; i < n; ++i) {
+ cb_gen_push(gen, cb_format("\n res.values[%d] = start.values[%d] * (1 - t) + end.values[%d] * t;", i, i, i));
+ }
+ cb_gen_push(gen, "\n return res;"
+ "\n}\n\n");
+}
+
+static inline void
+cb_linagen_defun_vec3_cross(CB_Generator *gen, char *type,
+ bool implementation) {
+ char *vec_suffix = strdup(type);
+ *vec_suffix = char_toupper(*type);
+ cb_gen_push_func_begin(gen, cb_format("linagen_fn Vec3%s vec3%s_cross",
+ vec_suffix, type));
+ cb_gen_push_func_arg(gen, cb_format("Vec3%s v1", vec_suffix));
+ cb_gen_push_func_arg(gen, cb_format("Vec3%s v2", vec_suffix));
+ cb_gen_push_func_end(gen, implementation);
+ if (!implementation) { return; }
+
+ cb_gen_push(gen, cb_format(" {" "\n Vec3%s res = {0};", vec_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_gen_push_func_end(gen, implementation);
if (!implementation) { return; }
- // NOTE(lb): should generated function use other generated functions,
- // or should they completely independent from each other?
- cb_gen_push(gen, cb_format(" {"
- "\n Vec%d%s res = vec%d%s_scale(v1, ((%s)1) / vec%d%s_magnitude(v1));",
- n, vec_suffix, n, type, type, n, type));
+ cb_gen_push(gen, cb_format(" {\n %s dot = {0};", type));
+ for (int32_t i = 0; i < n; ++i) {
+ cb_gen_push(gen, cb_format("\n dot += v1.values[%d] * v1.values[%d];", i, i, i));
+ }
+
+ cb_gen_push(gen, cb_format("\n float magnitude = sqrtf((float)dot);" ,
+ n, type));
+
+ cb_gen_push(gen, cb_format("\n Vec%d%s res = {0};"
+ "\n if (magnitude == 0.f) { return res; }",
+ n, vec_suffix));
+ for (int32_t i = 0; i < n; ++i) {
+ cb_gen_push(gen, cb_format("\n res.values[%d] = v1.values[%d] / magnitude;",
+ i, i, type));
+ }
+
cb_gen_push(gen, "\n return res;"
"\n}\n\n");
}
"\n}\n\n");
}
+static void
+cb_linagen_defun_vecn_distance(CB_Generator *gen, char *type,
+ int32_t n, bool implementation) {
+ char *vec_suffix = strdup(type);
+ *vec_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("Vec%d%s v1", n, vec_suffix));
+ cb_gen_push_func_arg(gen, cb_format("Vec%d%s v2", n, vec_suffix));
+ cb_gen_push_func_end(gen, implementation);
+ if (!implementation) { return; }
+
+ cb_gen_push(gen, " {");
+ for (int32_t i = 0; i < n; ++i) {
+ cb_gen_push(gen, cb_format("\n v1.values[%d] -= v2.values[%d];", i, i));
+ }
+
+ cb_gen_push(gen, cb_format("\n %s dot = {0};", type));
+ for (int32_t i = 0; i < n; ++i) {
+ cb_gen_push(gen, cb_format("\n dot += v1.values[%d] * v1.values[%d];",
+ i, i));
+ }
+ cb_gen_push(gen, "\n float res = sqrtf(dot);"
+ "\n return res;"
+ "\n}\n\n");
+}
+
+static void
+cb_linagen_defun_vecn_distance2(CB_Generator *gen, char *type,
+ int32_t n, bool implementation) {
+ char *vec_suffix = strdup(type);
+ *vec_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("Vec%d%s v1", n, vec_suffix));
+ cb_gen_push_func_arg(gen, cb_format("Vec%d%s v2", n, vec_suffix));
+ cb_gen_push_func_end(gen, implementation);
+ if (!implementation) { return; }
+
+ cb_gen_push(gen, " {");
+ for (int32_t i = 0; i < n; ++i) {
+ cb_gen_push(gen, cb_format("\n v1.values[%d] -= v2.values[%d];", i, i));
+ }
+
+ cb_gen_push(gen, cb_format("\n %s res = {0};", type));
+ for (int32_t i = 0; i < n; ++i) {
+ cb_gen_push(gen, cb_format("\n res += v1.values[%d] * v1.values[%d];",
+ i, i));
+ }
+ cb_gen_push(gen, "\n return res;"
+ "\n}\n\n");
+}
+
static inline void
cb_linagen_defun_vecn_add_assign(CB_Generator *gen, char *type,
int32_t n, bool implementation) {
int32_t n, bool implementation) {
char *vec_suffix = strdup(type);
*vec_suffix = char_toupper(*type);
- cb_gen_push_func_begin(gen, cb_format("linagen_fn Vec%d%s vec%d%s_normalize_assign",
- n, vec_suffix, n, type));
+ cb_gen_push_func_begin(gen, cb_format("linagen_fn void vec%d%s_normalize_assign",
+ n, type));
cb_gen_push_func_arg(gen, cb_format("Vec%d%s *v1", n, vec_suffix));
cb_gen_push_func_end(gen, implementation);
if (!implementation) { return; }
- cb_gen_push(gen, cb_format(" {"
- "\n vec%d%s_scale_assign(v1, ((%s)1) / vec%d%s_magnitude(*v1));"
- "\n}\n\n",
- n, type, type, n, type));
+ cb_gen_push(gen, cb_format(" {\n %s dot = {0};", type));
+ for (int32_t i = 0; i < n; ++i) {
+ cb_gen_push(gen, cb_format("\n dot += v1->values[%d] * v1->values[%d];",
+ i, i));
+ }
+ cb_gen_push(gen, "\n float magnitude = sqrtf((float)dot);"
+ "\n if (magnitude == 0.f) { return; }");
+
+ for (int32_t i = 0; i < n; ++i) {
+ cb_gen_push(gen, cb_format("\n v1->values[%d] /= magnitude;",
+ i, type));
+ }
+ cb_gen_push(gen, "\n}\n\n");
}