135 lines
2.4 KiB
C
135 lines
2.4 KiB
C
#ifndef KLEIN_H
|
|
#warning Please include klein/klein.h before klein/parm.h
|
|
#endif
|
|
|
|
#ifdef KLEIN_PARM_H
|
|
#error file included twice
|
|
#endif
|
|
#define KLEIN_PARM_H
|
|
|
|
|
|
typedef void (*function_t)(float *, int *, unsigned char *);
|
|
|
|
struct parm
|
|
{
|
|
unsigned char *grid;
|
|
unsigned char m, n;
|
|
function_t f;
|
|
};
|
|
|
|
|
|
void klein_parametrize( struct klein * klein, struct parm parm );
|
|
|
|
#ifdef KLEIN_IMPLEMENT
|
|
#ifdef TEST
|
|
#include <assert.h>
|
|
#endif
|
|
|
|
static inline int __factorial(int n)
|
|
{
|
|
if (n == 1)
|
|
return 1;
|
|
|
|
return n * __factorial(n - 1);
|
|
}
|
|
|
|
static inline int __face(int n)
|
|
{
|
|
if (n == 2)
|
|
return 1;
|
|
|
|
return (1 << (n - 3)) * __factorial(n) / __factorial(n - 2);
|
|
}
|
|
|
|
void klein_parametrize( struct klein * klein, struct parm parm)
|
|
{
|
|
unsigned int i, j, k, o, p, n;
|
|
unsigned long size, q = 0;
|
|
int *face;
|
|
|
|
#ifdef TEST
|
|
assert(__face(2) == 1);
|
|
assert(__face(3) == 6);
|
|
assert(__face(4) == 24);
|
|
#endif
|
|
|
|
klein->dim = parm.n;
|
|
klein->vertex_size = 0;
|
|
{
|
|
unsigned char test = 0;
|
|
for (o = 0; o < parm.m; o++)
|
|
{
|
|
for (p = 0; p < o; p++)
|
|
{
|
|
test += 1;
|
|
klein->vertex_size += parm.grid[p] * parm.grid[o] * 6 * __face(parm.m);
|
|
}
|
|
}
|
|
klein->vertex_size /= test;
|
|
}
|
|
|
|
size = (klein->dim) * (klein->vertex_size);
|
|
klein->vertex = malloc(size * sizeof(float));
|
|
|
|
face = malloc(parm.m * sizeof(int));
|
|
|
|
for (o = 0; o < parm.m; o++)
|
|
{
|
|
for (p = 0; p < o; p++)
|
|
{
|
|
for (k = 0; k < (1 << (parm.m - 2)); k++)
|
|
{
|
|
unsigned char skip = 0;
|
|
for (n = 0; n < parm.m; n++)
|
|
{
|
|
if (n == o || n == p)
|
|
skip++;
|
|
|
|
face[n] = (k & (1 << (n - skip))) ? parm.grid[n] : 0;
|
|
}
|
|
|
|
for (i = 0; i < parm.grid[p]; i++)
|
|
{
|
|
for (j = 0; j < parm.grid[o]; j++)
|
|
{
|
|
face[p] = i;
|
|
face[o] = j;
|
|
parm.f(&klein->vertex[q], face, parm.grid);
|
|
q += parm.n;
|
|
|
|
face[p] = i + 1;
|
|
face[o] = j;
|
|
parm.f(&klein->vertex[q], face, parm.grid);
|
|
q += parm.n;
|
|
|
|
face[p] = i + 1;
|
|
face[o] = j + 1;
|
|
parm.f(&klein->vertex[q], face, parm.grid);
|
|
q += parm.n;
|
|
|
|
face[p] = i;
|
|
face[o] = j;
|
|
parm.f(&klein->vertex[q], face, parm.grid);
|
|
q += parm.n;
|
|
|
|
face[p] = i;
|
|
face[o] = j + 1;
|
|
parm.f(&klein->vertex[q], face, parm.grid);
|
|
q += parm.n;
|
|
|
|
face[p] = i + 1;
|
|
face[o] = j + 1;
|
|
parm.f(&klein->vertex[q], face, parm.grid);
|
|
q += parm.n;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef TEST
|
|
assert(q == size);
|
|
#endif
|
|
}
|
|
#endif
|