Refactoring lattice generator API (dimensionality generalisation)
Former-commit-id: 3eb6623ed298bf1e2a458d15c237e83b3b3cf70d
This commit is contained in:
parent
0719043653
commit
1b24794baa
|
@ -6,56 +6,80 @@
|
||||||
|
|
||||||
|
|
||||||
// const PGenSphReturnData PGenSphDoneVal = {PGEN_DONE, {0,0,0}}; // defined already in lattices.h
|
// const PGenSphReturnData PGenSphDoneVal = {PGEN_DONE, {0,0,0}}; // defined already in lattices.h
|
||||||
|
// const PGenCart3ReturnData PGenCart3DoneVal = {PGEN_DONE, {0,0,0}}; // defined already in lattices.h
|
||||||
|
|
||||||
// General structure of a generator implementation looks like this:
|
// General structure of a generator implementation looks like this:
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
//==== PGenSph_NAME ====
|
//==== PGen_NAME ====
|
||||||
|
|
||||||
extern const PGenSphClassInfo PGenSph_NAME; // forward declaration needed by constructor (may be placed in header file instead)
|
extern const PGenClassInfo PGen_NAME; // forward declaration needed by constructor (may be placed in header file instead)
|
||||||
|
|
||||||
// Internal state structure
|
// Internal state structure
|
||||||
typedef struct PGenSph_NAME_StateData {
|
typedef struct PGen_NAME_StateData {
|
||||||
...
|
...
|
||||||
} PGenSph_NAME_StateData;
|
} PGen_NAME_StateData;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
PGenSph PGenSph_NAME_new(...) {
|
PGenSph PGen_NAME_new(...) {
|
||||||
g->stateData = malloc(sizeof(PGenSph_NAME_StateData));
|
g->stateData = malloc(sizeof(PGen_NAME_StateData));
|
||||||
...
|
...
|
||||||
PGenSph g = {&PGenSph_NAME, (void *) stateData};
|
PGenSph g = {&PGen_NAME, (void *) stateData};
|
||||||
return g;
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dectructor
|
// Dectructor
|
||||||
void PGenSph_NAME_dectructor(PGenSph *g) {
|
void PGen_NAME_dectructor(PGen *g) {
|
||||||
...
|
...
|
||||||
free(g->stateData);
|
free(g->stateData);
|
||||||
g->stateData = NULL;
|
g->stateData = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extractor
|
// Extractor, spherical coordinate output
|
||||||
PGenSphReturnData PGenSph_NAME_next(PGenSph *g) {
|
PGenSphReturnData PGen_NAME_next_sph(PGen *g) {
|
||||||
if (g->stateData == NULL) // already destroyed
|
if (g->stateData == NULL) // already destroyed
|
||||||
return PGenSphDoneVal;
|
return PGenSphDoneVal;
|
||||||
else {
|
else {
|
||||||
PGenSph_NAME_StateData *s = (PGenSph_NAME_StateData *) g->stateData;
|
PGen_NAME_StateData *s = (PGen_NAME_StateData *) g->stateData;
|
||||||
if (... /* there are still points to be generated */) {
|
if (... /* there are still points to be generated */) {
|
||||||
...
|
...
|
||||||
PGenSphReturnData retval = {.../*flags*/, .../*thePoint*/};
|
PGenSphReturnData retval = {.../*flags*/, .../*thePoint*/};
|
||||||
return retval;
|
return retval;
|
||||||
} else {
|
} else {
|
||||||
PGenSph_destroy(g);
|
PGen_destroy(g);
|
||||||
return PGenSphDoneVal;
|
return PGenSphDoneVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extractor, 3D cartesian coordinate output
|
||||||
|
PGenCart3ReturnData PGen_NAME_next_cart3(PGen *g) {
|
||||||
|
if (g->stateData == NULL) // already destroyed
|
||||||
|
return PGenCart3DoneVal;
|
||||||
|
else {
|
||||||
|
PGen_NAME_StateData *s = (PGen_NAME_StateData *) g->stateData;
|
||||||
|
if (... /* there are still points to be generated */) {
|
||||||
|
...
|
||||||
|
PGenCart3ReturnData retval = {.../*flags*/, .../*thePoint*/};
|
||||||
|
return retval;
|
||||||
|
} else {
|
||||||
|
PGen_destroy(g);
|
||||||
|
return PGenCart3DoneVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Class metadata structure; TODO maybe this can rather be done by macro.
|
// Class metadata structure; TODO maybe this can rather be done by macro.
|
||||||
const PGenSphClassInfo PGenSph_NAME = {
|
const PGenClassInfo PGen_NAME = {
|
||||||
"PGenSph_NAME",
|
"PGen_NAME",
|
||||||
PGenSph_NAME_next,
|
?, //dimensionality
|
||||||
PGenSph_NAME_destructor
|
// some of the _next_... fun pointers can be NULL
|
||||||
|
PGen_NAME_next_z,
|
||||||
|
PGen_NAME_next_pol,
|
||||||
|
PGen_NAME_next_sph,
|
||||||
|
PGen_NAME_next_cart2,
|
||||||
|
PGen_NAME_next_cart3,
|
||||||
|
PGen_NAME_destructor
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // 0
|
#endif // 0
|
||||||
|
@ -64,79 +88,102 @@ const PGenSphClassInfo PGenSph_NAME = {
|
||||||
//==== PGenSph_FromPoint2DArray ====
|
//==== PGenSph_FromPoint2DArray ====
|
||||||
|
|
||||||
// Internal state structure
|
// Internal state structure
|
||||||
typedef struct PGenSph_FromPoint2DArray_StateData {
|
typedef struct PGen_FromPoint2DArray_StateData {
|
||||||
const point2d *base;
|
const point2d *base;
|
||||||
size_t len;
|
size_t len;
|
||||||
size_t currentIndex;
|
size_t currentIndex;
|
||||||
}PGenSph_FromPoint2DArray_StateData;
|
}PGen_FromPoint2DArray_StateData;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
PGenSph PGenSph_FromPoint2DArray_new(const point2d *points, size_t len) {
|
PGen PGen_FromPoint2DArray_new(const point2d *points, size_t len) {
|
||||||
PGenSph_FromPoint2DArray_StateData *stateData = malloc(sizeof(PGenSph_FromPoint2DArray_StateData));
|
PGen_FromPoint2DArray_StateData *stateData = malloc(sizeof(PGen_FromPoint2DArray_StateData));
|
||||||
stateData->base = points;
|
stateData->base = points;
|
||||||
stateData->len = len;
|
stateData->len = len;
|
||||||
stateData->currentIndex = 0;
|
stateData->currentIndex = 0;
|
||||||
PGenSph g = {&PGenSph_FromPoint2DArray, (void *) stateData};
|
PGen g = {&PGen_FromPoint2DArray, (void *) stateData};
|
||||||
return g;
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
void PGenSph_FromPoint2DArray_destructor(PGenSph *g) {
|
void PGen_FromPoint2DArray_destructor(PGen *g) {
|
||||||
free(g->stateData);
|
free(g->stateData);
|
||||||
g->stateData = NULL;
|
g->stateData = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extractor
|
// Extractor, 2D cartesian (native)
|
||||||
PGenSphReturnData PGenSph_FromPoint2DArray_next(PGenSph *g) {
|
PGenCart2ReturnData PGen_FromPoint2DArray_next_cart2(PGen *g) {
|
||||||
|
if (g->stateData == NULL) // already destroyed
|
||||||
|
return PGenCart2DoneVal;
|
||||||
|
else {
|
||||||
|
PGen_FromPoint2DArray_StateData *s = (PGen_FromPoint2DArray_StateData *) g->stateData;
|
||||||
|
if (s->currentIndex < s->len) {
|
||||||
|
cart2_t thePoint = s->base[s->currentIndex];
|
||||||
|
++(s->currentIndex);
|
||||||
|
PGenCart2ReturnData retval = {(PGEN_AT_XY | PGEN_NEWR), thePoint};
|
||||||
|
return retval;
|
||||||
|
} else {
|
||||||
|
PGen_destroy(g);
|
||||||
|
return PGenCart2DoneVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extractor, spherical
|
||||||
|
PGenSphReturnData PGen_FromPoint2DArray_next_sph(PGen *g) {
|
||||||
if (g->stateData == NULL) // already destroyed
|
if (g->stateData == NULL) // already destroyed
|
||||||
return PGenSphDoneVal;
|
return PGenSphDoneVal;
|
||||||
else {
|
else {
|
||||||
PGenSph_FromPoint2DArray_StateData *s = (PGenSph_FromPoint2DArray_StateData *) g->stateData;
|
PGen_FromPoint2DArray_StateData *s = (PGen_FromPoint2DArray_StateData *) g->stateData;
|
||||||
if (s->currentIndex < s->len) {
|
if (s->currentIndex < s->len) {
|
||||||
sph_t thePoint = cart22sph(s->base[s->currentIndex]);
|
sph_t thePoint = cart22sph(s->base[s->currentIndex]);
|
||||||
++(s->currentIndex);
|
++(s->currentIndex);
|
||||||
PGenSphReturnData retval = {(PGEN_AT_XY | PGEN_NEWR), thePoint};
|
PGenSphReturnData retval = {(PGEN_AT_XY | PGEN_NEWR), thePoint};
|
||||||
return retval;
|
return retval;
|
||||||
} else {
|
} else {
|
||||||
PGenSph_destroy(g);
|
PGen_destroy(g);
|
||||||
return PGenSphDoneVal;
|
return PGenSphDoneVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const PGenSphClassInfo PGenSph_FromPoint2DArray = {
|
const PGenClassInfo PGen_FromPoint2DArray = {
|
||||||
"PGenSph_FromPoint2DArray",
|
"PGen_FromPoint2DArray",
|
||||||
PGenSph_FromPoint2DArray_next,
|
2, // dimensionality
|
||||||
PGenSph_FromPoint2DArray_destructor,
|
NULL,
|
||||||
|
NULL,//PGen_FromPoint2DArray_next_pol,
|
||||||
|
PGen_FromPoint2DArray_next_sph,
|
||||||
|
PGen_FromPoint2DArray_next_cart2,
|
||||||
|
NULL,//PGen_FromPoint2DArray_next_cart3,
|
||||||
|
PGen_FromPoint2DArray_destructor,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//==== PGenSph_zAxis ====
|
//==== PGen_1D ====
|
||||||
//equidistant points along the z-axis;
|
//equidistant points along the z-axis;
|
||||||
|
|
||||||
extern const PGenSphClassInfo PGenSph_zAxis; // forward declaration needed by constructor (may be placed in header file instead)
|
extern const PGenClassInfo PGen_1D; // forward declaration needed by constructor (may be placed in header file instead)
|
||||||
|
|
||||||
/* // This had to go to the header file:
|
/* // This had to go to the header file:
|
||||||
enum PGenSph_zAxis_incrementDirection{
|
enum PGen_1D_incrementDirection{
|
||||||
//PGENSPH_ZAXIS_POSITIVE_INC, // not implemented
|
//PGEN1D_POSITIVE_INC, // not implemented
|
||||||
//PGENSPH_ZAXIS_NEGATIVE_INC, // not implemented
|
//PGEN1D_NEGATIVE_INC, // not implemented
|
||||||
PGENSPH_ZAXIS_INC_FROM_ORIGIN,
|
PGEN1D_INC_FROM_ORIGIN,
|
||||||
PGENSPH_ZAXIS_INC_TOWARDS_ORIGIN
|
PGEN1D_INC_TOWARDS_ORIGIN
|
||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Internal state structure
|
// Internal state structure
|
||||||
typedef struct PGenSph_zAxis_StateData {
|
typedef struct PGen_1D_StateData {
|
||||||
long ptindex;
|
long ptindex;
|
||||||
//long stopindex;
|
//long stopindex;
|
||||||
double minR, maxR;
|
double minR, maxR;
|
||||||
bool inc_minR, inc_maxR;
|
bool inc_minR, inc_maxR;
|
||||||
double a; // lattice period
|
double a; // lattice period
|
||||||
double offset; // offset of the zeroth lattice point from origin (will be normalised to interval [-a/2,a/2]
|
double offset; // offset of the zeroth lattice point from origin (will be normalised to interval [-a/2,a/2]
|
||||||
enum PGenSph_zAxis_incrementDirection incdir;
|
enum PGen_1D_incrementDirection incdir;
|
||||||
//bool skip_origin;
|
//bool skip_origin;
|
||||||
} PGenSph_zAxis_StateData;
|
} PGen_1D_StateData;
|
||||||
|
|
||||||
static inline long ptindex_inc(long i) {
|
static inline long ptindex_inc(long i) {
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
|
@ -153,9 +200,9 @@ static inline long ptindex_dec(long i) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructor, specified by maximum and maximum absolute value
|
// Constructor, specified by maximum and maximum absolute value
|
||||||
PGenSph PGenSph_zAxis_new_minMaxR(double period, double offset, double minR, bool inc_minR, double maxR, bool inc_maxR,
|
PGen PGen_1D_new_minMaxR(double period, double offset, double minR, bool inc_minR, double maxR, bool inc_maxR,
|
||||||
PGenSph_zAxis_incrementDirection incdir) {
|
PGen_1D_incrementDirection incdir) {
|
||||||
PGenSph_zAxis_StateData *s = malloc(sizeof(PGenSph_zAxis_StateData));
|
PGen_1D_StateData *s = malloc(sizeof(PGen_1D_StateData));
|
||||||
s->minR = minR;
|
s->minR = minR;
|
||||||
s->maxR = maxR;
|
s->maxR = maxR;
|
||||||
s->inc_minR = inc_minR;
|
s->inc_minR = inc_minR;
|
||||||
|
@ -169,12 +216,12 @@ PGenSph PGenSph_zAxis_new_minMaxR(double period, double offset, double minR, boo
|
||||||
period *= -1;
|
period *= -1;
|
||||||
switch(s->incdir) {
|
switch(s->incdir) {
|
||||||
double curR;
|
double curR;
|
||||||
case PGENSPH_ZAXIS_INC_FROM_ORIGIN:
|
case PGEN_1D_INC_FROM_ORIGIN:
|
||||||
s->ptindex = floor(minR / fabs(period));
|
s->ptindex = floor(minR / fabs(period));
|
||||||
while ( (curR = fabs(s->offset + s->ptindex * period)) < minR || (!inc_minR && curR <= minR))
|
while ( (curR = fabs(s->offset + s->ptindex * period)) < minR || (!inc_minR && curR <= minR))
|
||||||
s->ptindex = ptindex_inc(s->ptindex);
|
s->ptindex = ptindex_inc(s->ptindex);
|
||||||
break;
|
break;
|
||||||
case PGENSPH_ZAXIS_INC_TOWARDS_ORIGIN:
|
case PGEN_1D_INC_TOWARDS_ORIGIN:
|
||||||
s->ptindex = - ceil(maxR / fabs(period));
|
s->ptindex = - ceil(maxR / fabs(period));
|
||||||
while ( (curR = fabs(s->offset + s->ptindex * period)) > maxR || (!inc_minR && curR >= maxR))
|
while ( (curR = fabs(s->offset + s->ptindex * period)) > maxR || (!inc_minR && curR >= maxR))
|
||||||
s->ptindex = ptindex_dec(s->ptindex);
|
s->ptindex = ptindex_dec(s->ptindex);
|
||||||
|
@ -184,31 +231,66 @@ PGenSph PGenSph_zAxis_new_minMaxR(double period, double offset, double minR, boo
|
||||||
}
|
}
|
||||||
s->a = period;
|
s->a = period;
|
||||||
|
|
||||||
PGenSph g = {&PGenSph_zAxis, (void *) s};
|
PGen g = {&PGen_1D, (void *) s};
|
||||||
return g;
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dectructor
|
// Dectructor
|
||||||
void PGenSph_zAxis_destructor(PGenSph *g) {
|
void PGen_1D_destructor(PGen *g) {
|
||||||
free(g->stateData);
|
free(g->stateData);
|
||||||
g->stateData = NULL;
|
g->stateData = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extractor
|
// Extractor 1D number
|
||||||
PGenSphReturnData PGenSph_zAxis_next(PGenSph *g) {
|
PGenZReturnData PGen_1D_next_z(PGen *g) {
|
||||||
if (g->stateData == NULL) // already destroyed
|
if (g->stateData == NULL) // already destroyed
|
||||||
return PGenSphDoneVal;
|
return PGenZDoneVal;
|
||||||
PGenSph_zAxis_StateData *s = (PGenSph_zAxis_StateData *) g->stateData;
|
PGen_1D_StateData *s = (PGen_1D_StateData *) g->stateData;
|
||||||
const double zval = s->ptindex * s->a + s->offset;
|
const double zval = s->ptindex * s->a + s->offset;
|
||||||
const double r = fabs(zval);
|
const double r = fabs(zval);
|
||||||
bool theEnd = false;
|
bool theEnd = false;
|
||||||
switch (s->incdir) {
|
switch (s->incdir) {
|
||||||
case PGENSPH_ZAXIS_INC_FROM_ORIGIN:
|
case PGEN_1D_INC_FROM_ORIGIN:
|
||||||
if (r < s->maxR || (s->inc_maxR && r == s->maxR))
|
if (r < s->maxR || (s->inc_maxR && r == s->maxR))
|
||||||
s->ptindex = ptindex_inc(s->ptindex);
|
s->ptindex = ptindex_inc(s->ptindex);
|
||||||
else theEnd = true;
|
else theEnd = true;
|
||||||
break;
|
break;
|
||||||
case PGENSPH_ZAXIS_INC_TOWARDS_ORIGIN:
|
case PGEN_1D_INC_TOWARDS_ORIGIN:
|
||||||
|
if (r > s->minR || (s->inc_minR && r == s->minR)) {
|
||||||
|
if (s->ptindex == 0) // handle "underflow"
|
||||||
|
s->minR = INFINITY;
|
||||||
|
else
|
||||||
|
s->ptindex = ptindex_dec(s->ptindex);
|
||||||
|
} else theEnd = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort(); // invalid value
|
||||||
|
}
|
||||||
|
if (!theEnd) {
|
||||||
|
const PGenZReturnData retval = {PGEN_NOTDONE | PGEN_NEWR | PGEN_AT_Z,
|
||||||
|
zval};
|
||||||
|
return retval;
|
||||||
|
} else {
|
||||||
|
PGen_destroy(g);
|
||||||
|
return PGenZDoneVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extractor spherical coordinates // TODO remove/simplify
|
||||||
|
PGenSphReturnData PGen_1D_next_sph(PGen *g) {
|
||||||
|
if (g->stateData == NULL) // already destroyed
|
||||||
|
return PGenSphDoneVal;
|
||||||
|
PGen_1D_StateData *s = (PGen_1D_StateData *) g->stateData;
|
||||||
|
const double zval = s->ptindex * s->a + s->offset;
|
||||||
|
const double r = fabs(zval);
|
||||||
|
bool theEnd = false;
|
||||||
|
switch (s->incdir) {
|
||||||
|
case PGEN_1D_INC_FROM_ORIGIN:
|
||||||
|
if (r < s->maxR || (s->inc_maxR && r == s->maxR))
|
||||||
|
s->ptindex = ptindex_inc(s->ptindex);
|
||||||
|
else theEnd = true;
|
||||||
|
break;
|
||||||
|
case PGEN_1D_INC_TOWARDS_ORIGIN:
|
||||||
if (r > s->minR || (s->inc_minR && r == s->minR)) {
|
if (r > s->minR || (s->inc_minR && r == s->minR)) {
|
||||||
if (s->ptindex == 0) // handle "underflow"
|
if (s->ptindex == 0) // handle "underflow"
|
||||||
s->minR = INFINITY;
|
s->minR = INFINITY;
|
||||||
|
@ -224,133 +306,81 @@ PGenSphReturnData PGenSph_zAxis_next(PGenSph *g) {
|
||||||
{r, zval >= 0 ? 0 : M_PI, 0}};
|
{r, zval >= 0 ? 0 : M_PI, 0}};
|
||||||
return retval;
|
return retval;
|
||||||
} else {
|
} else {
|
||||||
PGenSph_destroy(g);
|
PGen_destroy(g);
|
||||||
return PGenSphDoneVal;
|
return PGenSphDoneVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Class metadata structure; TODO maybe this can rather be done by macro.
|
// Class metadata structure; TODO maybe this can rather be done by macro.
|
||||||
const PGenSphClassInfo PGenSph_zAxis = {
|
const PGenClassInfo PGen_1D = {
|
||||||
"PGenSph_zAxis",
|
"PGen_1D",
|
||||||
PGenSph_zAxis_next,
|
1, // dimensionality
|
||||||
PGenSph_zAxis_destructor
|
PGen_1D_next_z,
|
||||||
|
NULL,//PGen_1D_next_pol,
|
||||||
|
PGen_1D_next_sph,
|
||||||
|
NULL,//PGen_1D_next_cart2,
|
||||||
|
NULL,//PGen_1D_next_cart3,
|
||||||
|
PGen_1D_destructor
|
||||||
};
|
};
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
//==== PGenSph_xyWeb ====
|
//==== PGen_xyWeb ====
|
||||||
// 2D lattice generator in the "spiderweb" style, generated in the "perimetre" order,
|
// 2D lattice generator in the "spiderweb" style, generated in the "perimetre" order,
|
||||||
// not strictly ordered (or limited) by distance from origin.
|
// not strictly ordered (or limited) by distance from origin.
|
||||||
// The minR and maxR here refer to the TODO WWHAT
|
// The minR and maxR here refer to the TODO WWHAT
|
||||||
|
|
||||||
extern const PGenSphClassInfo PGenSph_xyWeb; // forward declaration needed by constructor (may be placed in header file instead)
|
extern const PGenClassInfo PGen_xyWeb; // forward declaration needed by constructor (may be placed in header file instead)
|
||||||
|
|
||||||
// Internal state structure
|
// Internal state structure
|
||||||
typedef struct PGenSph_xyWeb_StateData {
|
typedef struct PGen_xyWeb_StateData {
|
||||||
long i, j;
|
long i, j;
|
||||||
//long stopindex;
|
unsigned short phase; // 0 to 5
|
||||||
|
long layer;
|
||||||
|
double layer_min_height; // this * layer is what minR and maxR are compared to
|
||||||
double minR, maxR;
|
double minR, maxR;
|
||||||
bool inc_minR, inc_maxR;
|
bool inc_minR, inc_maxR;
|
||||||
cart2_t b1, b2; // lattice vectors
|
cart2_t b1, b2; // lattice vectors
|
||||||
cart2_t offset; // offset of the zeroth lattice point from origin (will be normalised to the WS cell)
|
cart2_t offset; // offset of the zeroth lattice point from origin (will be normalised to the WS cell)
|
||||||
} PGenSph_xyWeb_StateData;
|
} PGen_xyWeb_StateData;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
PGenSph PGenSph_xyWeb_new(...) {
|
PGen PGen_xyWeb_new(...) {
|
||||||
g->stateData = malloc(sizeof(PGenSph_xyWeb_StateData));
|
g->stateData = malloc(sizeof(PGen_xyWeb_StateData));
|
||||||
...
|
...
|
||||||
PGenSph g = {&PGenSph_xyWeb, (void *) stateData};
|
PGen g = {&PGen_xyWeb, (void *) stateData};
|
||||||
return g;
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dectructor
|
// Dectructor
|
||||||
void PGenSph_xyWeb_dectructor(PGenSph *g) {
|
void PGen_xyWeb_dectructor(PGen *g) {
|
||||||
...
|
...
|
||||||
free(g->stateData);
|
free(g->stateData);
|
||||||
g->stateData = NULL;
|
g->stateData = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extractor
|
// Extractor (2D cartesian, native)
|
||||||
PGenSphReturnData PGenSph_xyWeb_next(PGenSph *g) {
|
PGenCart2ReturnData PGen_xyWeb_next_cart2(PGen *g) {
|
||||||
if (g->stateData == NULL) // already destroyed
|
if (g->stateData == NULL) // already destroyed
|
||||||
return PGenSphDoneVal;
|
return PGenDoneVal;
|
||||||
else {
|
else {
|
||||||
PGenSph_xyWeb_StateData *s = (PGenSph_xyWeb_StateData *) g->stateData;
|
PGen_xyWeb_StateData *s = (PGen_xyWeb_StateData *) g->stateData;
|
||||||
if (... /* there are still points to be generated */) {
|
if (... /* there are still points to be generated */) {
|
||||||
...
|
...
|
||||||
PGenSphReturnData retval = {.../*flags*/, .../*thePoint*/};
|
PGenReturnData retval = {.../*flags*/, .../*thePoint*/};
|
||||||
return retval;
|
return retval;
|
||||||
} else {
|
} else {
|
||||||
PGenSph_destroy(g);
|
PGen_destroy(g);
|
||||||
return PGenSphDoneVal;
|
return PGenDoneVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Class metadata structure; TODO maybe this can rather be done by macro.
|
// Class metadata structure; TODO maybe this can rather be done by macro.
|
||||||
const PGenSphClassInfo PGenSph_xyWeb = {
|
const PGenClassInfo PGen_xyWeb = {
|
||||||
"PGenSph_xyWeb",
|
"PGen_xyWeb",
|
||||||
PGenSph_xyWeb_next,
|
PGen_xyWeb_next,
|
||||||
PGenSph_xyWeb_destructor
|
PGen_xyWeb_destructor
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // 0
|
#endif // 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
//==== PGenSph_xyPlane ==== //TODO
|
|
||||||
|
|
||||||
extern const PGenSphClassInfo PGenSph_xyPlane; // forward declaration needed by constructor (may be placed in header file instead)
|
|
||||||
|
|
||||||
// Internal state structure
|
|
||||||
typedef struct PGenSph_xyPlane_StateData {
|
|
||||||
long i, j;
|
|
||||||
//long stopindex;
|
|
||||||
double minR, maxR;
|
|
||||||
bool inc_minR, inc_maxR;
|
|
||||||
cart2_t b1, b2; // lattice vectors
|
|
||||||
cart2_t offset; // offset of the zeroth lattice point from origin (will be normalised to the WS cell)
|
|
||||||
} PGenSph_xyPlane_StateData;
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
PGenSph PGenSph_xyPlane_new(...) {
|
|
||||||
g->stateData = malloc(sizeof(PGenSph_xyPlane_StateData));
|
|
||||||
...
|
|
||||||
PGenSph g = {&PGenSph_xyPlane, (void *) stateData};
|
|
||||||
return g;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dectructor
|
|
||||||
void PGenSph_xyPlane_dectructor(PGenSph *g) {
|
|
||||||
...
|
|
||||||
free(g->stateData);
|
|
||||||
g->stateData = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extractor
|
|
||||||
PGenSphReturnData PGenSph_xyPlane_next(PGenSph *g) {
|
|
||||||
if (g->stateData == NULL) // already destroyed
|
|
||||||
return PGenSphDoneVal;
|
|
||||||
else {
|
|
||||||
PGenSph_xyPlane_StateData *s = (PGenSph_xyPlane_StateData *) g->stateData;
|
|
||||||
if (... /* there are still points to be generated */) {
|
|
||||||
...
|
|
||||||
PGenSphReturnData retval = {.../*flags*/, .../*thePoint*/};
|
|
||||||
return retval;
|
|
||||||
} else {
|
|
||||||
PGenSph_destroy(g);
|
|
||||||
return PGenSphDoneVal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Class metadata structure; TODO maybe this can rather be done by macro.
|
|
||||||
const PGenSphClassInfo PGenSph_xyPlane = {
|
|
||||||
"PGenSph_xyPlane",
|
|
||||||
PGenSph_xyPlane_next,
|
|
||||||
PGenSph_xyPlane_destructor
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // 0
|
|
||||||
|
|
||||||
|
|
||||||
|
|
118
qpms/lattices.h
118
qpms/lattices.h
|
@ -57,15 +57,15 @@ static inline point2d point2d_fromxy(const double x, const double y) {
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GENERIC LATTICE POINT GENERATOR TYPE PGenSph
|
* GENERIC LATTICE POINT GENERATOR TYPE PGen
|
||||||
* ============================================
|
* ============================================
|
||||||
*
|
*
|
||||||
* A bit of OOP-in-C brainfuck here.
|
* A bit of OOP-in-C brainfuck here.
|
||||||
*
|
*
|
||||||
* The basic principle of operation is following:
|
* The basic principle of operation is following:
|
||||||
* Instead of a list (array) of points, an initialized PGenSph object
|
* Instead of a list (array) of points, an initialized PGen object
|
||||||
* is passed to a function that does something over a set of points.
|
* is passed to a function that does something over a set of points.
|
||||||
* Each time PGenSph-type object is "called", it returns PGenSphReturnData,
|
* Each time PGen-type object is "called", it returns PGenReturnData,
|
||||||
* which contains a point in spherical coordinates (sph_t) and some metadata.
|
* which contains a point in spherical coordinates (sph_t) and some metadata.
|
||||||
*
|
*
|
||||||
* After the last generated point, the generator frees all internal memory
|
* After the last generated point, the generator frees all internal memory
|
||||||
|
@ -73,15 +73,15 @@ static inline point2d point2d_fromxy(const double x, const double y) {
|
||||||
* shall be considered invalid data).
|
* shall be considered invalid data).
|
||||||
* The caller can also decide not to use the rest and end getting the points
|
* The caller can also decide not to use the rest and end getting the points
|
||||||
* even when the PGEN_NOTDONE was set in the last returned data.
|
* even when the PGEN_NOTDONE was set in the last returned data.
|
||||||
* In such case, the caller shall call PGenSph_destroy() manually.
|
* In such case, the caller shall call PGen_destroy() manually.
|
||||||
*
|
*
|
||||||
* MEMORY MANAGEMENT POLICY
|
* MEMORY MANAGEMENT POLICY
|
||||||
* ------------------------
|
* ------------------------
|
||||||
* The basic PGenSph structure shall be allocated on stack (it's only two pointers),
|
* The basic PGen structure shall be allocated on stack (it's only two pointers),
|
||||||
* everything internal goes on heap.
|
* everything internal goes on heap.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct PGenSph; // full definition below
|
struct PGen; // full definition below
|
||||||
|
|
||||||
typedef enum PGenPointFlags {
|
typedef enum PGenPointFlags {
|
||||||
PGEN_NOTDONE = 2, // The most important flag: when this is not set, the interation ended – other data returned should be considered nonsense and at this point, the generator should have de-allocated all internal memory.
|
PGEN_NOTDONE = 2, // The most important flag: when this is not set, the interation ended – other data returned should be considered nonsense and at this point, the generator should have de-allocated all internal memory.
|
||||||
|
@ -91,56 +91,120 @@ typedef enum PGenPointFlags {
|
||||||
PGEN_DONE = 0, // convenience value, not an actual flag
|
PGEN_DONE = 0, // convenience value, not an actual flag
|
||||||
} PGenPointFlags;
|
} PGenPointFlags;
|
||||||
|
|
||||||
|
typedef struct PGenZReturnData {
|
||||||
|
PGenPointFlags flags; // metatada
|
||||||
|
double point_z;
|
||||||
|
} PGenZReturnData;
|
||||||
|
|
||||||
|
typedef struct PGenPolReturnData {
|
||||||
|
PGenPointFlags flags; // metatada
|
||||||
|
pol_t point_pol;
|
||||||
|
} PGenPolReturnData;
|
||||||
|
|
||||||
typedef struct PGenSphReturnData {
|
typedef struct PGenSphReturnData {
|
||||||
PGenPointFlags flags; // metatada
|
PGenPointFlags flags; // metatada
|
||||||
sph_t point_sph; // the actual point data
|
sph_t point_sph; // the actual point data
|
||||||
} PGenSphReturnData;
|
} PGenSphReturnData;
|
||||||
|
|
||||||
static const PGenSphReturnData PGenSphDoneVal = {PGEN_DONE, {0,0,0}}; // convenience constant for use in the exctractor implementations
|
typedef struct PGenCart2ReturnData {
|
||||||
|
PGenPointFlags flags; // metatada
|
||||||
|
cart2_t point_cart2; // the actual point data
|
||||||
|
} PGenCart2ReturnData;
|
||||||
|
|
||||||
|
typedef struct PGenCart3ReturnData {
|
||||||
|
PGenPointFlags flags; // metatada
|
||||||
|
cart3_t point_cart3; // the actual point data
|
||||||
|
} PGenCart3ReturnData;
|
||||||
|
|
||||||
|
// convenience constants for use in the extractor implementations
|
||||||
|
static const PGenZReturnData PGenZDoneVal = {PGEN_DONE, 0};
|
||||||
|
static const PGenPolReturnData PGenPolDoneVal = {PGEN_DONE, {0,0}};
|
||||||
|
static const PGenSphReturnData PGenSphDoneVal = {PGEN_DONE, {0,0,0}};
|
||||||
|
static const PGenCart2ReturnData PGenCart2DoneVal = {PGEN_DONE, {0,0}};
|
||||||
|
static const PGenCart3ReturnData PGenCart3DoneVal = {PGEN_DONE, {0,0,0}};
|
||||||
|
|
||||||
typedef struct PGenSphClassInfo { // static PGenSph info
|
typedef struct PGenSphClassInfo { // static PGenSph info
|
||||||
char * const name; // mainly for debugging purposes
|
char * const name; // mainly for debugging purposes
|
||||||
PGenSphReturnData (*next)(struct PGenSph *); // This contains the actual generator procedure (TODO shouldn't I rather point to stateData?)
|
int dimensionality; // lower-dimensional can be converted to higher-D, not vice versa
|
||||||
void (*destructor)(struct PGenSph *); // Destructor to be called by next() at iteration end, or by the caller if ending the generation prematurely
|
// TODO info about native coordinate system
|
||||||
} PGenSphClassInfo;
|
PGenZReturnData (*next_z)(struct PGen *);
|
||||||
|
PGenPolReturnData (*next_pol)(struct PGen *); // This contains the actual generator procedure (TODO shouldn't I rather point to stateData?)
|
||||||
|
PGenSphReturnData (*next_sph)(struct PGen *);
|
||||||
|
PGenCart2ReturnData (*next_cart2)(struct PGen *);
|
||||||
|
PGenCart3ReturnData (*next_cart3)(struct PGen *);
|
||||||
|
void (*destructor)(struct PGen *); // Destructor to be called by next() at iteration end, or by the caller if ending the generation prematurely
|
||||||
|
} PGenClassInfo;
|
||||||
|
|
||||||
// TOP DATA STRUCTURE DEFINITION HERE
|
// TOP DATA STRUCTURE DEFINITION HERE
|
||||||
typedef struct PGenSph {
|
typedef struct PGen {
|
||||||
const PGenSphClassInfo * /*const*/ c;
|
const PGenClassInfo * /*const*/ c;
|
||||||
void *stateData; // shall be NULL if invalid (destroyed)
|
void *stateData; // shall be NULL if invalid (destroyed)
|
||||||
} PGenSph;
|
} PGen;
|
||||||
|
|
||||||
static inline void PGenSph_destroy(PGenSph *g) {
|
static inline void PGen_destroy(PGen *g) {
|
||||||
g->c->destructor(g);
|
g->c->destructor(g);
|
||||||
assert(g->stateData == NULL); // this should be done by the destructor
|
assert(g->stateData == NULL); // this should be done by the destructor
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline PGenSphReturnData PGenSph_next(PGenSph *g) {
|
static inline PGenSphReturnData PGen_next_sph(PGen *g) {
|
||||||
// TODO maybe some asserts around here
|
// TODO maybe some asserts around here
|
||||||
return g->c->next(g);
|
if (g->c->next_sph)
|
||||||
|
return g->c->next_sph(g);
|
||||||
|
else abort(); // the current point generator does not support this type of output
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline PGenCart3ReturnData PGen_next_cart3(PGen *g) {
|
||||||
|
// TODO maybe some asserts around here
|
||||||
|
if (g->c->next_cart3)
|
||||||
|
return g->c->next_cart3(g);
|
||||||
|
else abort(); // the current point generator does not support this type of output
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline PGenCart2ReturnData PGen_next_cart2(PGen *g) {
|
||||||
|
// TODO maybe some asserts around here
|
||||||
|
if (g->c->next_cart2)
|
||||||
|
return g->c->next_cart2(g);
|
||||||
|
else abort(); // the current point generator does not support this type of output
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool PGenSph_notDone(PGenSphReturnData data) {
|
static inline bool PGenSph_notDone(PGenSphReturnData data) {
|
||||||
return data.flags & PGEN_NOTDONE ? true : false;
|
return data.flags & PGEN_NOTDONE ? true : false;
|
||||||
}
|
}
|
||||||
|
static inline bool PGenCart3_notDone(PGenCart3ReturnData data) {
|
||||||
|
return data.flags & PGEN_NOTDONE ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline PGenCart3ReturnData PGenReturnDataConv_sph_cart3(PGenSphReturnData sphdata){
|
||||||
|
PGenCart3ReturnData c3data;
|
||||||
|
c3data.flags = sphdata.flags;
|
||||||
|
c3data.point_cart3 = sph2cart(sphdata.point_sph);
|
||||||
|
return c3data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline PGenSphReturnData PGenReturnDataConv_cart3_sph(PGenCart3ReturnData c){
|
||||||
|
PGenSphReturnData s;
|
||||||
|
s.flags = c.flags;
|
||||||
|
s.point_sph = cart2sph(c.point_cart3);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Some basic lattice generators implementing the abstract interface above (implemented in latticegens.c).
|
* Some basic lattice generators implementing the abstract interface above (implemented in latticegens.c).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This one simply iterates over an existing array of Point2d
|
// This one simply iterates over an existing array of Point2d
|
||||||
extern const PGenSphClassInfo PGenSph_FromPoint2DArray; // TODO Do I even need this to be declared here?
|
extern const PGenClassInfo PGen_FromPoint2DArray; // TODO Do I even need this to be declared here?
|
||||||
PGenSph PGenSph_FromPoints2DArray_new(const point2d *points, size_t len);
|
PGen PGen_FromPoints2DArray_new(const point2d *points, size_t len);
|
||||||
|
|
||||||
extern const PGenSphClassInfo PGenSph_zAxis;
|
extern const PGenClassInfo PGen_1D;
|
||||||
typedef enum PGenSph_zAxis_incrementDirection{
|
typedef enum PGen_1D_incrementDirection{
|
||||||
//PGENSPH_ZAXIS_POSITIVE_INC, // not implemented
|
//PGEN_1D_POSITIVE_INC, // not implemented
|
||||||
//PGENSPH_ZAXIS_NEGATIVE_INC, // not implemented
|
//PGEN_1D_NEGATIVE_INC, // not implemented
|
||||||
PGENSPH_ZAXIS_INC_FROM_ORIGIN,
|
PGEN_1D_INC_FROM_ORIGIN,
|
||||||
PGENSPH_ZAXIS_INC_TOWARDS_ORIGIN
|
PGEN_1D_INC_TOWARDS_ORIGIN
|
||||||
} PGenSph_zAxis_incrementDirection;
|
} PGen_1D_incrementDirection;
|
||||||
PGenSph PGenSph_zAxis_new_minMaxR(double period, double offset, double minR, bool inc_minR, double maxR, bool inc_maxR,
|
PGen PGen_1D_new_minMaxR(double period, double offset, double minR, bool inc_minR, double maxR, bool inc_maxR,
|
||||||
PGenSph_zAxis_incrementDirection incdir);
|
PGen_1D_incrementDirection incdir);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -10,10 +10,10 @@ void print_PGenSphReturnData(PGenSphReturnData d) {
|
||||||
s.r, s.theta / M_PI, s.phi / M_PI, c.x, c.y, c.z, d.flags);
|
s.r, s.theta / M_PI, s.phi / M_PI, c.x, c.y, c.z, d.flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_PGenSph(PGenSph *g) {
|
void dump_PGenSph(PGen *g) {
|
||||||
PGenSphReturnData d;
|
PGenSphReturnData d;
|
||||||
do {
|
do {
|
||||||
d = PGenSph_next(g);
|
d = PGen_next_sph(g);
|
||||||
print_PGenSphReturnData(d);
|
print_PGenSphReturnData(d);
|
||||||
} while (d.flags & PGEN_NOTDONE);
|
} while (d.flags & PGEN_NOTDONE);
|
||||||
}
|
}
|
||||||
|
@ -21,26 +21,26 @@ void dump_PGenSph(PGenSph *g) {
|
||||||
#define DO_AND_PRINT(label, s) printf(#label ":\n" #s "\n"); s ;
|
#define DO_AND_PRINT(label, s) printf(#label ":\n" #s "\n"); s ;
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
PGenSph g;
|
PGen g;
|
||||||
DO_AND_PRINT(test1a, g = PGenSph_zAxis_new_minMaxR(0.2, 0.14, 5, true, 7, true, PGENSPH_ZAXIS_INC_FROM_ORIGIN))
|
DO_AND_PRINT(test1a, g = PGen_1D_new_minMaxR(0.2, 0.14, 5, true, 7, true, PGEN_1D_INC_FROM_ORIGIN))
|
||||||
dump_PGenSph(&g);
|
dump_PGenSph(&g);
|
||||||
DO_AND_PRINT(test1b, g = PGenSph_zAxis_new_minMaxR(0.2, 0.14, 5, true, 7, true, PGENSPH_ZAXIS_INC_TOWARDS_ORIGIN))
|
DO_AND_PRINT(test1b, g = PGen_1D_new_minMaxR(0.2, 0.14, 5, true, 7, true, PGEN_1D_INC_TOWARDS_ORIGIN))
|
||||||
dump_PGenSph(&g);
|
dump_PGenSph(&g);
|
||||||
DO_AND_PRINT(test2a, g = PGenSph_zAxis_new_minMaxR(0.2, 0.05, 5.05, true, 7.05, true, PGENSPH_ZAXIS_INC_FROM_ORIGIN))
|
DO_AND_PRINT(test2a, g = PGen_1D_new_minMaxR(0.2, 0.05, 5.05, true, 7.05, true, PGEN_1D_INC_FROM_ORIGIN))
|
||||||
dump_PGenSph(&g);
|
dump_PGenSph(&g);
|
||||||
DO_AND_PRINT(test2b, g = PGenSph_zAxis_new_minMaxR(0.2, 0.05, 5.05, true, 7.05, true, PGENSPH_ZAXIS_INC_TOWARDS_ORIGIN))
|
DO_AND_PRINT(test2b, g = PGen_1D_new_minMaxR(0.2, 0.05, 5.05, true, 7.05, true, PGEN_1D_INC_TOWARDS_ORIGIN))
|
||||||
dump_PGenSph(&g);
|
dump_PGenSph(&g);
|
||||||
DO_AND_PRINT(test3a, g = PGenSph_zAxis_new_minMaxR(0.2, 0.05, 5.05, false, 7.05, false, PGENSPH_ZAXIS_INC_FROM_ORIGIN))
|
DO_AND_PRINT(test3a, g = PGen_1D_new_minMaxR(0.2, 0.05, 5.05, false, 7.05, false, PGEN_1D_INC_FROM_ORIGIN))
|
||||||
dump_PGenSph(&g);
|
dump_PGenSph(&g);
|
||||||
DO_AND_PRINT(test3b, g = PGenSph_zAxis_new_minMaxR(0.2, 0.05, 5.05, false, 7.05, false, PGENSPH_ZAXIS_INC_TOWARDS_ORIGIN))
|
DO_AND_PRINT(test3b, g = PGen_1D_new_minMaxR(0.2, 0.05, 5.05, false, 7.05, false, PGEN_1D_INC_TOWARDS_ORIGIN))
|
||||||
dump_PGenSph(&g);
|
dump_PGenSph(&g);
|
||||||
DO_AND_PRINT(test4a, g = PGenSph_zAxis_new_minMaxR(0.2, 0.0, 0, false, 1, false, PGENSPH_ZAXIS_INC_FROM_ORIGIN))
|
DO_AND_PRINT(test4a, g = PGen_1D_new_minMaxR(0.2, 0.0, 0, false, 1, false, PGEN_1D_INC_FROM_ORIGIN))
|
||||||
dump_PGenSph(&g);
|
dump_PGenSph(&g);
|
||||||
DO_AND_PRINT(test4b, g = PGenSph_zAxis_new_minMaxR(0.2, 0.0, 0, false, 1, false, PGENSPH_ZAXIS_INC_TOWARDS_ORIGIN))
|
DO_AND_PRINT(test4b, g = PGen_1D_new_minMaxR(0.2, 0.0, 0, false, 1, false, PGEN_1D_INC_TOWARDS_ORIGIN))
|
||||||
dump_PGenSph(&g);
|
dump_PGenSph(&g);
|
||||||
DO_AND_PRINT(test5a, g = PGenSph_zAxis_new_minMaxR(0.2, 0.0, 0, true, 1, true, PGENSPH_ZAXIS_INC_FROM_ORIGIN))
|
DO_AND_PRINT(test5a, g = PGen_1D_new_minMaxR(0.2, 0.0, 0, true, 1, true, PGEN_1D_INC_FROM_ORIGIN))
|
||||||
dump_PGenSph(&g);
|
dump_PGenSph(&g);
|
||||||
DO_AND_PRINT(test5b, g = PGenSph_zAxis_new_minMaxR(0.2, 0.0, 0, true, 1, true, PGENSPH_ZAXIS_INC_TOWARDS_ORIGIN))
|
DO_AND_PRINT(test5b, g = PGen_1D_new_minMaxR(0.2, 0.0, 0, true, 1, true, PGEN_1D_INC_TOWARDS_ORIGIN))
|
||||||
dump_PGenSph(&g);
|
dump_PGenSph(&g);
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue