This is dgenum.c in view mode; [Download] [Up]
#include <stdio.h>
#include <math.h>
#include "wa.h"
#include "vec4.h"
#include "dgflag.h"
#include "enum.h"
#include "color.h"
#include "3d.h"
#include "ooglutil.h"
#include "discgrpP.h"
static DiscGrp *mydg;
static ColorA white = {1,1,1,.75};
static DiscGrpEl grpel;
static Transform mlist[128];
static int (*constraintfn)();
int check_big = 1, /* this is currently never non-zero */
check_new = 1, /* ditto */
have_matrices = 1,
metric = DG_HYPERBOLIC,
stringent = 0;
int
long_cnt = 0,
same_cnt = 0,
far_cnt = 0,
print_cnt = 0,
store_cnt = 0;
static int numchunks = 1;
static int ngens = 0;
int debug = 0;
static char symbollist[64];
static void get_matrices();
int
getindex(c)
char c;
{
int i;
for (i=0; i<ngens; ++i)
if (symbollist[i] == c) return(i);
return(-1);
}
static
word_to_mat(word, mat1)
char *word;
Transform mat1;
{
int length, i, index;
/*printf("# %s\n",word); */
TmIdentity(mat1);
for (i=0; word[i] != 0; ++i)
{
index = getindex(word[i]);
if (index < 0) {
printf("Bad symbol\n");
return;
}
TmConcat(mat1, mlist[index], mat1);
}
}
static int
is_big_and_new(DiscGrpEl *dgel)
{
int is_big=0, is_n = DG_CONSTRAINT_NEW;
if (check_new) is_n = is_new(dgel->tform);
if (is_n) {
is_big = constraintfn(dgel);
if (is_big & DG_CONSTRAINT_LONG) long_cnt++;
if (is_big & DG_CONSTRAINT_PRINT) print_cnt++;
if (is_big & DG_CONSTRAINT_STORE) store_cnt++;
if (is_big & DG_CONSTRAINT_TOOFAR) far_cnt++;
}
else same_cnt++;
return(is_big | is_n );
}
static int
process(DiscGrpEl *dgel, int stacking)
{
Transform mat;
register int is_ok;
if (have_matrices) {
is_ok = is_big_and_new(dgel);
/* remember that only NEW and PRINT are required to be here */
if (is_ok & DG_CONSTRAINT_NEW ) {
if (!(is_ok & DG_CONSTRAINT_LONG)) {
if (is_ok & (DG_CONSTRAINT_STORE | DG_CONSTRAINT_PRINT)) {
if (check_new) {
insert_mat(dgel->tform);
/* and put it on the stack */
if (stacking) push_new_stack(dgel->word);
}
if (is_ok & DG_CONSTRAINT_PRINT) enumpush(dgel);
}
}
}
}
return(is_ok);
}
static int
enumerate(int state, int depth, DiscGrpEl *dgel)
{
register int i, newstate, pval;
Transform mat;
char wword[64];
if ( ! ((pval = process(dgel, 0)) & DG_CONSTRAINT_STORE)) return 0;
if (pval & DG_CONSTRAINT_MAXLEN) return 0;
if (depth > MAXDEPTH) return 0;
for (i=1; i<mydg->fsa->ngens; ++i)
{
newstate = mydg->fsa->action[state][i];
if ( newstate != mydg->fsa->fail)
{
dgel->word[depth] = mydg->fsa->genlist[i-1][0];
dgel->word[depth+1] = 0; /* null-terminate */
word_to_mat(dgel->word, dgel->tform);
enumerate(newstate, depth+1, dgel);
}
}
}
static int
dumb_enumerate(int depth, DiscGrpEl *dgel)
{
register int i, j, l, stacking;
Transform mat;
char *word, wword[64];
extern char *pop_old_stack();
init_stack();
process(dgel, 1);
for (j = 0; j < MAXDEPTH ; ++j)
{
make_new_old();
/* are we interested in his descendents ? */
while ( (word = pop_old_stack()) != NULL) {
/* these words have length j */
strcpy(dgel->word, word);
for (i=0; i<ngens; ++i)
{
dgel->word[j] = symbollist[i];
dgel->word[j+1] = 0; /* null-terminate */
word_to_mat(dgel->word, dgel->tform);
process(dgel, 1);
}
}
}
}
static char emptyword[64] = "";
/*
* hack together an enumerate routine
*/
DiscGrpElList *
DiscGrpEnum(DiscGrp *discgrp, int (* constraint)(void) )
{
DiscGrpElList *enum_list = OOGLNewE(DiscGrpElList, "DiscGrpEnum");
extern DiscGrpEl *enumgetstack();
DiscGrpEl dgel;
/* initialize the local variables */
constraintfn = constraint;
have_matrices = 1;
same_cnt = 0;
far_cnt = 0;
print_cnt = 0;
store_cnt = 0;
long_cnt = 0;
ngens = discgrp->gens->num_el;
metric = discgrp->attributes & DG_METRIC_BITS;
bzero(dgel.word, sizeof(dgel.word));
dgel.attributes = discgrp->attributes;
TmIdentity(dgel.tform);
dgel.color = white;
mydg = discgrp;
init_out_stack();
get_matrices();
if (mydg->fsa) enumerate(mydg->fsa->start, 0, &dgel);
else dumb_enumerate(0,&dgel);
/* clean up the mess */
delete_list();
enum_list->num_el = enumgetsize();
enum_list->el_list = enumgetstack();
if (mydg->flag & DG_DEBUG) {
fprintf(stderr,"%d elements printed \n",print_cnt);
fprintf(stderr,"%d elements stored \n",store_cnt);
fprintf(stderr,"%d elements move too far \n",far_cnt);
fprintf(stderr,"%d elements too long \n",long_cnt);
fprintf(stderr,"%d elements duplicates \n",same_cnt);
}
return(enum_list);
}
static void
get_matrices()
{
int i;
for (i=0; i<mydg->gens->num_el; ++i)
{
symbollist[i] = mydg->gens->el_list[i].word[0];
TmCopy(mydg->gens->el_list[i].tform, mlist[i]);
}
fprintf(stderr,"%d generators read\n",i);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.