mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-13 22:22:27 +00:00
[qfcc] Use scatter-gather for multivec expressions
This makes working with them much easier, and the type system reflects what's in the multi-vector. Unfortunately, that does mean that large algebras will wind up having a LOT of types, but it allows for efficient storage of sparse multi-vectors: auto v = 4*(e1 + e032 + e123); results in: 0005 0213 1:0008<00000008>4:void 0:0000<00000000>?:invalid 0:0044<00000044>4:void assign (<void>), v 0006 0213 1:000c<0000000c>4:void 0:0000<00000000>?:invalid 0:0048<00000048>4:void assign (<void>), {v + 4} Where the two source vectors are: 44:1 0 .imm float:18e [4, 0, 0, 0] 48:1 0 .imm float:1aa [4, 0, 0, 4] They just happen to be adjacent, but don't need to be.
This commit is contained in:
parent
dfb719c92b
commit
cfcacfbf28
9 changed files with 282 additions and 157 deletions
|
@ -38,11 +38,11 @@ typedef struct basis_blade_s {
|
|||
|
||||
typedef struct basis_group_s {
|
||||
int count;
|
||||
pr_uint_t group_mask;
|
||||
pr_uivec2_t range;
|
||||
basis_blade_t *blades;
|
||||
int *map;
|
||||
set_t *set;
|
||||
struct type_s *type;
|
||||
} basis_group_t;
|
||||
|
||||
typedef struct basis_layout_s {
|
||||
|
@ -67,6 +67,7 @@ typedef struct algebra_s {
|
|||
metric_t metric;
|
||||
basis_layout_t layout;
|
||||
basis_group_t *groups;
|
||||
struct type_s **mvec_types;
|
||||
int num_components; ///< number of componets (2^d)
|
||||
int dimension; ///< number of dimensions (plus + minus + zero)
|
||||
int plus; ///< number of elements squaring to +1
|
||||
|
@ -76,13 +77,14 @@ typedef struct algebra_s {
|
|||
|
||||
typedef struct multivector_s {
|
||||
int num_components;
|
||||
int element;
|
||||
int group_mask;
|
||||
algebra_t *algebra;
|
||||
} multivector_t;
|
||||
|
||||
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 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,
|
||||
|
@ -95,6 +97,7 @@ int metric_apply (const metric_t *metric, pr_uint_t a, pr_uint_t b) __attribute_
|
|||
algebra_t *algebra_get (const struct type_s *type) __attribute__((pure));
|
||||
int algebra_type_assignable (const struct type_s *dst,
|
||||
const struct type_s *src) __attribute__((pure));
|
||||
struct type_s *algebra_base_type (const struct type_s *type) __attribute__((pure));
|
||||
|
||||
struct expr_s *algebra_binary_expr (int op, struct expr_s *e1,
|
||||
struct expr_s *e2);
|
||||
|
|
|
@ -281,6 +281,7 @@ typedef struct {
|
|||
} ex_extend_t;
|
||||
|
||||
typedef struct {
|
||||
struct type_s *type; ///< overall type of multivector
|
||||
struct algebra_s *algebra; ///< owning algebra
|
||||
int count; ///< number of component expressions
|
||||
struct expr_s *components; ///< multivector components
|
||||
|
|
|
@ -164,10 +164,12 @@ basis_blade_init (basis_blade_t *blade, pr_uint_t mask)
|
|||
|
||||
static void
|
||||
basis_group_init (basis_group_t *group, int count, basis_blade_t *blades,
|
||||
algebra_t *a, int element)
|
||||
algebra_t *a, int group_id)
|
||||
{
|
||||
pr_uint_t group_mask = 1 << group_id;
|
||||
*group = (basis_group_t) {
|
||||
.count = count,
|
||||
.group_mask = group_mask,
|
||||
.range = { ~0u, 0 },
|
||||
.blades = malloc (sizeof (basis_blade_t[count])),
|
||||
.set = set_new (),
|
||||
|
@ -184,29 +186,6 @@ basis_group_init (basis_group_t *group, int count, basis_blade_t *blades,
|
|||
for (int i = 0; i < count; i++) {
|
||||
group->map[blades[i].mask - group->range[0]] = i;
|
||||
}
|
||||
|
||||
if (count == 1 && blades[0].mask == 0) {
|
||||
group->type = a->type;
|
||||
} else {
|
||||
multivector_t *mvec = malloc (sizeof (multivector_t));
|
||||
*mvec = (multivector_t) {
|
||||
.num_components = count,
|
||||
.element = element,
|
||||
.algebra = a,
|
||||
};
|
||||
group->type = new_type ();
|
||||
*group->type = (type_t) {
|
||||
.type = a->type->type,
|
||||
.name = "basis group",
|
||||
.alignment = 4, //FIXME
|
||||
.width = count,
|
||||
.meta = ty_algebra,
|
||||
.t.algebra = (algebra_t *) mvec,
|
||||
.freeable = true,
|
||||
.allocated = true,
|
||||
};
|
||||
chain_type (group->type);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -268,6 +247,12 @@ metric_apply (const metric_t *metric, pr_uint_t a, pr_uint_t b)
|
|||
return count_minus (c & metric->minus);
|
||||
}
|
||||
|
||||
static type_t **
|
||||
alloc_mvec_types (int num_groups)
|
||||
{
|
||||
return calloc (1 << num_groups, sizeof (type_t *));
|
||||
}
|
||||
|
||||
static void
|
||||
algebra_init (algebra_t *a)
|
||||
{
|
||||
|
@ -309,6 +294,7 @@ algebra_init (algebra_t *a)
|
|||
blades[13], blades[12], blades[11], blades[14],
|
||||
};
|
||||
a->groups = malloc (sizeof (basis_group_t[6]));
|
||||
a->mvec_types = alloc_mvec_types (6);
|
||||
basis_group_init (&a->groups[0], 4, pga_blades + 0, a, 0);
|
||||
basis_group_init (&a->groups[1], 3, pga_blades + 4, a, 1);
|
||||
basis_group_init (&a->groups[2], 1, pga_blades + 7, a, 2);
|
||||
|
@ -325,6 +311,7 @@ algebra_init (algebra_t *a)
|
|||
blades[2], blades[3], blades[1], blades[7],
|
||||
};
|
||||
a->groups = malloc (sizeof (basis_group_t[4]));
|
||||
a->mvec_types = alloc_mvec_types (4);
|
||||
basis_group_init (&a->groups[0], 1, pga_blades + 0, a, 0);
|
||||
basis_group_init (&a->groups[1], 3, pga_blades + 1, a, 1);
|
||||
basis_group_init (&a->groups[2], 3, pga_blades + 4, a, 2);
|
||||
|
@ -333,6 +320,7 @@ algebra_init (algebra_t *a)
|
|||
} else {
|
||||
// just use the grades as the default layout
|
||||
a->groups = malloc (sizeof (basis_group_t[d + 1]));
|
||||
a->mvec_types = alloc_mvec_types (d + 1);
|
||||
for (int i = 0; i < d + 1; i++) {
|
||||
int c = counts[i];
|
||||
int ind = indices[i];
|
||||
|
@ -340,6 +328,15 @@ algebra_init (algebra_t *a)
|
|||
}
|
||||
basis_layout_init (&a->layout, d + 1, a->groups);
|
||||
}
|
||||
|
||||
for (int i = 0; i < a->layout.count; i++) {
|
||||
auto g = &a->layout.groups[i];
|
||||
if (g->count == 1 && g->blades[0].mask == 0) {
|
||||
a->mvec_types[g->group_mask] = a->type;
|
||||
} else {
|
||||
algebra_mvec_type (a, g->group_mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -415,6 +412,41 @@ algebra_type (type_t *type, expr_t *params)
|
|||
return find_type (t);
|
||||
}
|
||||
|
||||
type_t *
|
||||
algebra_mvec_type (algebra_t *algebra, pr_uint_t group_mask)
|
||||
{
|
||||
if (!group_mask) {
|
||||
return 0;
|
||||
}
|
||||
if (!algebra->mvec_types[group_mask]) {
|
||||
int count = 0;
|
||||
for (int i = 0; i < algebra->layout.count; i++) {
|
||||
if (group_mask & (1 << i)) {
|
||||
count += algebra->layout.groups[i].count;
|
||||
}
|
||||
}
|
||||
multivector_t *mvec = malloc (sizeof (multivector_t));
|
||||
*mvec = (multivector_t) {
|
||||
.num_components = count,
|
||||
.group_mask = group_mask,
|
||||
.algebra = algebra,
|
||||
};
|
||||
algebra->mvec_types[group_mask] = new_type ();
|
||||
*algebra->mvec_types[group_mask] = (type_t) {
|
||||
.type = algebra->type->type,
|
||||
.name = "basis group",
|
||||
.alignment = 4, //FIXME
|
||||
.width = count,
|
||||
.meta = ty_algebra,
|
||||
.t.algebra = (algebra_t *) mvec,
|
||||
.freeable = true,
|
||||
.allocated = true,
|
||||
};
|
||||
chain_type (algebra->mvec_types[group_mask]);
|
||||
}
|
||||
return algebra->mvec_types[group_mask];
|
||||
}
|
||||
|
||||
static int pga_swaps_2d[8] = {
|
||||
[0x5] = 1, // e20
|
||||
};
|
||||
|
@ -470,17 +502,18 @@ algebra_symbol (const char *name, symtab_t *symtab)
|
|||
int sign = 1 - 2 * (swaps & 1);
|
||||
auto g = alg->layout.group_map[alg->layout.mask_map[blade]];
|
||||
auto group = &alg->layout.groups[g[0]];
|
||||
auto group_type = alg->mvec_types[group->group_mask];
|
||||
ex_value_t *blade_val = 0;
|
||||
if (is_float (alg->type)) {
|
||||
float components[group->count] = {};
|
||||
components[g[1]] = sign;
|
||||
blade_val = new_type_value (group->type, (pr_type_t *)components);
|
||||
blade_val = new_type_value (group_type, (pr_type_t *)components);
|
||||
} else {
|
||||
double components[group->count] = {};
|
||||
components[g[1]] = sign;
|
||||
blade_val = new_type_value (group->type, (pr_type_t *)components);
|
||||
blade_val = new_type_value (group_type, (pr_type_t *)components);
|
||||
}
|
||||
sym = new_symbol_type (name, group->type);
|
||||
sym = new_symbol_type (name, group_type);
|
||||
sym->sy_type = sy_const;
|
||||
sym->s.value = blade_val;
|
||||
symtab_addsymbol (symtab, sym);
|
||||
|
@ -524,8 +557,8 @@ algebra_print_type_str (dstring_t *str, const type_t *type)
|
|||
} else if (type->type == ev_float || type->type == ev_double) {
|
||||
auto m = type->t.multivec;
|
||||
auto a = m->algebra;
|
||||
dasprintf (str, " algebra(%s(%d,%d,%d):%d)", a->type->name,
|
||||
a->plus, a->minus, a->zero, m->element);
|
||||
dasprintf (str, " algebra(%s(%d,%d,%d):%04x)", a->type->name,
|
||||
a->plus, a->minus, a->zero, m->group_mask);
|
||||
} else {
|
||||
internal_error (0, "invalid algebra type");
|
||||
}
|
||||
|
@ -544,8 +577,8 @@ algebra_encode_type (dstring_t *encoding, const type_t *type)
|
|||
auto a = m->algebra;
|
||||
dasprintf (encoding, "{∧");
|
||||
encode_type (encoding, a->type);
|
||||
dasprintf (encoding, "(%d,%d,%d):%d}", a->plus, a->minus, a->zero,
|
||||
m->element);
|
||||
dasprintf (encoding, "(%d,%d,%d):%04x}", a->plus, a->minus, a->zero,
|
||||
m->group_mask);
|
||||
} else {
|
||||
internal_error (0, "invalid algebra type");
|
||||
}
|
||||
|
@ -609,3 +642,12 @@ algebra_type_assignable (const type_t *dst, const type_t *src)
|
|||
}
|
||||
return dst->t.multivec == src->t.multivec;
|
||||
}
|
||||
|
||||
type_t *
|
||||
algebra_base_type (const type_t *type)
|
||||
{
|
||||
if (type->type == ev_invalid) {
|
||||
return type->t.algebra->type;
|
||||
}
|
||||
return ev_types[type->type];
|
||||
}
|
||||
|
|
|
@ -201,7 +201,7 @@ get_type (expr_t *e)
|
|||
case ex_extend:
|
||||
return e->e.extend.type;
|
||||
case ex_multivec:
|
||||
return e->e.multivec.algebra->algebra_type;
|
||||
return e->e.multivec.type;
|
||||
case ex_count:
|
||||
internal_error (e, "invalid expression");
|
||||
}
|
||||
|
@ -445,8 +445,6 @@ copy_expr (expr_t *e)
|
|||
case ex_multivec:
|
||||
n = new_expr ();
|
||||
*n = *e;
|
||||
n->e.multivec.algebra = e->e.multivec.algebra;
|
||||
n->e.multivec.count = e->e.multivec.count;
|
||||
n->e.multivec.components = copy_expr (e->e.multivec.components);
|
||||
t = e->e.multivec.components;
|
||||
e = n->e.multivec.components;
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "QF/math/bitop.h"
|
||||
|
||||
#include "tools/qfcc/include/algebra.h"
|
||||
#include "tools/qfcc/include/diagnostic.h"
|
||||
#include "tools/qfcc/include/expr.h"
|
||||
|
@ -36,6 +38,121 @@
|
|||
|
||||
#include "tools/qfcc/source/qc-parse.h"
|
||||
|
||||
static expr_t *
|
||||
mvec_expr (expr_t *expr, algebra_t *algebra)
|
||||
{
|
||||
auto mvtype = get_type (expr);
|
||||
if (expr->type == ex_multivec || is_scalar (mvtype)) {
|
||||
return expr;
|
||||
}
|
||||
if (!is_algebra (mvtype)) {
|
||||
return error (expr, "invalid operand for GA");
|
||||
}
|
||||
|
||||
auto layout = &algebra->layout;
|
||||
pr_uint_t group_mask = (1u << (layout->count + 1)) - 1;
|
||||
if (mvtype->type != ev_invalid) {
|
||||
group_mask = mvtype->t.multivec->group_mask;
|
||||
}
|
||||
if (!(group_mask & (group_mask - 1))) {
|
||||
return expr;
|
||||
}
|
||||
auto mvec = new_expr ();
|
||||
mvec->type = ex_multivec;
|
||||
mvec->e.multivec = (ex_multivec_t) {
|
||||
.type = algebra_mvec_type (algebra, group_mask),
|
||||
.algebra = algebra,
|
||||
};
|
||||
expr_t **c = &mvec->e.multivec.components;
|
||||
for (int i = 0; i < layout->count; i++) {
|
||||
pr_uint_t mask = 1u << i;
|
||||
if (mask & group_mask) {
|
||||
auto comp_type = algebra_mvec_type (algebra, mask);
|
||||
int comp_offset = algebra->layout.group_map[i][1];
|
||||
*c = new_offset_alias_expr (comp_type, expr, comp_offset);
|
||||
mvec->e.multivec.count++;
|
||||
}
|
||||
}
|
||||
|
||||
return mvec;
|
||||
}
|
||||
|
||||
static void
|
||||
mvec_scatter (expr_t **components, expr_t *mvec, algebra_t *algebra)
|
||||
{
|
||||
auto layout = &algebra->layout;
|
||||
int group;
|
||||
|
||||
if (mvec->type != ex_multivec) {
|
||||
auto type = get_type (mvec);
|
||||
if (!is_algebra (type)) {
|
||||
group = layout->group_map[layout->mask_map[0]][0];
|
||||
} else {
|
||||
if (type->type == ev_invalid) {
|
||||
internal_error (mvec, "full algebra in mvec_scatter");
|
||||
}
|
||||
pr_uint_t mask = type->t.multivec->group_mask;
|
||||
if (mask & (mask - 1)) {
|
||||
internal_error (mvec, "bare multivector in mvec_scatter");
|
||||
}
|
||||
group = BITOP_LOG2 (mask);
|
||||
}
|
||||
components[group] = mvec;
|
||||
return;
|
||||
}
|
||||
for (auto c = mvec->e.multivec.components; c; c = c->next) {
|
||||
auto ct = get_type (c);
|
||||
if (is_scalar (ct)) {
|
||||
group = layout->group_map[layout->mask_map[0]][0];
|
||||
components[group] = mvec;
|
||||
} else if (ct->meta == ty_algebra && ct->type != ev_invalid) {
|
||||
pr_uint_t mask = ct->t.multivec->group_mask;
|
||||
if (mask & (mask - 1)) {
|
||||
internal_error (mvec, "multivector in multivec expression");
|
||||
}
|
||||
group = BITOP_LOG2 (mask);
|
||||
} else {
|
||||
internal_error (mvec, "invalid type in multivec expression");
|
||||
}
|
||||
components[group] = c;
|
||||
}
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
mvec_gather (expr_t **components, algebra_t *algebra)
|
||||
{
|
||||
auto layout = &algebra->layout;
|
||||
|
||||
pr_uint_t group_mask = 0;
|
||||
int count = 0;
|
||||
expr_t *mvec = 0;
|
||||
for (int i = 0; i < layout->count; i++) {
|
||||
if (components[i]) {
|
||||
count++;
|
||||
mvec = components[i];
|
||||
group_mask |= 1 << i;
|
||||
}
|
||||
}
|
||||
if (count == 1) {
|
||||
return mvec;
|
||||
}
|
||||
|
||||
mvec = new_expr ();
|
||||
mvec->type = ex_multivec;
|
||||
mvec->e.multivec = (ex_multivec_t) {
|
||||
.type = algebra_mvec_type (algebra, group_mask),
|
||||
.algebra = algebra,
|
||||
};
|
||||
for (int i = layout->count; i-- > 0; ) {
|
||||
if (components[i]) {
|
||||
components[i]->next = mvec->e.multivec.components;
|
||||
mvec->e.multivec.components = components[i];
|
||||
mvec->e.multivec.count++;
|
||||
}
|
||||
}
|
||||
return mvec;
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
promote_scalar (type_t *dst_type, expr_t *scalar)
|
||||
{
|
||||
|
@ -56,29 +173,34 @@ scalar_product (expr_t *e1, expr_t *e2)
|
|||
{
|
||||
auto scalar = is_scalar (get_type (e1)) ? e1 : e2;
|
||||
auto vector = is_scalar (get_type (e1)) ? e2 : e1;
|
||||
if (vector->type == ex_multivec) {
|
||||
auto comp = vector->e.multivec.components;
|
||||
auto prod = scalar_product (scalar, comp);
|
||||
while (comp->next) {
|
||||
comp = comp->next;
|
||||
auto p = scalar_product (scalar, comp);
|
||||
p = fold_constants (p);
|
||||
p->next = prod;
|
||||
prod = p;
|
||||
auto algebra = algebra_get (get_type (vector));
|
||||
auto layout = &algebra->layout;
|
||||
|
||||
scalar = promote_scalar (algebra->type, scalar);
|
||||
|
||||
expr_t *components[layout->count] = {};
|
||||
vector = mvec_expr (vector, algebra);
|
||||
mvec_scatter (components, vector, algebra);
|
||||
|
||||
for (int i = 0; i < layout->count; i++) {
|
||||
if (!components[i]) {
|
||||
continue;
|
||||
}
|
||||
return prod;
|
||||
} else {
|
||||
auto vector_type = get_type (vector);
|
||||
auto scalar_type = base_type (vector_type);
|
||||
scalar = promote_scalar (scalar_type, scalar);
|
||||
if (type_width (vector_type) > 4) {
|
||||
auto comp_type = get_type (components[i]);
|
||||
if (type_width (comp_type) == 1) {
|
||||
auto prod = new_binary_expr ('*', components[i], scalar);
|
||||
prod->e.expr.type = comp_type;
|
||||
components[i] = fold_constants (prod);
|
||||
} else if (type_width (comp_type) > 4) {
|
||||
internal_error (vector, "scalar * %d-vector not implemented",
|
||||
type_width (vector_type));
|
||||
type_width (comp_type));
|
||||
} else {
|
||||
auto prod = new_binary_expr (SCALE, components[i], scalar);
|
||||
prod->e.expr.type = comp_type;
|
||||
components[i] = fold_constants (prod);
|
||||
}
|
||||
auto prod = new_binary_expr (SCALE, vector, scalar);
|
||||
prod->e.expr.type = vector_type;
|
||||
return fold_constants (prod);
|
||||
}
|
||||
return mvec_gather (components, algebra);
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
|
@ -110,30 +232,31 @@ regressive_product (expr_t *e1, expr_t *e2)
|
|||
}
|
||||
|
||||
static void
|
||||
component_sum (int op, expr_t **components, expr_t *e,
|
||||
const basis_layout_t *layout)
|
||||
component_sum (int op, expr_t **c, expr_t **a, expr_t **b,
|
||||
algebra_t *algebra)
|
||||
{
|
||||
int group;
|
||||
auto t = get_type (e);
|
||||
if (is_scalar (t)) {
|
||||
group = layout->group_map[layout->mask_map[0]][0];
|
||||
} else {
|
||||
group = t->t.multivec->element;
|
||||
}
|
||||
if (components[group]) {
|
||||
if (t != get_type (components[group])) {
|
||||
internal_error (e, "tangled multivec types");
|
||||
}
|
||||
components[group] = new_binary_expr (op, components[group], e);
|
||||
components[group]->e.expr.type = t;
|
||||
} else {
|
||||
if (op == '+') {
|
||||
components[group] = e;
|
||||
auto layout = &algebra->layout;
|
||||
for (int i = 0; i < layout->count; i++) {
|
||||
if (a[i] && b[i]) {
|
||||
if (get_type (a[i]) != get_type (b[i])) {
|
||||
internal_error (a[i], "tangled multivec types");
|
||||
}
|
||||
c[i] = new_binary_expr (op, a[i], b[i]);
|
||||
c[i]->e.expr.type = get_type (a[i]);
|
||||
c[i] = fold_constants (c[i]);
|
||||
} else if (a[i]) {
|
||||
c[i] = a[i];
|
||||
} else if (b[i]) {
|
||||
if (op == '+') {
|
||||
c[i] = b[i];
|
||||
} else {
|
||||
c[i] = scalar_product (new_float_expr (-1), b[i]);
|
||||
c[i] = fold_constants (c[i]);
|
||||
}
|
||||
} else {
|
||||
components[group] = scalar_product (new_float_expr (-1), e);
|
||||
c[i] = 0;
|
||||
}
|
||||
}
|
||||
components[group] = fold_constants (components[group]);
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
|
@ -141,60 +264,17 @@ multivector_sum (int op, expr_t *e1, expr_t *e2)
|
|||
{
|
||||
auto t1 = get_type (e1);
|
||||
auto t2 = get_type (e2);
|
||||
auto alg = is_algebra (t1) ? algebra_get (t1) : algebra_get (t2);
|
||||
auto layout = &alg->layout;
|
||||
expr_t *components[layout->count] = {};
|
||||
if (e1->type == ex_multivec) {
|
||||
for (auto c = e1->e.multivec.components; c; c = c->next) {
|
||||
auto ct = get_type (c);
|
||||
int group;
|
||||
if (is_scalar (ct)) {
|
||||
group = layout->group_map[layout->mask_map[0]][0];
|
||||
} else {
|
||||
group = ct->t.multivec->element;
|
||||
}
|
||||
components[group] = c;
|
||||
}
|
||||
} else {
|
||||
int group;
|
||||
if (is_scalar (t1)) {
|
||||
group = layout->group_map[layout->mask_map[0]][0];
|
||||
} else {
|
||||
group = t1->t.multivec->element;
|
||||
}
|
||||
components[group] = e1;
|
||||
}
|
||||
if (e2->type == ex_multivec) {
|
||||
for (auto c = e1->e.multivec.components; c; c = c->next) {
|
||||
component_sum (op, components, c, layout);
|
||||
}
|
||||
} else {
|
||||
component_sum (op, components, e2, layout);
|
||||
}
|
||||
int count = 0;
|
||||
expr_t *sum = 0;
|
||||
for (int i = 0; i < layout->count; i++) {
|
||||
if (components[i]) {
|
||||
count++;
|
||||
sum = components[i];
|
||||
}
|
||||
}
|
||||
if (count == 1) {
|
||||
return sum;
|
||||
}
|
||||
|
||||
sum = new_expr ();
|
||||
sum->type = ex_multivec;
|
||||
sum->e.multivec.algebra = alg;
|
||||
for (int i = layout->count; i-- > 0; ) {
|
||||
if (components[i]) {
|
||||
components[i]->next = sum->e.multivec.components;
|
||||
sum->e.multivec.components = components[i];
|
||||
sum->e.multivec.count++;
|
||||
}
|
||||
}
|
||||
|
||||
return sum;
|
||||
auto algebra = is_algebra (t1) ? algebra_get (t1) : algebra_get (t2);
|
||||
auto layout = &algebra->layout;
|
||||
expr_t *a[layout->count] = {};
|
||||
expr_t *b[layout->count] = {};
|
||||
expr_t *c[layout->count];
|
||||
e1 = mvec_expr (e1, algebra);
|
||||
e2 = mvec_expr (e2, algebra);
|
||||
mvec_scatter (a, e1, algebra);
|
||||
mvec_scatter (b, e2, algebra);
|
||||
component_sum (op, c, a, b, algebra);
|
||||
return mvec_gather (c, algebra);
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
|
@ -302,35 +382,21 @@ algebra_assign_expr (expr_t *dst, expr_t *src)
|
|||
type_t *srcType = get_type (src);
|
||||
type_t *dstType = get_type (dst);
|
||||
|
||||
if (type_size (srcType) == type_size (dstType)) {
|
||||
return new_assign_expr (dst, src);
|
||||
if (src->type != ex_multivec) {
|
||||
if (type_size (srcType) == type_size (dstType)) {
|
||||
return new_assign_expr (dst, src);
|
||||
}
|
||||
}
|
||||
|
||||
if (dstType->meta != ty_algebra && dstType->type != ev_invalid) {
|
||||
if (dstType->meta != ty_algebra && dstType != srcType) {
|
||||
return 0;
|
||||
}
|
||||
auto layout = &dstType->t.algebra->layout;
|
||||
auto algebra = algebra_get (dstType);
|
||||
auto layout = &algebra->layout;
|
||||
expr_t *components[layout->count] = {};
|
||||
if (src->type == ex_multivec) {
|
||||
for (auto c = src->e.multivec.components; c; c = c->next) {
|
||||
auto ct = get_type (c);
|
||||
int group;
|
||||
if (is_scalar (ct)) {
|
||||
group = layout->group_map[layout->mask_map[0]][0];
|
||||
} else {
|
||||
group = ct->t.multivec->element;
|
||||
}
|
||||
components[group] = c;
|
||||
}
|
||||
} else {
|
||||
int group;
|
||||
if (is_scalar (srcType)) {
|
||||
group = layout->group_map[layout->mask_map[0]][0];
|
||||
} else {
|
||||
group = srcType->t.multivec->element;
|
||||
}
|
||||
components[group] = src;
|
||||
}
|
||||
src = mvec_expr (src, algebra);
|
||||
mvec_scatter (components, src, algebra);
|
||||
|
||||
auto block = new_block_expr ();
|
||||
int memset_base = 0;
|
||||
int memset_size = 0;
|
||||
|
@ -341,14 +407,17 @@ algebra_assign_expr (expr_t *dst, expr_t *src)
|
|||
zero_components (block, dst, memset_base, memset_size);
|
||||
memset_size = 0;
|
||||
}
|
||||
auto dst_type = layout->groups[i].type;
|
||||
auto dst_type = algebra_mvec_type (algebra, 1 << i);
|
||||
auto dst_alias = new_offset_alias_expr (dst_type, dst, offset);
|
||||
append_expr (block, new_assign_expr (dst_alias, components[i]));
|
||||
offset += type_size (dst_type);
|
||||
memset_base = offset;
|
||||
} else {
|
||||
offset += type_size (layout->groups[i].type);
|
||||
memset_size += type_size (layout->groups[i].type);
|
||||
if (dstType->type == ev_invalid) {
|
||||
auto dst_type = algebra_mvec_type (algebra, 1 << i);
|
||||
offset += type_size (dst_type);
|
||||
memset_size += type_size (dst_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (memset_size) {
|
||||
|
|
|
@ -173,6 +173,9 @@ check_types_compatible (expr_t *dst, expr_t *src)
|
|||
type_t *src_type = get_type (src);
|
||||
|
||||
if (dst_type == src_type) {
|
||||
if (is_algebra (dst_type) || is_algebra (src_type)) {
|
||||
return algebra_assign_expr (dst, src);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,8 @@ __attribute__((const)) int algebra_type_assignable (const type_t *dst, const typ
|
|||
int algebra_type_assignable (const type_t *dst, const type_t *src){return 0;}
|
||||
__attribute__((const)) int is_algebra (const type_t *type);
|
||||
int is_algebra (const type_t *type){return 0;}
|
||||
__attribute__((const)) int algebra_base_type (const type_t *type);
|
||||
int algebra_base_type (const type_t *type){return 0;}
|
||||
|
||||
__attribute__((const)) pr_string_t ReuseString (const char *str) {return 0;}
|
||||
__attribute__((const)) codespace_t *codespace_new (void) {return 0;}
|
||||
|
|
|
@ -678,6 +678,9 @@ vector_type (const type_t *ele_type, int width)
|
|||
type_t *
|
||||
base_type (const type_t *vec_type)
|
||||
{
|
||||
if (is_algebra (vec_type)) {
|
||||
return algebra_base_type (vec_type);
|
||||
}
|
||||
if (!is_math (vec_type)) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -1221,6 +1224,9 @@ is_math (const type_t *type)
|
|||
if (is_vector (type) || is_quaternion (type)) {
|
||||
return 1;
|
||||
}
|
||||
if (is_algebra (type)) {
|
||||
return 1;
|
||||
}
|
||||
return is_scalar (type) || is_nonscalar (type);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,8 @@ main (void)
|
|||
@algebra (PGA) {
|
||||
auto p1 = 3*e1 + e2 - e3 + e0;
|
||||
auto p2 = e1 + 3*e2 + e3 - e0;
|
||||
pgaf1 = p1 * p2;
|
||||
auto v = 4*(e1 + e032 + e123);
|
||||
pgaf1 = p1 + v;// * p2;
|
||||
#if 0
|
||||
auto rx = e23;
|
||||
auto ry = e31;
|
||||
|
|
Loading…
Reference in a new issue