+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) {