From e96727c2cc8d091bfa0a3bea4008353f42bcebc1 Mon Sep 17 00:00:00 2001 From: ceebo Date: Tue, 16 Dec 2014 16:58:11 +0000 Subject: [PATCH 1/5] Fix issues reported by g++ -Wall (in particular (x & 1 == 0) <> (x % 2 == 0) due to C precedence rules) --- LifeAPI.h | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/LifeAPI.h b/LifeAPI.h index 5723ddf..6f6539d 100644 --- a/LifeAPI.h +++ b/LifeAPI.h @@ -362,7 +362,7 @@ void IterateState(LifeState *lifstate) uint64_t x0, r0, xU, aU, xB, aB; uint64_t a0,a1,a2,c, b0, b1, b2; - int i, j, idxU, idxB, minNot0, maxNot0; + int i, idxU, idxB; for(i = min; i <= max; i++) { @@ -419,9 +419,6 @@ void IterateState(LifeState *lifstate) if(e == N - 2) e = N - 1; - int newmin = s; - int newmax = e; - for(i = s; i <= e; i++) { state[i] = tempState[i]; @@ -454,11 +451,7 @@ void CirculateUp(uint64_t *state, int anyk) void Move(LifeState* state, int x, int y) { - int i, j; - - uint64_t temp[N]; - - for(i = 0; i < N; i++) + for(int i = 0; i < N; i++) { if(y < 0) state->state[i] = CirculateRight(state->state[i], -y); @@ -1162,9 +1155,7 @@ int Validate(LifeIterator *iter1, LifeIterator *iter2) if(iter1->curx != iter2->curx) { - //Those two lines are the same - //if((iter1->curx + iter2->curx) % 2 == 0) - if((iter1->curx + iter2->curx) & 1 == 0) + if((iter1->curx + iter2->curx) % 2 == 0) { if(iter1->curx > iter2->curx) return SUCCESS; @@ -1182,7 +1173,7 @@ int Validate(LifeIterator *iter1, LifeIterator *iter2) if(iter1->cury != iter2->cury) { - if((iter1->cury + iter2->cury) & 1 == 0) + if((iter1->cury + iter2->cury) % 2 == 0) { if(iter1->cury > iter2->cury) return SUCCESS; @@ -1198,7 +1189,7 @@ int Validate(LifeIterator *iter1, LifeIterator *iter2) } } - if((iter1->curs + iter2->curs) & 1 == 0) + if((iter1->curs + iter2->curs) % 2 == 0) { if(iter1->curs > iter2->curs) return SUCCESS; @@ -1382,4 +1373,4 @@ void Add(ResultManager* manager) void Save(ResultManager* manager, const char* fileName) { -} \ No newline at end of file +} From 4f49b606ff305ad364bd26dd6b76537b19dd2d9d Mon Sep 17 00:00:00 2001 From: ceebo Date: Tue, 16 Dec 2014 17:02:23 +0000 Subject: [PATCH 2/5] Use stringstream to construct RLE And use LifeState *state consistently Also make the two operand Parse function the base implementation. Four operand Parse is now derived from it. --- LifeAPI.h | 141 +++++++++++++++++++++--------------------------------- 1 file changed, 54 insertions(+), 87 deletions(-) diff --git a/LifeAPI.h b/LifeAPI.h index 6f6539d..64105b3 100644 --- a/LifeAPI.h +++ b/LifeAPI.h @@ -6,6 +6,8 @@ #include #include #include +#include + #define N 64 #define CAPTURE_COUNT 10 #define MAX_ITERATIONS 200 @@ -529,7 +531,7 @@ void Transform(LifeState* state, int dx, int dy) Move(state, dx, dy); } -int Parse(LifeState* lifeState, const char* rle, int dx, int dy) +int Parse(LifeState* state, const char* rle) { char ch; int cnt, i, j; @@ -539,7 +541,7 @@ int Parse(LifeState* lifeState, const char* rle, int dx, int dy) cnt = 0; for(j = 0; j < N; j++) - lifeState->state[j] = 0; + state->state[j] = 0; i = 0; @@ -559,7 +561,7 @@ int Parse(LifeState* lifeState, const char* rle, int dx, int dy) for(j = 0; j < cnt; j++) { - SetCell(lifeState, x, y, 1); + SetCell(state, x, y, 1); x++; } @@ -595,25 +597,28 @@ int Parse(LifeState* lifeState, const char* rle, int dx, int dy) i++; } - lifeState->min = 0; - lifeState->max = N - 1; - - Move(lifeState, dx, dy); + state->min = 0; + state->max = N - 1; return SUCCESS; } -int Parse(LifeState* lifeState, const char* rle) +int Parse(LifeState* state, const char* rle, int dx, int dy) { - return Parse(lifeState, rle, 0, 0); + int result = Parse(state, rle); + + if (result == SUCCESS) + Move(state, dx, dy); + + return result; } -int Parse(LifeState* lifeState, const char* rle, int dx, int dy, int dxx, int dxy, int dyx, int dyy) +int Parse(LifeState* state, const char* rle, int dx, int dy, int dxx, int dxy, int dyx, int dyy) { - int result = Parse(lifeState, rle); + int result = Parse(state, rle); if(result == SUCCESS) - Transform(lifeState, dx, dy, dxx, dxy, dyx, dyy); + Transform(state, dx, dy, dxx, dxy, dyx, dyy); return result; } @@ -641,131 +646,93 @@ LifeState* NewState(const char* rle) return NewState(rle, 0, 0); } -char* Join(char* first, char* second) -{ - char * s = (char *)malloc(snprintf(NULL, 0, "%s%s", first, second) + 1); - sprintf(s, "%s%s", first, second); - return s; -} - -char* GetRLE(LifeState * lifeState) +const std::string GetRLE(LifeState *state) { - uint64_t * state = lifeState->state; - char* result = ""; - + std::ostringstream ss; int i, j; - int currowVal,currowCount, numempty, isempty; - - numempty = 0; - isempty = 1; - char str[15]; - + int val, count, numempty = 0; for(j = 0; j < N; j++) { - currowCount = 1; - currowVal = Get(0,j, state); + count = 1; + val = Get(0, j, state->state); for(i = 1; i < 64; i++) { - if(currowVal == 1) + if(val == 1) { - isempty = 0; - if(numempty > 0) { if(numempty > 1) - { - sprintf(str, "%d$", numempty); - result = Join(result, str); - } - else - { - result = Join(result, "$"); - } + ss << numempty; + + ss << "$"; numempty = 0; } } - if(Get(i,j, state) != currowVal) + if(Get(i, j, state->state) != val) { - isempty = 0; - if(numempty > 0) { if(numempty > 1) - { - sprintf(str, "%d$", numempty); - result = Join(result, str); - } - else - result = Join(result, "$"); + ss << numempty; + + ss << "$"; numempty = 0; } - if(currowVal == 0) + if(val == 0) { - if(currowCount == 1) - result = Join(result, "b"); - else - { - sprintf(str, "%db", currowCount); - result = Join(result, str); - } + if(count > 1) + ss << count; + + ss << "b"; } else { - if(currowCount == 1) - result = Join(result, "o"); - else - { - sprintf(str, "%do", currowCount); - result = Join(result,str); - } + if(count > 1) + ss << count; + + ss << "o"; } - currowCount = 1; - currowVal = Get(i,j, state); + count = 1; + val = Get(i, j, state->state); } else { - currowCount++; + count++; } } - if(currowVal == 1) + if(val == 1) { - if(currowCount > 1) - { - sprintf(str, "%do", currowCount); - result = Join(result,str); - } - else - result = Join(result, "o$"); + if(count > 1) + ss << count; + + ss << "o"; } else { numempty++; - } - - isempty = 1; - + } } - - return result; + + ss << "!"; + + return ss.str(); } -void PrintRLE(LifeState * lifeState) +void PrintRLE(LifeState *state) { - char * prefix ="x = 0, y = 0, rule = B3/S23\n"; - printf(Join(prefix, GetRLE(lifeState))); - printf ("!\n\n"); + printf("x = 0, y = 0, rule = B3/S23\n%s\n\n", GetRLE(state).c_str()); } void Print() From b10845d62bd575c264878209374c82efa8c8748c Mon Sep 17 00:00:00 2001 From: ceebo Date: Tue, 16 Dec 2014 17:05:11 +0000 Subject: [PATCH 3/5] Add overload for Evolve with destination --- LifeAPI.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/LifeAPI.h b/LifeAPI.h index 64105b3..6edbd99 100644 --- a/LifeAPI.h +++ b/LifeAPI.h @@ -757,11 +757,16 @@ void PrintRLE(int idx) void Evolve(LifeState* state, int numIters) { - int i; - for(i = 0; i < numIters; i++) + for(int i = 0; i < numIters; i++) IterateState(state); } +void Evolve(LifeState* after, LifeState* before, int numIters) +{ + Copy(after, before); + Evolve(after, numIters); +} + void New() { if(GlobalState == NULL) From 86b00736630245611235f2d57f7a409145039ef1 Mon Sep 17 00:00:00 2001 From: ceebo Date: Tue, 16 Dec 2014 17:07:05 +0000 Subject: [PATCH 4/5] Add function RandomState PRNG courtesy of Stebastian Vigna at http://xorshift.di.unimi.it --- LifeAPI.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/LifeAPI.h b/LifeAPI.h index 6edbd99..2addfb9 100644 --- a/LifeAPI.h +++ b/LifeAPI.h @@ -767,6 +767,38 @@ void Evolve(LifeState* after, LifeState* before, int numIters) Evolve(after, numIters); } +namespace PRNG { + + //Public domain PRNG by Sebastian Vigna 2014, see http://xorshift.di.unimi.it + + uint64_t s[16] = { 0x12345678 }; + int p = 0; + + uint64_t rand64() { + uint64_t s0 = s[ p ]; + uint64_t s1 = s[ p = ( p + 1 ) & 15 ]; + s1 ^= s1 << 31; // a + s1 ^= s1 >> 11; // b + s0 ^= s0 >> 30; // c + return ( s[ p ] = s0 ^ s1 ) * 1181783497276652981LL; + } + +} + +void RandomState(LifeState* state) { + + for (int i = 0; i < N; i++) + state->state[i] = PRNG::rand64(); + + RecalculateMinMax(state); +} + +void RandomState() { + + RandomState(GlobalState); + +} + void New() { if(GlobalState == NULL) From ce0e7d421f032ddc1d3cfb2af5e449446f7453fd Mon Sep 17 00:00:00 2001 From: ceebo Date: Tue, 16 Dec 2014 19:25:53 +0000 Subject: [PATCH 5/5] Fix bug in GetRLE and simplify Previously no $ was printed if line ends in a live cell. Easy fix was to take numempty++ out of the "else" block but I rewrote as well. Also, GetCell should not have "val" as argument --- LifeAPI.h | 109 +++++++++++++++++++++--------------------------------- 1 file changed, 42 insertions(+), 67 deletions(-) diff --git a/LifeAPI.h b/LifeAPI.h index 2addfb9..78c6b02 100644 --- a/LifeAPI.h +++ b/LifeAPI.h @@ -92,7 +92,7 @@ int GetCell(LifeState* state, int x, int y) return Get((x + 32) % 64, (y + 32) % 64, state->state); } -int GetCell(int x, int y, int val) +int GetCell(int x, int y) { return GetCell(GlobalState, x, y); } @@ -648,83 +648,58 @@ LifeState* NewState(const char* rle) const std::string GetRLE(LifeState *state) { - std::ostringstream ss; + std::ostringstream ss; - int i, j; - - int val, count, numempty = 0; + int eol_count = 0; - for(j = 0; j < N; j++) + for(int j = 0; j < N; j++) { - count = 1; - val = Get(0, j, state->state); + int last_val = -1; + int run_count = 0; - for(i = 1; i < 64; i++) + for(int i = 0; i < N; i++) { - if(val == 1) + int val = Get(i, j, state->state); + + // Flush linefeeds if we find a live cell + if(val == 1 && eol_count > 0) { - if(numempty > 0) - { - if(numempty > 1) - ss << numempty; - - ss << "$"; - - numempty = 0; - } + if(eol_count > 1) + ss << eol_count; + + ss << "$"; + + eol_count = 0; } - - if(Get(i, j, state->state) != val) - { - if(numempty > 0) - { - if(numempty > 1) - ss << numempty; - - ss << "$"; - - numempty = 0; - } - - if(val == 0) - { - if(count > 1) - ss << count; - ss << "b"; - } - else - { - if(count > 1) - ss << count; + // Flush current run if val changes + if (val == 1 - last_val) + { + if(run_count > 1) + ss << run_count; - ss << "o"; - } - - count = 1; - val = Get(i, j, state->state); - - } - else - { - count++; + ss << (last_val ? "o" : "b"); + + run_count = 0; } - - } - - if(val == 1) - { - if(count > 1) - ss << count; - - ss << "o"; - } - else - { - numempty++; - } - } + run_count++; + last_val = val; + } + + // Flush run of live cells at end of line + if (last_val == 1) + { + if(run_count > 1) + ss << run_count; + + ss << "o"; + run_count = 0; + } + + eol_count++; + } + ss << "!"; return ss.str();