From 277c5a2318898dda28058d6260b79410f5670b7e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 Dec 2024 11:43:07 +0900 Subject: [PATCH] [qfcc] Optimize matrix construction from a matrix If the source matrix has at least as many rows as the new matrix, then the columns are taken from the columns (possibly shortened via swizzle). --- tools/qfcc/source/expr_construct.c | 76 +++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 17 deletions(-) diff --git a/tools/qfcc/source/expr_construct.c b/tools/qfcc/source/expr_construct.c index d8c614cc2..5fbbb6caf 100644 --- a/tools/qfcc/source/expr_construct.c +++ b/tools/qfcc/source/expr_construct.c @@ -37,6 +37,23 @@ #include "tools/qfcc/include/type.h" #include "tools/qfcc/include/value.h" +static const expr_t * +get_column (const expr_t *e, int i) +{ + auto t = get_type (e); + if (!is_matrix (t)) { + internal_error (e, "not a matrix"); + } + if (i < 0 || i >= type_cols (t)) { + internal_error (e, "invalid index"); + } + + auto ind = new_int_expr (i, false); + auto a = new_array_expr (e, ind); + a->array.type = column_type (t); + return a; +} + static const expr_t * get_value (const expr_t *e, int i, int j) { @@ -46,10 +63,7 @@ get_value (const expr_t *e, int i, int j) internal_error (e, "invalid index"); } if (type_cols (t) > 1) { - auto ind = new_int_expr (i, false); - auto a = new_array_expr (e, ind); - a->array.type = column_type (t); - e = a; + e = get_column (e, i); } if (type_rows (t) > 1) { auto ind = new_int_expr (j, false); @@ -170,23 +184,51 @@ construct_matrix (const type_t *type, const expr_t *matrix, const expr_t *e) int rows = type_rows (type); int src_cols = type_cols (get_type (matrix)); int src_rows = type_rows (get_type (matrix)); - const expr_t *components[cols * rows + 1] = {}; - auto zero = new_nil_expr (); - for (int i = 0; i < cols; i++) { - for (int j = 0; j < rows; j++) { - const expr_t *val; - if (i < src_cols && j < src_rows) { - val = get_value (matrix, i, j); - } else { - val = zero; + if (src_rows >= rows) { + char swizzle[] = "xyzw"; + swizzle[rows] = 0; + const expr_t *columns[cols] = {}; + const expr_t *zero_column = nullptr; + if (src_cols < cols) { + auto ctype = column_type (type); + const expr_t *zero_col[rows]; + auto zero = new_nil_expr (); + for (int j = 0; j < rows; j++) { + zero_col[j] = zero; } - components[i * rows + j] = val; + zero_column = new_vector_list_gather (ctype, zero_col, rows); } + int i; + for (i = 0; i < src_cols && i < cols; i++) { + columns[i] = get_column (matrix, i); + if (src_rows > rows) { + columns[i] = new_swizzle_expr (columns[i], swizzle); + } + } + for (; i < cols; i++) { + columns[i] = zero_column; + } + return new_vector_list_gather (type, columns, cols); + } else { + const expr_t *components[cols * rows + 1] = {}; + auto zero = new_nil_expr (); + + for (int i = 0; i < cols; i++) { + for (int j = 0; j < rows; j++) { + const expr_t *val; + if (i < src_cols && j < src_rows) { + val = get_value (matrix, i, j); + } else { + val = zero; + } + components[i * rows + j] = val; + } + } + auto params = new_list_expr (nullptr); + list_gather (¶ms->list, components, cols * rows); + return construct_by_components (type, params, e); } - auto params = new_list_expr (nullptr); - list_gather (¶ms->list, components, cols * rows); - return construct_by_components (type, params, e); } static const expr_t *