123 lines
3.0 KiB
C
123 lines
3.0 KiB
C
#include "enumerate.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#define LOOP(i,n) for(int i = 0; i < (n); i++)
|
|
|
|
void enumerate_coxeter_group(group_t *group, mat *gen, mat *matrices)
|
|
{
|
|
TYPE t = GETTYPE(gen[0]->x[0]);
|
|
mat_workspace *ws;
|
|
|
|
ws = mat_workspace_init(3, t);
|
|
|
|
mat_identity(matrices[0]);
|
|
for(int i = 1; i < group->size; i++) {
|
|
if(!group->elements[i].inverse)
|
|
continue;
|
|
|
|
int parent = group->elements[i].parent->id;
|
|
int letter = group->elements[i].letter;
|
|
|
|
mat_multiply(ws, matrices[i], matrices[parent], gen[letter]);
|
|
}
|
|
|
|
mat_workspace_clear(ws);
|
|
}
|
|
|
|
static int compare_tracedata(const void *a_, const void *b_)
|
|
{
|
|
int d = 0;
|
|
|
|
struct tracedata **a = (struct tracedata **)a_;
|
|
struct tracedata **b = (struct tracedata **)b_;
|
|
|
|
d = CMP((*a)->tr,(*b)->tr);
|
|
if(d == 0) {
|
|
d = CMP((*a)->trinv, (*b)->trinv);
|
|
}
|
|
|
|
return d;
|
|
}
|
|
|
|
static int compare_tracedata_id(const void *a, const void *b)
|
|
{
|
|
int ida = (*(struct tracedata **)a)->id;
|
|
int idb = (*(struct tracedata **)b)->id;
|
|
|
|
return ida > idb ? 1 : ida < idb ? -1 : 0;
|
|
}
|
|
|
|
int enumerate_coxeter_group_traces(group_t *group, mat *gen, struct tracedata **traces_out)
|
|
{
|
|
TYPE t = GETTYPE(gen[0]->x[0]);
|
|
int n = group->size;
|
|
|
|
mat *matrices = malloc(n*sizeof(mat));
|
|
struct tracedata *traces = malloc(n*sizeof(struct tracedata));
|
|
struct tracedata **distinct_traces = malloc(n*sizeof(struct tracedata*));
|
|
|
|
LOOP(i, n) mat_init(matrices[i], 3, t);
|
|
enumerate_coxeter_group(group, gen, matrices);
|
|
|
|
LOOP(i, n) {
|
|
INIT(traces[i].tr, t);
|
|
INIT(traces[i].trinv, t);
|
|
}
|
|
LOOP(i, n) {
|
|
if(!group->elements[i].inverse)
|
|
continue;
|
|
mat_trace(traces[i].tr, matrices[i]);
|
|
mat_trace(traces[i].trinv, matrices[group->elements[i].inverse->id]);
|
|
traces[i].id = i;
|
|
distinct_traces[i] = &traces[i];
|
|
}
|
|
|
|
qsort(distinct_traces, n, sizeof(struct tracedata*), compare_tracedata);
|
|
|
|
int nuniq = 0;
|
|
LOOP(i, n) {
|
|
if(i == 0 || compare_tracedata(&distinct_traces[i], &distinct_traces[nuniq-1]) != 0) {
|
|
distinct_traces[nuniq] = distinct_traces[i];
|
|
nuniq++;
|
|
} else {
|
|
int oldlength = group->elements[distinct_traces[nuniq-1]->id].length;
|
|
int newlength = group->elements[distinct_traces[i]->id].length;
|
|
if(newlength < oldlength)
|
|
distinct_traces[nuniq-1]->id = distinct_traces[i]->id;
|
|
}
|
|
}
|
|
|
|
qsort(distinct_traces, nuniq, sizeof(struct tracedata*), compare_tracedata_id);
|
|
|
|
struct tracedata *unique_traces = malloc(nuniq*sizeof(struct tracedata));
|
|
LOOP(i, nuniq) {
|
|
INIT(unique_traces[i].tr, t);
|
|
INIT(unique_traces[i].trinv, t);
|
|
SET(unique_traces[i].tr, distinct_traces[i]->tr);
|
|
SET(unique_traces[i].trinv, distinct_traces[i]->trinv);
|
|
unique_traces[i].id = distinct_traces[i]->id;
|
|
}
|
|
|
|
LOOP(i, n) mat_clear(matrices[i]);
|
|
LOOP(i, n) {
|
|
CLEAR(traces[i].tr);
|
|
CLEAR(traces[i].trinv);
|
|
}
|
|
free(matrices);
|
|
free(traces);
|
|
free(distinct_traces);
|
|
|
|
*traces_out = unique_traces;
|
|
return nuniq;
|
|
}
|
|
|
|
void enumerate_tracedata_clear(struct tracedata *traces, int n)
|
|
{
|
|
LOOP(i, n) {
|
|
CLEAR(traces[i].tr);
|
|
CLEAR(traces[i].trinv);
|
|
}
|
|
free(traces);
|
|
}
|