mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 20:41:20 +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 '-':
|
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:
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
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 mvec_gather (n, algebra);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_t *
|
expr_t *
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 :)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue