From 56c102de949f691d6e5674c17b7724b7933d0980 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Wed, 22 Aug 2018 00:00:59 +0200 Subject: [PATCH] tailored allocation, and increased MAX_EDGE to 14 --- archimedean.cpp | 11 ++++----- barriers.cpp | 2 +- bigstuff.cpp | 3 +-- binary-tiling.cpp | 2 +- cell.cpp | 8 +++---- heptagon.cpp | 3 +-- hyper.h | 61 ++++++++++++++++++++++++++++++++++++++++------- 7 files changed, 65 insertions(+), 25 deletions(-) diff --git a/archimedean.cpp b/archimedean.cpp index 8e781d44..e9af294a 100644 --- a/archimedean.cpp +++ b/archimedean.cpp @@ -410,7 +410,8 @@ struct hrmap_archimedean : hrmap { heptagon *getOrigin() { return origin; } hrmap_archimedean() { - origin = new heptagon; + int N0 = isize(current.adjacent[0]); + origin = tailored_alloc (N0); origin->s = hsOrigin; origin->emeraldval = 0; origin->zebraval = 0; @@ -418,23 +419,21 @@ struct hrmap_archimedean : hrmap { origin->fieldval = 0; origin->rval0 = origin->rval1 = 0; origin->cdata = NULL; - origin->c.clear(); origin->alt = NULL; origin->distance = 0; parent_index_of(origin) = 0; id_of(origin) = 0; - origin->c7 = newCell(isize(current.adjacent[0]), origin); + origin->c7 = newCell(N0, origin); heptagon *alt = NULL; if(hyperbolic) { dynamicval g(geometry, gNormal); - alt = new heptagon; + alt = tailored_alloc (S7); alt->s = hsOrigin; alt->emeraldval = 0; alt->zebraval = 0; - alt->c.clear(); alt->distance = 0; alt->c7 = NULL; alt->alt = alt; @@ -491,7 +490,7 @@ transmatrix adjcell_matrix(heptagon *h, int d); heptagon *build_child(heptspin p, pair adj) { indenter ind; - auto h = buildHeptagon1(new heptagon, p.at, p.spin, hstate(1), 0); + auto h = buildHeptagon1(tailored_alloc (isize(current.adjacent[adj.first])), p.at, p.spin, hstate(1), 0); SDEBUG( printf("NEW %p.%d ~ %p.0\n", p.at, p.spin, h); ) id_of(h) = adj.first; parent_index_of(h) = adj.second; diff --git a/barriers.cpp b/barriers.cpp index f6481f0f..616cd18f 100644 --- a/barriers.cpp +++ b/barriers.cpp @@ -741,7 +741,7 @@ bool buildBarrierNowall(cell *c, eLand l2, int forced_dir) { bool warpv = warped_version(c->land, l2); if(warpv && !archimedean && !pseudohept(c)) return false; - int ds[8]; + int ds[MAX_EDGE]; for(int i=0; itype; i++) ds[i] = i; for(int j=0; jtype; j++) swap(ds[j], ds[hrand(j+1)]); diff --git a/bigstuff.cpp b/bigstuff.cpp index a6f47672..086b5eca 100644 --- a/bigstuff.cpp +++ b/bigstuff.cpp @@ -202,13 +202,12 @@ heptagon *createAlternateMap(cell *c, int rad, hstate firststate, int special) { if(polarb50(c) != 1) return NULL; } - heptagon *alt = new heptagon; + heptagon *alt = tailored_alloc (S7); allmaps.push_back(newAltMap(alt)); //printf("new alt {%p}\n", alt); alt->s = firststate; alt->emeraldval = 0; alt->zebraval = 0; - alt->c.clear(); alt->distance = 0; alt->c7 = NULL; alt->alt = alt; diff --git a/binary-tiling.cpp b/binary-tiling.cpp index 112fde6d..2300980d 100644 --- a/binary-tiling.cpp +++ b/binary-tiling.cpp @@ -77,7 +77,7 @@ namespace binary { } heptagon *build(heptagon *parent, int d, int d1, int t, int side, int delta) { - auto h = buildHeptagon1(new heptagon, parent, d, hsOrigin, d1); + auto h = buildHeptagon1(tailored_alloc (t), parent, d, hsOrigin, d1); h->distance = parent->distance + delta; h->c7 = newCell(t, h); h->cdata = NULL; diff --git a/cell.cpp b/cell.cpp index 2594e42d..11aaf4d5 100644 --- a/cell.cpp +++ b/cell.cpp @@ -22,10 +22,9 @@ int cellcount = 0; void initcell(cell *c); // from game.cpp cell *newCell(int type, heptagon *master) { - cell *c = new cell; + cell *c = tailored_alloc (type); c->type = type; c->master = master; - for(int i=0; imove(i) = NULL; initcell(c); return c; } @@ -52,7 +51,7 @@ hrmap *newAltMap(heptagon *o) { return new hrmap_alternate(o); } hrmap_hyperbolic::hrmap_hyperbolic() { // printf("Creating hyperbolic map: %p\n", this); - origin = new heptagon; + origin = tailored_alloc (S7); heptagon& h = *origin; h.s = hsOrigin; h.emeraldval = a46 ? 0 : 98; @@ -61,7 +60,6 @@ hrmap_hyperbolic::hrmap_hyperbolic() { h.fieldval = 0; h.rval0 = h.rval1 = 0; h.cdata = NULL; - h.c.clear(); h.alt = NULL; h.distance = 0; isnonbitrunc = nonbitrunc; @@ -109,7 +107,7 @@ struct hrmap_spherical : hrmap { h.rval0 = h.rval1 = 0; h.alt = NULL; h.cdata = NULL; - h.c.clear(); + h.c.fullclear(); h.fieldval = i; if(!irr::on) h.c7 = newCell(S7, &h); } diff --git a/heptagon.cpp b/heptagon.cpp index a2a62dc7..bbc92a9f 100644 --- a/heptagon.cpp +++ b/heptagon.cpp @@ -69,14 +69,13 @@ template auto iprintf(T... t) { for(int i=0; ialt = NULL; h->s = s; - h->c.clear(); h->c.connect(pard, parent, d, false); h->cdata = NULL; return h; } heptagon *buildHeptagon(heptagon *parent, int d, hstate s, int pard = 0, int fixdistance = COMPUTE) { - heptagon *h = buildHeptagon1(new heptagon, parent, d, s, pard, fixdistance); + heptagon *h = buildHeptagon1(tailored_alloc (S7), parent, d, s, pard, fixdistance); if(binarytiling || archimedean) return h; if(parent->c7) { if(irr::on) diff --git a/hyper.h b/hyper.h index ef7970ce..f330c7a8 100644 --- a/hyper.h +++ b/hyper.h @@ -320,30 +320,43 @@ struct gcell { #define NOBARRIERS 15 #define MODFIXER 10090080 -#define MAX_EDGE 12 +#define MAX_EDGE 14 template struct walker; template struct connection_table { + + // Assumption: class T has a field c of type connection_table. + + // NOTE: since aconnection_table may be allocated with + // less than MAX_EDGE neighbors (see tailored_alloc), + // the order of fields matters. + unsigned char spintable[6]; unsigned short mirrortable; - // neighbors; move[0] always goes towards origin, and then we go clockwise T* move_table[MAX_EDGE]; + unsigned char spintable_extra[2]; + T* full() { T* x; return (T*)((char*)this - ((char*)(&(x->c)) - (char*)x)); } + unsigned char& get_spinchar(int d) { + if(d < 12) return spintable[d>>1]; + else return spintable_extra[(d-12)>>1]; + } void setspin(int d, int spin, bool mirror) { - spintable[d>>1] &= ~(15 << ((d&1) << 2)); - spintable[d>>1] |= spin << ((d&1) << 2); + unsigned char& c = get_spinchar(d); + c &= ~(15 << ((d&1) << 2)); + c |= spin << ((d&1) << 2); if(mirror) mirrortable |= (1 << d); else mirrortable &=~ (1 << d); } // we are spin(i)-th neighbor of move[i] - int spin(int d) { return (spintable[d>>1] >> ((d&1)<<2)) & 15; } + int spin(int d) { return (get_spinchar(d) >> ((d&1)<<2)) & 15; } bool mirror(int d) { return (mirrortable >> d) & 1; } int fix(int d) { return (d + MODFIXER) % full()->degree(); } T*& modmove(int i) { return move(fix(i)); } T*& move(int i) { return move_table[i]; } unsigned char modspin(int i) { return spin(fix(i)); } - void clear() { + void fullclear() { for(int i=0; i struct connection_table { } }; +// Allocate a class T with a connection_table, but +// with only `degree` connections. Also set yet +// unknown connections to NULL. + +// Generating the hyperbolic world consumes lots of +// RAM, so we really need to be careful on low memory devices. + +template T* tailored_alloc(int degree) { + const T* sample = (T*) °ree; + T* result; +#ifndef NO_TAILORED_ALLOC + if(degree <= 12) { + int b = (char*)&sample->c.move_table[degree] - (char*) sample; + result = (T*) new char[b]; + new (result) T(); + } + else +#endif + result = new T; + for(int i=0; ic.move_table[i] = NULL; + return result; + } + static const struct wstep_t { wstep_t() {} } wstep; static const struct wmirror_t { wmirror_t() {}} wmirror; static const struct rev_t { rev_t() {} } rev; @@ -415,8 +451,6 @@ template struct walker { walker mirrorat(int d) { return walker (at, at->c.fix(d+d - spin), !mirrored); } }; -inline int fix42(int a) { return (a+MODFIXER)% S42; } - struct cell; // automaton state @@ -455,6 +489,11 @@ struct heptagon { ~heptagon () { heptacount--; } heptagon *cmove(int d) { return createStep(this, d); } inline int degree(); + + // prevent accidental copying + heptagon(const heptagon&) = delete; + heptagon& operator=(const heptagon&) = delete; + // do not add any fields after connection_table (see tailored_alloc) }; struct cell : gcell { @@ -472,6 +511,12 @@ struct cell : gcell { cell*& move(int d) { return c.move(d); } cell*& modmove(int d) { return c.modmove(d); } cell* cmove(int d) { return createMov(this, d); } + cell() {} + + // prevent accidental copying + cell(const cell&) = delete; + heptagon& operator=(const cell&) = delete; + // do not add any fields after connection_table (see tailored_alloc) }; int heptagon::degree() { if(archimedean) return c7->type; else return S7; }