From 5f22fd07d94d73ab2b0004733e492d98d767e913 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Aug 2023 15:49:52 +0900 Subject: [PATCH] [qfcc] Implement 3d PGA dot products Also, correct the handling of scalars in dot and wedge products: it turns out s.v and s^v both scale. However, it seems the CSE code loses things sometimes. --- tools/qfcc/include/algebra.h | 1 + tools/qfcc/source/algebra.c | 22 ++- tools/qfcc/source/expr_algebra.c | 231 +++++++++++++++++++++++++++++-- tools/qfcc/test/algtypes.r | 1 + 4 files changed, 239 insertions(+), 16 deletions(-) diff --git a/tools/qfcc/include/algebra.h b/tools/qfcc/include/algebra.h index 36d641495..c87221eaf 100644 --- a/tools/qfcc/include/algebra.h +++ b/tools/qfcc/include/algebra.h @@ -85,6 +85,7 @@ struct expr_s; bool is_algebra (const struct type_s *type) __attribute__((pure)); struct type_s *algebra_type (struct type_s *type, struct expr_s *params); struct type_s *algebra_mvec_type (algebra_t *algebra, pr_uint_t group_mask); +struct ex_value_s *algebra_blade_value (algebra_t *alg, const char *name); struct symtab_s *algebra_scope (struct type_s *type, struct symtab_s *curscope); void algebra_print_type_str (struct dstring_s *str, const struct type_s *type); void algebra_encode_type (struct dstring_s *encoding, diff --git a/tools/qfcc/source/algebra.c b/tools/qfcc/source/algebra.c index 2fda195a6..4fb0b86cb 100644 --- a/tools/qfcc/source/algebra.c +++ b/tools/qfcc/source/algebra.c @@ -456,11 +456,9 @@ static int pga_swaps_3d[16] = { [0xd] = 1, // e032 }; -static symbol_t * -algebra_symbol (const char *name, symtab_t *symtab) +ex_value_t * +algebra_blade_value (algebra_t *alg, const char *name) { - algebra_t *alg = symtab->procsymbol_data; - symbol_t *sym = 0; uint32_t dimension = alg->plus + alg->minus + alg->zero; bool pga_2d = (alg->plus == 2 && alg->minus == 0 && alg->zero == 1); bool pga_3d = (alg->plus == 3 && alg->minus == 0 && alg->zero == 1); @@ -513,12 +511,24 @@ algebra_symbol (const char *name, symtab_t *symtab) components[g[1]] = sign; blade_val = new_type_value (group_type, (pr_type_t *)components); } - sym = new_symbol_type (name, group_type); + return blade_val; + } + return 0; +} + +static symbol_t * +algebra_symbol (const char *name, symtab_t *symtab) +{ + algebra_t *alg = symtab->procsymbol_data; + symbol_t *sym = 0; + + auto blade_val = algebra_blade_value (alg, name); + if (blade_val) { + sym = new_symbol_type (name, blade_val->type); sym->sy_type = sy_const; sym->s.value = blade_val; symtab_addsymbol (symtab, sym); } - return sym; } diff --git a/tools/qfcc/source/expr_algebra.c b/tools/qfcc/source/expr_algebra.c index ef6b49578..a05fc424d 100644 --- a/tools/qfcc/source/expr_algebra.c +++ b/tools/qfcc/source/expr_algebra.c @@ -285,6 +285,14 @@ dot_expr (type_t *type, expr_t *a, expr_t *b) return dot; } +static expr_t * +cross_expr (type_t *type, expr_t *a, expr_t *b) +{ + auto cross = new_binary_expr (CROSS, a, b); + cross->e.expr.type = type; + return cross; +} + typedef void (*pga_func) (expr_t **c, expr_t *a, expr_t *b, algebra_t *alg); static void scale_component (expr_t **c, expr_t *a, expr_t *b, algebra_t *alg) @@ -294,9 +302,210 @@ scale_component (expr_t **c, expr_t *a, expr_t *b, algebra_t *alg) c[group] = scale; } +static void +pga3_x_y_z_w_dot_x_y_z_w (expr_t **c, expr_t *a, expr_t *b, algebra_t *alg) +{ + auto stype = alg->type; + auto vtype = vector_type (stype, 3); + auto dot_type = algebra_mvec_type (alg, 0x04); + auto va = new_offset_alias_expr (vtype, a, 0); + auto vb = new_offset_alias_expr (vtype, b, 0); + c[2] = dot_expr (dot_type, va, vb); +} + +static void +pga3_x_y_z_w_dot_yz_zx_xy (expr_t **c, expr_t *a, expr_t *b, algebra_t *alg) +{ + auto stype = alg->type; + auto vtype = vector_type (stype, 3); + auto dot_type = algebra_mvec_type (alg, 0x01); + auto va = new_offset_alias_expr (vtype, a, 0); + c[2] = cross_expr (dot_type, b, va); +} + +static void +pga3_x_y_z_w_dot_wx_wy_wz (expr_t **c, expr_t *a, expr_t *b, algebra_t *alg) +{ + auto stype = alg->type; + auto vtype = vector_type (stype, 3); + auto va = new_offset_alias_expr (vtype, a, 0); + auto cs = dot_expr (stype, b, va); + auto blade = new_value_expr (algebra_blade_value (alg, "e0")); + c[0] = scale_expr (blade, unary_expr ('-', cs), alg); +} + +static void +pga3_x_y_z_w_dot_wxyz (expr_t **c, expr_t *a, expr_t *b, algebra_t *alg) +{ + auto stype = alg->type; + auto dot_type = algebra_mvec_type (alg, 0x20); + auto va = new_offset_alias_expr (dot_type, new_swizzle_expr (a, "xyz0"), 0); + auto sb = new_offset_alias_expr (stype, b, 0); + c[5] = scale_expr (va, sb, alg); +} + +#define pga3_wzy_wxz_wyx_xyz_dot_x_y_z_w pga3_x_y_z_w_dot_wzy_wxz_wyx_xyz +static void +pga3_x_y_z_w_dot_wzy_wxz_wyx_xyz (expr_t **c, expr_t *a, expr_t *b, + algebra_t *alg) +{ + auto stype = alg->type; + auto vtype = vector_type (stype, 3); + auto bvtype = algebra_mvec_type (alg, 0x02); + auto bmtype = algebra_mvec_type (alg, 0x08); + auto va = new_offset_alias_expr (bvtype, a, 0); + auto vb = new_offset_alias_expr (vtype, b, 0); + auto sb = new_offset_alias_expr (stype, b, 3); + c[1] = scale_expr (va, sb, alg); + c[3] = cross_expr (bmtype, vb, va); +} + +static void +pga3_yz_zx_xy_dot_x_y_z_w (expr_t **c, expr_t *a, expr_t *b, algebra_t *alg) +{ + auto stype = alg->type; + auto vtype = vector_type (stype, 3); + auto dot_type = algebra_mvec_type (alg, 0x01); + auto vb = new_offset_alias_expr (vtype, a, 0); + c[2] = cross_expr (dot_type, a, vb); +} + +static void +pga3_yz_zx_xy_dot_yz_zx_xy (expr_t **c, expr_t *a, expr_t *b, algebra_t *alg) +{ + auto dot_type = algebra_mvec_type (alg, 0x04); + c[2] = unary_expr ('-', dot_expr (dot_type, a, b)); +} + +#define pga3_wxyz_dot_yz_zx_xy pga3_yz_zx_xy_dot_wxyz +static void +pga3_yz_zx_xy_dot_wxyz (expr_t **c, expr_t *a, expr_t *b, algebra_t *alg) +{ + auto stype = alg->type; + auto bmtype = algebra_mvec_type (alg, 0x08); + auto va = new_offset_alias_expr (bmtype, a, 0); + auto sb = new_offset_alias_expr (stype, b, 0); + c[3] = scale_expr (va, unary_expr ('-', sb), alg); +} + +#define pga3_wzy_wxz_wyx_xyz_dot_yz_zx_xy pga3_yz_zx_xy_dot_wzy_wxz_wyx_xyz +static void +pga3_yz_zx_xy_dot_wzy_wxz_wyx_xyz (expr_t **c, expr_t *a, expr_t *b, + algebra_t *alg) +{ + auto stype = alg->type; + auto vtype = vector_type (stype, 3); + auto dot_type = algebra_mvec_type (alg, 0x01); + + auto vb = new_offset_alias_expr (vtype, b, 0); + auto sb = new_offset_alias_expr (stype, b, 3); + + auto cv = scale_expr (a, sb, alg); + auto cs = dot_expr (stype, a, vb); + + auto tmp = new_temp_def_expr (dot_type); + auto vtmp = new_offset_alias_expr (vtype, tmp, 0); + auto stmp = new_offset_alias_expr (stype, tmp, 3); + auto block = new_block_expr (); + block->e.block.result = tmp; + append_expr (block, assign_expr (vtmp, cv)); + append_expr (block, assign_expr (stmp, cs)); + c[0] = block; +} + +static void +pga3_wx_wy_wz_dot_x_y_z_w (expr_t **c, expr_t *a, expr_t *b, algebra_t *alg) +{ + auto stype = alg->type; + auto vtype = vector_type (stype, 3); + auto va = new_offset_alias_expr (vtype, a, 0); + auto cs = dot_expr (stype, b, va); + auto blade = new_value_expr (algebra_blade_value (alg, "e0")); + c[0] = scale_expr (blade, cs, alg); +} + +static void +pga3_wxyz_dot_x_y_z_w (expr_t **c, expr_t *a, expr_t *b, algebra_t *alg) +{ + auto stype = alg->type; + auto dot_type = algebra_mvec_type (alg, 0x20); + auto vb = new_offset_alias_expr (dot_type, + new_swizzle_expr (b, "-x-y-z0"), 0); + auto sa = new_offset_alias_expr (stype, a, 0); + c[5] = scale_expr (vb, sa, alg); +} + +static void +pga3_wxyz_dot_wzy_wxz_wyx_xyz (expr_t **c, expr_t *a, expr_t *b, algebra_t *alg) +{ + auto stype = alg->type; + auto sa = new_offset_alias_expr (stype, a, 0); + auto sb = new_offset_alias_expr (stype, b, 3); + auto blade = new_value_expr (algebra_blade_value (alg, "e0")); + sb = unary_expr ('-', sb); + c[0] = scale_expr (blade, scale_expr (sa, sb, alg), alg); +} + +static void +pga3_wzy_wxz_wyx_xyz_dot_wxyz (expr_t **c, expr_t *a, expr_t *b, algebra_t *alg) +{ + auto stype = alg->type; + auto sa = new_offset_alias_expr (stype, a, 0); + auto sb = new_offset_alias_expr (stype, b, 3); + auto blade = new_value_expr (algebra_blade_value (alg, "e0")); + c[0] = scale_expr (blade, scale_expr (sa, sb, alg), alg); +} + +static void +pga3_wzy_wxz_wyx_xyz_dot_wzy_wxz_wyx_xyz (expr_t **c, expr_t *a, expr_t *b, + algebra_t *alg) +{ + auto stype = alg->type; + auto sa = new_offset_alias_expr (stype, a, 3); + auto sb = new_offset_alias_expr (stype, b, 3); + c[0] = unary_expr ('-', scale_expr (sa, sb, alg)); +} + static pga_func pga3_dot_funcs[6][6] = { - [2] = { + [0] = { + [0] = pga3_x_y_z_w_dot_x_y_z_w, + [1] = pga3_x_y_z_w_dot_yz_zx_xy, [2] = scale_component, + [3] = pga3_x_y_z_w_dot_wx_wy_wz, + [4] = pga3_x_y_z_w_dot_wxyz, + [5] = pga3_x_y_z_w_dot_wzy_wxz_wyx_xyz, + }, + [1] = { + [0] = pga3_yz_zx_xy_dot_x_y_z_w, + [1] = pga3_yz_zx_xy_dot_yz_zx_xy, + [2] = scale_component, + [4] = pga3_yz_zx_xy_dot_wxyz, + [5] = pga3_yz_zx_xy_dot_wzy_wxz_wyx_xyz, + }, + [2] = { + [0] = scale_component, + [1] = scale_component, + [2] = scale_component, + [3] = scale_component, + [4] = scale_component, + [5] = scale_component, + }, + [3] = { + [0] = pga3_wx_wy_wz_dot_x_y_z_w, + [2] = scale_component, + }, + [4] = { + [0] = pga3_wxyz_dot_x_y_z_w, + [1] = pga3_wxyz_dot_yz_zx_xy, + [2] = scale_component, + [5] = pga3_wxyz_dot_wzy_wxz_wyx_xyz, + }, + [5] = { + [0] = pga3_wzy_wxz_wyx_xyz_dot_x_y_z_w, + [1] = pga3_wzy_wxz_wyx_xyz_dot_yz_zx_xy, + [2] = scale_component, + [4] = pga3_wzy_wxz_wyx_xyz_dot_wxyz, + [5] = pga3_wzy_wxz_wyx_xyz_dot_wzy_wxz_wyx_xyz, }, }; @@ -317,8 +526,7 @@ pga2_yw_wx_xy_dot_x_y_w (expr_t **c, expr_t *a, expr_t *b, algebra_t *alg) auto dot_type = algebra_mvec_type (alg, 0x04); auto va = new_offset_alias_expr (dot_type, new_swizzle_expr (a, "y-x0"), 0); auto sb = new_offset_alias_expr (stype, b, 2); - auto tmp = new_binary_expr (CROSS, a, b); - tmp->e.expr.type = dot_type; + auto tmp = cross_expr (dot_type, a, b); tmp = new_offset_alias_expr (dot_type, new_swizzle_expr (tmp, "00z"), 0); c[2] = new_binary_expr ('+', scale_expr (va, sb, alg), tmp); c[2]->e.expr.type = dot_type; @@ -331,8 +539,7 @@ pga2_x_y_w_dot_yw_wx_xy (expr_t **c, expr_t *a, expr_t *b, algebra_t *alg) auto dot_type = algebra_mvec_type (alg, 0x04); auto va = new_offset_alias_expr (dot_type, new_swizzle_expr (a, "-yx0"), 0); auto sb = new_offset_alias_expr (stype, b, 2); - auto tmp = new_binary_expr (CROSS, a, b); - tmp->e.expr.type = dot_type; + auto tmp = cross_expr (dot_type, a, b); tmp = new_offset_alias_expr (dot_type, new_swizzle_expr (tmp, "00-z"), 0); c[2] = new_binary_expr ('+', scale_expr (va, sb, alg), tmp); c[2]->e.expr.type = dot_type; @@ -387,7 +594,10 @@ static pga_func pga2_dot_funcs[4][4] = { [2] = pga2_yw_wx_xy_dot_x_y_w, }, [1] = { + [0] = scale_component, [1] = scale_component, + [2] = scale_component, + [3] = scale_component, }, [2] = { [0] = pga2_x_y_w_dot_yw_wx_xy, @@ -466,8 +676,7 @@ pga3_x_y_z_w_wedge_x_y_z_w (expr_t **c, expr_t *a, expr_t *b, algebra_t *alg) auto vb = new_offset_alias_expr (vtype, b, 0); auto sa = new_offset_alias_expr (stype, a, 3); auto sb = new_offset_alias_expr (stype, b, 3); - c[1] = new_binary_expr (CROSS, va, vb); - c[1]->e.expr.type = algebra_mvec_type (alg, 0x02); + c[1] = cross_expr (algebra_mvec_type (alg, 0x02), va, vb); c[3] = new_binary_expr ('-', scale_expr (vb, sa, alg), scale_expr (va, sb, alg)); c[3]->e.expr.type = wedge_type; @@ -503,7 +712,7 @@ pga3_x_y_z_w_wedge_wx_wy_wz (expr_t **c, expr_t *a, expr_t *b, algebra_t *alg) auto vtype = vector_type (stype, 3); auto wedge_type = algebra_mvec_type (alg, 0x20); auto va = new_offset_alias_expr (vtype, a, 0); - auto cv = new_binary_expr (CROSS, va, b); + auto cv = cross_expr (vtype, va, b); auto cs = new_zero_expr (stype); auto tmp = new_temp_def_expr (wedge_type); auto vtmp = new_offset_alias_expr (vtype, tmp, 0); @@ -584,8 +793,7 @@ static void pga2_x_y_w_wedge_x_y_w (expr_t **c, expr_t *a, expr_t *b, algebra_t *alg) { auto wedge_type = algebra_mvec_type (alg, 0x01); - c[0] = new_binary_expr (CROSS, a, b); - c[0]->e.expr.type = wedge_type; + c[0] = cross_expr (wedge_type, a, b); } static pga_func pga2_wedge_funcs[4][4] = { @@ -604,6 +812,9 @@ static pga_func pga2_wedge_funcs[4][4] = { [1] = scale_component, [2] = pga2_x_y_w_wedge_x_y_w, }, + [3] = { + [1] = scale_component, + }, }; static void diff --git a/tools/qfcc/test/algtypes.r b/tools/qfcc/test/algtypes.r index 34b783c2a..bfb12df4a 100644 --- a/tools/qfcc/test/algtypes.r +++ b/tools/qfcc/test/algtypes.r @@ -24,6 +24,7 @@ main (void) auto v = 4*(e1 + e032 + e123); pgaf1 = p1 + v;// * p2; pgaf1 = (p1 + v)∧p2; + pgaf1 = v • p2; #if 0 auto rx = e23; auto ry = e31;