#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 #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