[qfcc] Implement multi-vector negation

That was surprisingly harder than expected due to recursion and a
not-so-good implementation in expr_negate (it went too high-level thus
resulting in multivec expressions getting to the code generator).
This commit is contained in:
Bill Currie 2023-08-28 17:00:14 +09:00
parent 6b1684b711
commit 1329a1c43a
4 changed files with 34 additions and 5 deletions

View file

@ -1766,6 +1766,9 @@ unary_expr (int op, expr_t *e)
case '-': case '-':
if (!is_math (get_type (e))) if (!is_math (get_type (e)))
return error (e, "invalid type for unary -"); return error (e, "invalid type for unary -");
if (is_algebra (get_type (e))) {
return algebra_negate (e);
}
if (is_constant (e)) { if (is_constant (e)) {
switch (extract_type (e)) { switch (extract_type (e)) {
case ev_string: case ev_string:

View file

@ -1434,11 +1434,25 @@ algebra_binary_expr (int op, expr_t *e1, expr_t *e2)
expr_t * expr_t *
algebra_negate (expr_t *e) algebra_negate (expr_t *e)
{ {
if (e) { auto t = get_type (e);
internal_error (e, "not implemented"); auto algebra = algebra_get (t);
auto layout = &algebra->layout;
expr_t *n[layout->count] = {};
e = mvec_expr (e, algebra);
mvec_scatter (n, e, algebra);
for (int i = 0; i < layout->count; i++) {
if (!n[i]) {
continue;
} }
notice (e, "not implemented"); auto ct = get_type (n[i]);
return 0; if (is_algebra (ct)) {
n[i] = cast_expr (float_type (ct), n[i]);
}
n[i] = unary_expr ('-', n[i]);
n[i]->e.expr.type = ct;
}
return mvec_gather (n, algebra);
} }
expr_t * expr_t *

View file

@ -1711,7 +1711,8 @@ expr_negate (sblock_t *sblock, expr_t *e, operand_t **op)
zero->file = e->file; zero->file = e->file;
zero->line = e->line; zero->line = e->line;
convert_nil (zero, e->e.expr.type); convert_nil (zero, e->e.expr.type);
neg = binary_expr ('-', zero, e->e.expr.e1); neg = new_binary_expr ('-', zero, e->e.expr.e1);
neg->e.expr.type = e->e.expr.type;
neg->file = e->file; neg->file = e->file;
neg->line = e->line; neg->line = e->line;
return statement_subexpr (sblock, neg, op); return statement_subexpr (sblock, neg, op);

View file

@ -241,5 +241,16 @@ main (void)
s.scalar, s.bvec); s.scalar, s.bvec);
return 1; return 1;
} }
e.mvec = -e.mvec; // odd
if ((dvec3)e.vec != '-2 -3 -0.5'd || (scalar_t)e.tvec != 10) {
printf ("odd† != '-2 -3 -0.5' + 10: %lv %g\n", e.vec, e.tvec);
return 1;
}
s.mvec = -s.mvec; // even
if (s.scalar != 4.5 || (dvec3)s.bvec != '7 22 23'd) {
printf ("even† != 4.5, '7 22 23': %g %lv\n",
s.scalar, s.bvec);
return 1;
}
return 0; // to survive and prevail :) return 0; // to survive and prevail :)
} }