mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-26 14:20:59 +00:00
[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:
parent
6b1684b711
commit
1329a1c43a
4 changed files with 34 additions and 5 deletions
|
@ -1766,6 +1766,9 @@ unary_expr (int op, expr_t *e)
|
|||
case '-':
|
||||
if (!is_math (get_type (e)))
|
||||
return error (e, "invalid type for unary -");
|
||||
if (is_algebra (get_type (e))) {
|
||||
return algebra_negate (e);
|
||||
}
|
||||
if (is_constant (e)) {
|
||||
switch (extract_type (e)) {
|
||||
case ev_string:
|
||||
|
|
|
@ -1434,11 +1434,25 @@ algebra_binary_expr (int op, expr_t *e1, expr_t *e2)
|
|||
expr_t *
|
||||
algebra_negate (expr_t *e)
|
||||
{
|
||||
if (e) {
|
||||
internal_error (e, "not implemented");
|
||||
auto t = get_type (e);
|
||||
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;
|
||||
}
|
||||
auto ct = get_type (n[i]);
|
||||
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;
|
||||
}
|
||||
notice (e, "not implemented");
|
||||
return 0;
|
||||
return mvec_gather (n, algebra);
|
||||
}
|
||||
|
||||
expr_t *
|
||||
|
|
|
@ -1711,7 +1711,8 @@ expr_negate (sblock_t *sblock, expr_t *e, operand_t **op)
|
|||
zero->file = e->file;
|
||||
zero->line = e->line;
|
||||
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->line = e->line;
|
||||
return statement_subexpr (sblock, neg, op);
|
||||
|
|
|
@ -241,5 +241,16 @@ main (void)
|
|||
s.scalar, s.bvec);
|
||||
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 :)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue