From f323401c10dec7d79c58be71c5de67684c8a52dc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 16 Nov 2022 00:06:21 +0900 Subject: [PATCH] [qfcc] Add an explicit hadamard operator While the option to make '*' mean dot product for vectors is important, it breaks vector scaling in ruamoko progs as the resultant vector op becomes a dot product instead of the indented hadamard product (ie, component-wise). --- tools/qfcc/source/constfold.c | 2 +- tools/qfcc/source/dot_expr.c | 1 + tools/qfcc/source/expr_binary.c | 7 +++++++ tools/qfcc/source/options.c | 2 +- tools/qfcc/source/qc-lex.l | 1 + tools/qfcc/source/qc-parse.y | 3 ++- tools/qfcc/source/statements.c | 1 + 7 files changed, 14 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 6f6287f43..02a0b3cd8 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -394,7 +394,7 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) { const float *v1, *v2; vec3_t v, float_vec; - static int valid[] = {'+', '-', '*', SCALE, EQ, NE, 0}; + static int valid[] = {'+', '-', '*', HADAMARD, SCALE, EQ, NE, 0}; expr_t *t; if (!is_vector(get_type (e1))) { diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index a3a825eb3..8b5019898 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -94,6 +94,7 @@ get_op_string (int op) case 'C': return ""; case CROSS: return "@cross"; case DOT: return "@dot"; + case HADAMARD: return "@hadamard"; case SCALE: return "@scale"; default: return "unknown"; diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 9f96ef741..cffb1c580 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -150,6 +150,7 @@ static expr_type_t vector_vector[] = { {'-', &type_vector}, {DOT, &type_vector}, {CROSS, &type_vector}, + {HADAMARD, &type_vector}, {'*', 0, 0, 0, vector_multiply}, {EQ, 0, 0, 0, vector_compare}, {NE, 0, 0, 0, vector_compare}, @@ -1100,11 +1101,13 @@ binary_expr (int op, expr_t *e1, expr_t *e2) t2 = pt2; } } + int scalar_op = 0; if (type_width (t1) == 1) { // scalar op vec if (!(e = convert_scalar (e1, op, e2))) { return invalid_binary_expr (op, e1, e2); } + scalar_op = 1; e1 = e; t1 = get_type (e1); } @@ -1113,9 +1116,13 @@ binary_expr (int op, expr_t *e1, expr_t *e2) if (!(e = convert_scalar (e2, op, e1))) { return invalid_binary_expr (op, e1, e2); } + scalar_op = 1; e2 = e; t2 = get_type (e2); } + if (scalar_op && op == '*') { + op = HADAMARD; + } if (type_width (t1) != type_width (t2)) { // vec op vec of different widths return invalid_binary_expr (op, e1, e2); diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index c9cec0127..86586c375 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -742,7 +742,7 @@ DecodeArgs (int argc, char **argv) if (options.code.vector_components == (qboolean) -1) options.code.vector_components = false; if (options.math.vector_mult == 0) - options.math.vector_mult = options.advanced == 1 ? DOT : '*'; + options.math.vector_mult = options.advanced == 1 ? DOT : HADAMARD; } else { options.code.promote_float = 0; } diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index dd8c9ff84..5e50ef5d5 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -428,6 +428,7 @@ static keyword_t qf_keywords[] = { {"@cross", CROSS, 0 }, {"@dot", DOT, 0 }, + {"@hadamard", HADAMARD, 0 }, }; // These keywors are always available. Other than the @ keywords, they diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 1bab1798b..e23f231f8 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -141,7 +141,7 @@ int yylex (void); %left SHL SHR %left '+' '-' %left '*' '/' '%' MOD SCALE -%left CROSS DOT +%left CROSS DOT HADAMARD %right SIZEOF UNARY INCOP %left HYPERUNARY %left '.' '(' '[' @@ -1672,6 +1672,7 @@ expr | expr MOD expr { $$ = binary_expr (MOD, $1, $3); } | expr CROSS expr { $$ = binary_expr (CROSS, $1, $3); } | expr DOT expr { $$ = binary_expr (DOT, $1, $3); } + | expr HADAMARD expr { $$ = binary_expr (HADAMARD, $1, $3); } ; texpr diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 7f5134318..3da2e12a5 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -538,6 +538,7 @@ convert_op (int op) case '.': return "load"; case CROSS: return "cross"; case DOT: return "dot"; + case HADAMARD: return "mul"; case SCALE: return "scale"; default: return 0;