Commit 5c27075a authored by Adam P. Goucher's avatar Adam P. Goucher

Bitwise shifts of patterns

parent 8d6ba7fa
Pipeline #60422129 passed with stages
in 8 minutes and 3 seconds
#ifndef LIFELIB_VERSION /*
__version__=[x.replace('"', '') for x in '''
*/
#define LIFELIB_VERSION "ll2.2.12"
#define LIFELIB_VERSION "ll2.2.13"
// '''.split() if ('ll' in x)][0][2:]
#endif
......@@ -140,6 +140,11 @@ extern "C"
return new(std::nothrow) apg::pattern(lab, lab->semisolid(depth, flags), ppat->getrule());
}
void* BitshiftPattern(void* pat, int shift) {
auto ppat = reinterpret_cast<apg::pattern*>(pat);
return new(std::nothrow) apg::pattern(ppat->bitshift(shift));
}
void* ShiftPattern(void* pat, int x, int y, uint64_t exponent) {
auto ppat = reinterpret_cast<apg::pattern*>(pat);
return new(std::nothrow) apg::pattern(ppat->shift(x, y, exponent));
......
......@@ -925,6 +925,56 @@ namespace apg {
}
hypernode<I> bitshift_recurse(hypernode<I> hnode, std::map<std::pair<I, uint32_t>, I> *memmap, int shift) {
if (shift == 0) { return hnode; }
if ((shift >= N) || (shift <= -N)) { return hypernode<I>(0, hnode.depth); }
if (hnode.index2 != 0) {
return bitshift_recurse(breach(hnode), memmap, shift);
}
auto it = memmap->find(std::make_pair(hnode.index, hnode.depth));
if (hnode.index == 0) {
return hypernode<I>(0, hnode.depth);
} else if (it != memmap->end()) {
return hypernode<I>(it->second, hnode.depth);
} else if (hnode.depth == 0) {
// Extract the pointer to the node:
kiventry<nicearray<uint64_t, 4*N>, I, J >* pptr = ind2ptr_leaf(hnode.index);
nicearray<uint64_t, 4*N> outleaf = {0ull};
int lbound = (shift <= 0) ? 0 : shift;
int ubound = (shift >= 0) ? N : (N + shift);
for (int j = lbound * 4; j < ubound * 4; j++) {
outleaf.x[j] = pptr->key.x[j - 4*shift];
}
I res = make_leaf(outleaf);
memmap->emplace(std::make_pair(hnode.index, 0), res);
return hypernode<I>(res, 0);
} else {
// Extract the pointer to the node:
kiventry<nicearray<I, 4>, I, J >* pptr = ind2ptr_nonleaf(hnode.depth, hnode.index);
// Lazy evaluation:
hypernode<I> ytl = bitshift_recurse(hypernode<I>(pptr->key.x[0], hnode.depth - 1), memmap, shift);
hypernode<I> ytr = bitshift_recurse(hypernode<I>(pptr->key.x[1], hnode.depth - 1), memmap, shift);
hypernode<I> ybl = bitshift_recurse(hypernode<I>(pptr->key.x[2], hnode.depth - 1), memmap, shift);
hypernode<I> ybr = bitshift_recurse(hypernode<I>(pptr->key.x[3], hnode.depth - 1), memmap, shift);
// Assemble the transformed node:
nicearray<I, 4> cc = {ytl.index, ytr.index, ybl.index, ybr.index};
hypernode<I> xcc = make_nonleaf_hn(hnode.depth, cc);
memmap->emplace(std::make_pair(hnode.index, hnode.depth), xcc.index);
return xcc;
}
}
hypernode<I> brand_recurse(hypernode<I> hnode, std::map<std::pair<I, uint32_t>, I> *memmap, bool disjunctive) {
if (N == 1) { return hnode; }
......
......@@ -401,12 +401,18 @@ namespace apg {
}
virtual hypernode<I> brand_recurse(hypernode<I> hnode, std::map<std::pair<I, uint32_t>, I> *memmap, bool disjunctive) = 0;
virtual hypernode<I> bitshift_recurse(hypernode<I> hnode, std::map<std::pair<I, uint32_t>, I> *memmap, int shift) = 0;
hypernode<I> brand_recurse(hypernode<I> hnode) {
std::map<std::pair<I, uint32_t>, I> memmap;
return brand_recurse(hnode, &memmap, false);
}
hypernode<I> bitshift_recurse(hypernode<I> hnode, int shift) {
std::map<std::pair<I, uint32_t>, I> memmap;
return bitshift_recurse(hnode, &memmap, shift);
}
hypernode<I> bror_recurse(hypernode<I> hnode) {
std::map<std::pair<I, uint32_t>, I> memmap;
return brand_recurse(hnode, &memmap, true);
......
......@@ -359,6 +359,10 @@ namespace apg {
return basepattern<I>(lab, lab->pattern_match(hnode, hypernode<I>(0, 1), coerce(c1)), rulestring);
}
basepattern<I> bitshift(int shift) {
return basepattern<I>(lab, lab->bitshift_recurse(hnode, shift), rulestring);
}
basepattern<I> bror() {
return basepattern<I>(lab, lab->bror_recurse(hnode), rulestring);
}
......@@ -730,6 +734,10 @@ namespace apg {
// -----------------------------------------
};
template<typename I>
basepattern<I> operator<<(basepattern<I> lhs, int amount) { return lhs.bitshift(amount); }
template<typename I>
basepattern<I> operator>>(basepattern<I> lhs, int amount) { return lhs.bitshift(-amount); }
template<typename I>
basepattern<I> operator+(basepattern<I> lhs, const basepattern<I> &rhs) { return lhs.disjunction(rhs); }
template<typename I>
......
......@@ -76,7 +76,8 @@ restypes = {'DeletePattern': None, 'GetBeszelIndex': c_uint64, 'GetUlqomaIndex':
'GetSolidForPattern': c_void_p, 'GetOriginState': c_uint64, 'GetCells': None, 'SetCells': None,
'CreatePatternFromFile': c_void_p, 'MakeSpaceshipStream': c_void_p, 'GetCompiledVersion': None,
'GetCoords': None, 'GetPatternBound': c_uint64, 'GetSubpops': None, 'Hashsoup': c_void_p,
'FindConnectedComponent': c_void_p, 'GetOneCell': c_void_p, 'CopyPattern': c_void_p, 'GetWechslerOfPattern': None}
'FindConnectedComponent': c_void_p, 'GetOneCell': c_void_p, 'CopyPattern': c_void_p, 'GetWechslerOfPattern': None,
'BitshiftPattern': c_void_p}
def call_underlying(lifelib, fname_and_args):
......
......@@ -106,6 +106,11 @@ class Pattern(object):
self.lifelib('BooleanPatternMutable', self.ptr, other.ptr, op)
return self
def _bitshift(self, shift):
newptr = self.lifelib('BitshiftPattern', self.ptr, shift)
return Pattern(self.session, newptr, self.owner)
def _boolean_immutable(self, other, op):
newptr = self.lifelib('BooleanPatternImmutable', self.ptr, other.ptr, op)
......@@ -147,6 +152,12 @@ class Pattern(object):
def __mul__(self, other):
return self._boolean_immutable(other, 4)
def __lshift__(self, other):
return self._bitshift(other)
def __rshift__(self, other):
return self._bitshift(-other)
def convolve(self, other, exclusive=False):
return self._boolean_immutable(other, (6 if exclusive else 5))
......
......@@ -14,6 +14,15 @@ class TestGoL(unittest.TestCase):
self.sess = lifelib.load_rules('b3s23')
self.lt = self.sess.lifetree(memory=1000, n_layers=4)
def test_bitshift(self):
pd = self.lt.pattern('xp15_4r4z4r4')
self.assertEqual((pd << 3).wechsler, '0_0_0_4r4z4r4')
self.assertEqual((pd << 2).wechsler, '0_0_4r4z4r4')
self.assertEqual((pd << 1).wechsler, '0_4r4z4r4')
self.assertEqual(((pd << 2) >> 2), pd)
def test_ulimit(self):
self.sess.lifelib.ensure_limit(10000, 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