Commit cc6329dd authored by Adam P. Goucher's avatar Adam P. Goucher

Compatibility with numpy arrays for mass getcells/setcells

parent b6298091
......@@ -83,7 +83,7 @@ namespace apg {
return (w & 1);
}
void setcell(uint64_t x, uint64_t y, bool newval) {
void setcell(int64_t x, int64_t y, bool newval) {
int32_t u = (uint32_t) (x >> 3);
int32_t v = (uint32_t) (y >> 3);
uint64_t w = (1ull << ((x & 7) | ((y & 7) << 3)));
......@@ -398,6 +398,24 @@ namespace apg {
};
std::vector<bitworld> cells2vec(uint64_t n, int64_t* coords, uint64_t* states) {
std::vector<bitworld> planes;
for (uint64_t i = 0; i < n; i++) {
uint64_t bp = 0;
uint64_t colour = (states == 0) ? 1 : states[i];
while (colour > 0) {
if (colour & 1) {
if (bp >= planes.size()) { planes.resize(bp+1); }
planes[bp].setcell(coords[2*i], coords[2*i+1], 1);
}
bp += 1; colour = colour >> 1;
}
}
return planes;
}
std::vector<bitworld> rle2vec(std::string rle) {
std::vector<bitworld> planes;
uint64_t x = 0; uint64_t y = 0; uint64_t count = 0;
......
......@@ -199,6 +199,22 @@ extern "C"
s.copy(buffer, 2048);
}
void GetCells(void* pat, int ncells, int64_t* coords, uint64_t* states) {
auto ppat = reinterpret_cast<apg::pattern*>(pat);
for (int i = 0; i < ncells; i++) {
states[i] = ppat->getcell(coords[2*i], coords[2*i+1]);
}
}
void SetCells(void* pat, int ncells, int64_t* coords, uint64_t* states) {
auto ppat = reinterpret_cast<apg::pattern*>(pat);
auto lab = ppat->getlab();
auto newnode = lab->bror_recurse(lab->fromcells(ncells, coords, 0));
ppat->changehnode(lab->boolean_universe(ppat->gethnode(), newnode, 3));
auto newnode2 = lab->fromcells(ncells, coords, states);
ppat->changehnode(lab->boolean_universe(ppat->gethnode(), newnode2, 1));
}
int64_t GetDXOfPattern(void* pat) {
auto ppat = reinterpret_cast<apg::pattern*>(pat);
return ppat->dx;
......
......@@ -761,12 +761,12 @@ namespace apg {
}
}
hypernode<I> brand_recurse(hypernode<I> hnode, std::map<std::pair<I, uint32_t>, I> *memmap) {
hypernode<I> brand_recurse(hypernode<I> hnode, std::map<std::pair<I, uint32_t>, I> *memmap, bool disjunctive) {
if (N == 1) { return hnode; }
if (hnode.index2 != 0) {
return brand_recurse(breach(hnode), memmap);
return brand_recurse(breach(hnode), memmap, disjunctive);
}
auto it = memmap->find(std::make_pair(hnode.index, hnode.depth));
......@@ -782,7 +782,13 @@ namespace apg {
for (int j = 0; j < 4; j++) {
uint64_t l = pptr->key.x[j];
for (int i = 1; i < N; i++) { l &= pptr->key.x[4*i+j]; }
for (int i = 1; i < N; i++) {
if (disjunctive) {
l |= pptr->key.x[4*i+j];
} else {
l &= pptr->key.x[4*i+j];
}
}
for (int i = 0; i < N; i++) { outleaf.x[4*i+j] = l; }
}
......@@ -794,10 +800,10 @@ namespace apg {
kiventry<nicearray<I, 4>, I, J >* pptr = ind2ptr_nonleaf(hnode.depth, hnode.index);
// Lazy evaluation:
hypernode<I> ytl = brand_recurse(hypernode<I>(pptr->key.x[0], hnode.depth - 1), memmap);
hypernode<I> ytr = brand_recurse(hypernode<I>(pptr->key.x[1], hnode.depth - 1), memmap);
hypernode<I> ybl = brand_recurse(hypernode<I>(pptr->key.x[2], hnode.depth - 1), memmap);
hypernode<I> ybr = brand_recurse(hypernode<I>(pptr->key.x[3], hnode.depth - 1), memmap);
hypernode<I> ytl = brand_recurse(hypernode<I>(pptr->key.x[0], hnode.depth - 1), memmap, disjunctive);
hypernode<I> ytr = brand_recurse(hypernode<I>(pptr->key.x[1], hnode.depth - 1), memmap, disjunctive);
hypernode<I> ybl = brand_recurse(hypernode<I>(pptr->key.x[2], hnode.depth - 1), memmap, disjunctive);
hypernode<I> ybr = brand_recurse(hypernode<I>(pptr->key.x[3], hnode.depth - 1), memmap, disjunctive);
// Assemble the transformed node:
nicearray<I, 4> cc = {ytl.index, ytr.index, ybl.index, ybr.index};
......
......@@ -247,6 +247,10 @@ namespace apg {
return hnode;
}
hypernode<I> fromcells(uint64_t n, int64_t *coords, uint64_t *states) {
return fromplanes(cells2vec(n, coords, states));
}
hypernode<I> fromrle(std::string s) {
if (s != "") {
return fromplanes(rle2vec(s));
......@@ -377,11 +381,16 @@ namespace apg {
return copy_recurse(hnode, lab, &memmap);
}
virtual hypernode<I> brand_recurse(hypernode<I> hnode, std::map<std::pair<I, uint32_t>, I> *memmap) = 0;
virtual hypernode<I> brand_recurse(hypernode<I> hnode, std::map<std::pair<I, uint32_t>, I> *memmap, bool disjunctive) = 0;
hypernode<I> brand_recurse(hypernode<I> hnode) {
std::map<std::pair<I, uint32_t>, I> memmap;
return brand_recurse(hnode, &memmap);
return brand_recurse(hnode, &memmap, false);
}
hypernode<I> bror_recurse(hypernode<I> hnode) {
std::map<std::pair<I, uint32_t>, I> memmap;
return brand_recurse(hnode, &memmap, true);
}
virtual hypernode<I> transform_recurse(hypernode<I> hnode, uint8_t perm, std::map<std::pair<I, uint32_t>, I> *memmap) = 0;
......
......@@ -227,7 +227,7 @@ namespace apg {
}
uint64_t getcell(int64_t x, int64_t y) {
uint64_t c = lab->getcell_recurse(hnode, x + (8ull << hnode.depth), y + (8ull << hnode.depth));
uint64_t c = lab->getcell_recurse(hnode, ((uint64_t) x) + (8ull << hnode.depth), ((uint64_t) y) + (8ull << hnode.depth));
return c;
}
......
......@@ -70,7 +70,7 @@ restypes = {'DeletePattern': None, 'GetBeszelIndex': c_uint64, 'GetUlqomaIndex':
'GetPopulationOfPattern': None, 'CreateLifetree': c_void_p, 'CreatePatternFromRLE': c_void_p,
'CreateRectangle': c_void_p, 'DeleteLifetree': None, 'GetPatternBox': None, 'PatternEquality': c_bool,
'PatternNonempty': c_bool, 'MatchLive': c_void_p, 'MatchLiveAndDead': c_void_p, 'GetRuleOfPattern': None,
'GetSolidForPattern': c_void_p, 'GetOriginState': c_uint64}
'GetSolidForPattern': c_void_p, 'GetOriginState': c_uint64, 'GetCells': None, 'SetCells': None}
def call_underlying(lifelib, fname_and_args):
......
......@@ -391,11 +391,30 @@ class Pattern(object):
subrect = subrect & bigenough._semisolid(3).shift(0, bottom)
return subrect
elif hasattr(x, 'ctypes'):
import numpy as np
x = np.ascontiguousarray(x, dtype=np.int64)
n = len(x)
y = np.zeros((n,), dtype=np.uint64, order='C')
cx = x.ctypes
cy = y.ctypes
self.lifelib('GetCells', self.ptr, n, (cx.data,), (cy.data,))
return y
else:
raise TypeError("operator[] accepts either a generation (int) or a pair of slices")
def __setitem__(self, x, item):
if hasattr(x, 'ctypes'):
import numpy as np
x = np.ascontiguousarray(x, dtype=np.int64)
n = len(x)
y = np.ascontiguousarray(item, dtype=np.uint64)
cx = x.ctypes
cy = y.ctypes
self.lifelib('SetCells', self.ptr, n, (cx.data,), (cy.data,))
return
x = tuple([(slice(y, y + 1) if isinstance(y, Integral) else y) for y in x])
self -= self[x]
......
......@@ -46,6 +46,22 @@ bbbbooobobobbboo!''', 'g3b3s23')
self.assertEqual(p54soup[30, 7], 2)
self.assertEqual(p54soup.population, x + 1)
try:
import numpy as np
except ImportError:
return
coords = np.array([[0, 1], [2, 3], [4, 5]], dtype=np.int64)
values = np.array([1, 0, 2], dtype=np.int64)
p54soup[coords] = values
values2 = p54soup[coords]
print(values)
print(values2)
self.assertEqual(np.all(values == values2), True)
def test_largerthanlife(self):
lt = self.sess.lifetree(memory=1000, n_layers=1)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment