From c6043c6eaf0c12af2fd1c5c0d4c5dd8da61b66b2 Mon Sep 17 00:00:00 2001 From: overflowerror Date: Sat, 13 Jan 2024 23:37:01 +0100 Subject: [PATCH] initial commit adding benchmarks --- .idea/.gitignore | 8 + benchmarkTuringFP.cpp | 212 +++++++++++++++++++++++++ benchmarkTuringOOP.cpp | 284 +++++++++++++++++++++++++++++++++ benchmarkTuringSP.cpp | 205 ++++++++++++++++++++++++ benchmarkTuringSPnoTuples.cpp | 290 ++++++++++++++++++++++++++++++++++ runAll.sh | 20 +++ 6 files changed, 1019 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 benchmarkTuringFP.cpp create mode 100644 benchmarkTuringOOP.cpp create mode 100644 benchmarkTuringSP.cpp create mode 100644 benchmarkTuringSPnoTuples.cpp create mode 100755 runAll.sh diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/benchmarkTuringFP.cpp b/benchmarkTuringFP.cpp new file mode 100644 index 0000000..8919a51 --- /dev/null +++ b/benchmarkTuringFP.cpp @@ -0,0 +1,212 @@ +#include +#include +#include +#include + +using namespace std; +using namespace std::chrono; + +#define CASES (100000) +#define MAX_VALUE (0xffff) + +#define MAX_BAND_SIZE (MAX_VALUE + 1) + +#define SEED (1337) + +int inputs[CASES]; +bool results[CASES]; + +bool isBinaryPalindrome(int input) { + int numberOfDigits = input == 0 ? 1 : static_cast(floor(log2(input)) + 1); + + for (int i = 0; i < numberOfDigits / 2; i++) { + if (((input & (1 << i)) ? 1 : 0) != ((input & (1 << (numberOfDigits - i - 1))) ? 1 : 0)) { + return false; + } + } + + return true; +} + +void resetTestData() { + srand(SEED); + + for (int i = 0; i < CASES; i++) { + inputs[i] = rand() % (MAX_VALUE + 1); + results[i] = isBinaryPalindrome(inputs[i]); + } +} + +enum Direction { + LEFT, RIGHT +}; + +enum Symbol { + UNDEFINED, TRUE, FALSE +}; + +#define returnBand(x) { function _f = x; return _f; } + +auto emptyBand() { + return [](int _) { return UNDEFINED; }; +} + +auto setOnBand(int pos, Symbol symbol, const function& band) { + return [=](int i) { + if (i == pos) { + return symbol; + } else { + return band(i); + } + }; +} + +auto inputBitToBand(int input, int bit, int length) { + if (bit == length) { + returnBand(emptyBand()); + } + + returnBand(setOnBand( + bit, + (input & (1 << (length - bit - 1))) ? TRUE : FALSE, + inputBitToBand(input, bit + 1, length) + )); +} + +auto inputToBand(int input) { + if (input == 0) { + returnBand(emptyBand()); + } + + int numberOfDigits = static_cast(floor(log2(input)) + 1); + returnBand(inputBitToBand(input, 0, numberOfDigits)); +} + +auto transitionTable(int state, Symbol symbolRead) { + switch (state) { + case 0: // init; look for first symbol + switch (symbolRead) { + case UNDEFINED: return make_tuple(200, RIGHT, UNDEFINED); + case TRUE: return make_tuple(10, RIGHT, UNDEFINED); + case FALSE: return make_tuple(20, RIGHT, UNDEFINED); + } + case 10: // look for right hand side - we need TRUE + switch (symbolRead) { + case UNDEFINED: return make_tuple(11, LEFT, UNDEFINED); + case TRUE: return make_tuple(10, RIGHT, TRUE); + case FALSE: return make_tuple(10, RIGHT, FALSE); + } + case 11: // right hand side - this should be TRUE + switch (symbolRead) { + case UNDEFINED: return make_tuple(200, LEFT, UNDEFINED); + case TRUE: return make_tuple(12, LEFT, UNDEFINED); + case FALSE: return make_tuple(100, LEFT, UNDEFINED); + } + case 12: // right hand side - new decision + switch (symbolRead) { + case UNDEFINED: return make_tuple(200, RIGHT, UNDEFINED); + case TRUE: return make_tuple(13, LEFT, UNDEFINED); + case FALSE: return make_tuple(23, LEFT, UNDEFINED); + } + case 13: // look for left hand side - we need TRUE + switch (symbolRead) { + case UNDEFINED: return make_tuple(14, RIGHT, UNDEFINED); + case TRUE: return make_tuple(13, LEFT, TRUE); + case FALSE: return make_tuple(13, LEFT, FALSE); + } + case 14: // left hand side - should be TRUE + switch (symbolRead) { + case UNDEFINED: return make_tuple(200, RIGHT, UNDEFINED); + case TRUE: return make_tuple(0, RIGHT, UNDEFINED); + case FALSE: return make_tuple(100, RIGHT, UNDEFINED); + } + + case 20: // look for right hand side - we need FALSE + switch (symbolRead) { + case UNDEFINED: return make_tuple(21, LEFT, UNDEFINED); + case TRUE: return make_tuple(20, RIGHT, TRUE); + case FALSE: return make_tuple(20, RIGHT, FALSE); + } + case 21: // right hand side - this should be FALSE + switch (symbolRead) { + case UNDEFINED: return make_tuple(200, LEFT, UNDEFINED); + case TRUE: return make_tuple(100, LEFT, UNDEFINED); + case FALSE: return make_tuple(22, LEFT, UNDEFINED); + } + case 22: // right hand side - new decision + switch (symbolRead) { + case UNDEFINED: return make_tuple(200, RIGHT, UNDEFINED); + case TRUE: return make_tuple(13, LEFT, UNDEFINED); + case FALSE: return make_tuple(23, LEFT, UNDEFINED); + } + case 23: // look for left hand side - we need FALSE + switch (symbolRead) { + case UNDEFINED: return make_tuple(24, RIGHT, UNDEFINED); + case TRUE: return make_tuple(23, LEFT, TRUE); + case FALSE: return make_tuple(23, LEFT, FALSE); + } + case 24: // left hand side - should be FALSE + switch (symbolRead) { + case UNDEFINED: return make_tuple(200, RIGHT, UNDEFINED); + case TRUE: return make_tuple(100, RIGHT, UNDEFINED); + case FALSE: return make_tuple(0, RIGHT, UNDEFINED); + } + default: + return make_tuple(100, RIGHT, UNDEFINED); + } +} + +bool reject(int state) { + return state == 100; +} + +bool accept(int state) { + return state == 200; +} + +int getNextPosition(int position, Direction direction) { + if (direction == LEFT) { + return position - 1; + } else { + return position + 1; + } +} + +bool runMachine(function band, int position, int state) { + auto transition = transitionTable(state, band(position)); + int nextState = get<0>(transition); + Direction direction = get<1>(transition); + Symbol write = get<2>(transition); + int nextPosition = getNextPosition(position, direction); + + if (reject(nextState)) { + return false; + } + if (accept(nextState)) { + return true; + } + + return runMachine(setOnBand(position, write, band), nextPosition, nextState); +} + +bool test(int input) { + auto band = inputToBand(input); + + return runMachine(band, 0, 0); +} + +int main() { + resetTestData(); + + auto t1 = high_resolution_clock::now(); + for (int i = 0; i < CASES; i++) { + if (test(inputs[i]) != results[i]) { + cout << i << ": " << inputs[i] << ", " << results[i] << " -> "<< "FAIL" << endl; + } + } + auto t2 = high_resolution_clock::now(); + + duration ms = t2 - t1; + cout << ms.count() << " ms, " << (ms.count() / CASES) << " ms/case" << endl; + +} \ No newline at end of file diff --git a/benchmarkTuringOOP.cpp b/benchmarkTuringOOP.cpp new file mode 100644 index 0000000..cc05913 --- /dev/null +++ b/benchmarkTuringOOP.cpp @@ -0,0 +1,284 @@ +#include +#include +#include +#include + +using namespace std; +using namespace std::chrono; + +#define CASES (100000) +#define MAX_VALUE (0xffff) + +#define MAX_BAND_SIZE (MAX_VALUE + 1) + +#define SEED (1337) + +int inputs[CASES]; +bool results[CASES]; + +bool isBinaryPalindrome(int input) { + int numberOfDigits = input == 0 ? 1 : static_cast(floor(log2(input)) + 1); + + for (int i = 0; i < numberOfDigits / 2; i++) { + if (((input & (1 << i)) ? 1 : 0) != ((input & (1 << (numberOfDigits - i - 1))) ? 1 : 0)) { + return false; + } + } + + return true; +} + +void resetTestData() { + srand(SEED); + + for (int i = 0; i < CASES; i++) { + inputs[i] = rand() % (MAX_VALUE + 1); + results[i] = isBinaryPalindrome(inputs[i]); + } +} + +enum Direction { + LEFT, RIGHT +}; + +enum Symbol { + UNDEFINED, TRUE, FALSE +}; + +class Transition { +public: + int state; + Direction direction; + Symbol symbolToWrite; + + Transition(int state, Direction direction, Symbol symbolToWrite) { + this->state = state; + this->direction = direction; + this->symbolToWrite = symbolToWrite; + } +}; + +class StateMachine { +protected: + int state; + + virtual int getInitialState() = 0; + virtual Transition getNext(int state, Symbol symbolRead) = 0; + virtual bool reject(int state) = 0; + virtual bool accept(int state) = 0; + +public: + void reset() { + state = getInitialState(); + } + + Transition getNext(Symbol symbolRead) { + auto transition = getNext(state, symbolRead); + state = transition.state; + + return transition; + } + + bool reject() { + return reject(state); + } + + bool accept() { + return accept(state); + } +}; + +class PalindromeRecognizer : public StateMachine { + int getInitialState() { + return 0; + } + + Transition getNext(int state, Symbol symbolRead) { + //cout << state << " " << (symbolRead == UNDEFINED) << " " << (symbolRead == TRUE) << endl; + + switch (state) { + case 0: // init; look for first symbol + switch (symbolRead) { + case UNDEFINED: return Transition(200, RIGHT, UNDEFINED); + case TRUE: return Transition(10, RIGHT, UNDEFINED); + case FALSE: return Transition(20, RIGHT, UNDEFINED); + } + case 10: // look for right hand side - we need TRUE + switch (symbolRead) { + case UNDEFINED: return Transition(11, LEFT, UNDEFINED); + case TRUE: return Transition(10, RIGHT, TRUE); + case FALSE: return Transition(10, RIGHT, FALSE); + } + case 11: // right hand side - this should be TRUE + switch (symbolRead) { + case UNDEFINED: return Transition(200, LEFT, UNDEFINED); + case TRUE: return Transition(12, LEFT, UNDEFINED); + case FALSE: return Transition(100, LEFT, UNDEFINED); + } + case 12: // right hand side - new decision + switch (symbolRead) { + case UNDEFINED: return Transition(200, RIGHT, UNDEFINED); + case TRUE: return Transition(13, LEFT, UNDEFINED); + case FALSE: return Transition(23, LEFT, UNDEFINED); + } + case 13: // look for left hand side - we need TRUE + switch (symbolRead) { + case UNDEFINED: return Transition(14, RIGHT, UNDEFINED); + case TRUE: return Transition(13, LEFT, TRUE); + case FALSE: return Transition(13, LEFT, FALSE); + } + case 14: // left hand side - should be TRUE + switch (symbolRead) { + case UNDEFINED: return Transition(200, RIGHT, UNDEFINED); + case TRUE: return Transition(0, RIGHT, UNDEFINED); + case FALSE: return Transition(100, RIGHT, UNDEFINED); + } + + case 20: // look for right hand side - we need FALSE + switch (symbolRead) { + case UNDEFINED: return Transition(21, LEFT, UNDEFINED); + case TRUE: return Transition(20, RIGHT, TRUE); + case FALSE: return Transition(20, RIGHT, FALSE); + } + case 21: // right hand side - this should be FALSE + switch (symbolRead) { + case UNDEFINED: return Transition(200, LEFT, UNDEFINED); + case TRUE: return Transition(100, LEFT, UNDEFINED); + case FALSE: return Transition(22, LEFT, UNDEFINED); + } + case 22: // right hand side - new decision + switch (symbolRead) { + case UNDEFINED: return Transition(200, RIGHT, UNDEFINED); + case TRUE: return Transition(13, LEFT, UNDEFINED); + case FALSE: return Transition(23, LEFT, UNDEFINED); + } + case 23: // look for left hand side - we need FALSE + switch (symbolRead) { + case UNDEFINED: return Transition(24, RIGHT, UNDEFINED); + case TRUE: return Transition(23, LEFT, TRUE); + case FALSE: return Transition(23, LEFT, FALSE); + } + case 24: // left hand side - should be FALSE + switch (symbolRead) { + case UNDEFINED: return Transition(200, RIGHT, UNDEFINED); + case TRUE: return Transition(100, RIGHT, UNDEFINED); + case FALSE: return Transition(0, RIGHT, UNDEFINED); + } + default: + return Transition(100, RIGHT, UNDEFINED); + } + } + + bool reject(int state) { + return state == 100; + } + + bool accept(int state) { + return state == 200; + } +}; + +class Band { +private: + Symbol fields[MAX_BAND_SIZE]; + int position; + + void set(Symbol symbol) { + if (position < 0 || position >= MAX_BAND_SIZE) { + return; + } else { + fields[position] = symbol; + } + } + + void move(Direction direction) { + switch (direction) { + case LEFT: + position--; + break; + case RIGHT: + position++; + break; + } + } + +public: + Band(int input) { + int numberOfDigits = input == 0 ? 1 : static_cast(floor(log2(input)) + 1); + + for (int i = 0; i < numberOfDigits; i++) { + fields[i] = (input & (1 << (numberOfDigits - i - 1))) ? TRUE : FALSE; + } + for (int i = numberOfDigits; i < MAX_BAND_SIZE; i++) { + fields[i] = UNDEFINED; + } + + this->position = 0; + } + + Symbol get() { + //cout << position << " "; + if (position < 0 || position >= MAX_BAND_SIZE) { + return UNDEFINED; + } else { + return fields[position]; + } + } + + void apply(Transition transition) { + set(transition.symbolToWrite); + move(transition.direction); + } +}; + +class TuringMachine { +private: + Band* band; + StateMachine* stateMachine; + +public: + TuringMachine(StateMachine* stateMachine, Band* band) { + this->stateMachine = stateMachine; + this->stateMachine->reset(); + this->band = band; + } + + bool run() { + while (true) { + if (stateMachine->reject()) { + return false; + } + if (stateMachine->accept()) { + return true; + } + + band->apply( + stateMachine->getNext(band->get()) + ); + } + } +}; + +bool test(int input) { + Band band(input); + PalindromeRecognizer program; + + TuringMachine machine(&program, &band); + return machine.run(); +} + +int main() { + resetTestData(); + + auto t1 = high_resolution_clock::now(); + for (int i = 0; i < CASES; i++) { + if (test(inputs[i]) != results[i]) { + cout << i << ": " << inputs[i] << ", " << results[i] << " -> "<< "FAIL" << endl; + } + } + auto t2 = high_resolution_clock::now(); + + duration ms = t2 - t1; + cout << ms.count() << " ms, " << (ms.count() / CASES) << " ms/case" << endl; + +} \ No newline at end of file diff --git a/benchmarkTuringSP.cpp b/benchmarkTuringSP.cpp new file mode 100644 index 0000000..330a7b2 --- /dev/null +++ b/benchmarkTuringSP.cpp @@ -0,0 +1,205 @@ +#include +#include +#include +#include + +using namespace std; +using namespace std::chrono; + +#define CASES (100000) +#define MAX_VALUE (0xffff) + +#define MAX_BAND_SIZE (MAX_VALUE + 1) + +#define SEED (1337) + +int inputs[CASES]; +bool results[CASES]; + +bool isBinaryPalindrome(int input) { + int numberOfDigits = input == 0 ? 1 : static_cast(floor(log2(input)) + 1); + + for (int i = 0; i < numberOfDigits / 2; i++) { + if (((input & (1 << i)) ? 1 : 0) != ((input & (1 << (numberOfDigits - i - 1))) ? 1 : 0)) { + return false; + } + } + + return true; +} + +void resetTestData() { + srand(SEED); + + for (int i = 0; i < CASES; i++) { + inputs[i] = rand() % (MAX_VALUE + 1); + results[i] = isBinaryPalindrome(inputs[i]); + } +} + +enum Direction { + LEFT, RIGHT +}; + +enum Symbol { + UNDEFINED, TRUE, FALSE +}; + +auto transitionTable(int state, Symbol symbolRead) { + switch (state) { + case 0: // init; look for first symbol + switch (symbolRead) { + case UNDEFINED: return make_tuple(200, RIGHT, UNDEFINED); + case TRUE: return make_tuple(10, RIGHT, UNDEFINED); + case FALSE: return make_tuple(20, RIGHT, UNDEFINED); + } + case 10: // look for right hand side - we need TRUE + switch (symbolRead) { + case UNDEFINED: return make_tuple(11, LEFT, UNDEFINED); + case TRUE: return make_tuple(10, RIGHT, TRUE); + case FALSE: return make_tuple(10, RIGHT, FALSE); + } + case 11: // right hand side - this should be TRUE + switch (symbolRead) { + case UNDEFINED: return make_tuple(200, LEFT, UNDEFINED); + case TRUE: return make_tuple(12, LEFT, UNDEFINED); + case FALSE: return make_tuple(100, LEFT, UNDEFINED); + } + case 12: // right hand side - new decision + switch (symbolRead) { + case UNDEFINED: return make_tuple(200, RIGHT, UNDEFINED); + case TRUE: return make_tuple(13, LEFT, UNDEFINED); + case FALSE: return make_tuple(23, LEFT, UNDEFINED); + } + case 13: // look for left hand side - we need TRUE + switch (symbolRead) { + case UNDEFINED: return make_tuple(14, RIGHT, UNDEFINED); + case TRUE: return make_tuple(13, LEFT, TRUE); + case FALSE: return make_tuple(13, LEFT, FALSE); + } + case 14: // left hand side - should be TRUE + switch (symbolRead) { + case UNDEFINED: return make_tuple(200, RIGHT, UNDEFINED); + case TRUE: return make_tuple(0, RIGHT, UNDEFINED); + case FALSE: return make_tuple(100, RIGHT, UNDEFINED); + } + + case 20: // look for right hand side - we need FALSE + switch (symbolRead) { + case UNDEFINED: return make_tuple(21, LEFT, UNDEFINED); + case TRUE: return make_tuple(20, RIGHT, TRUE); + case FALSE: return make_tuple(20, RIGHT, FALSE); + } + case 21: // right hand side - this should be FALSE + switch (symbolRead) { + case UNDEFINED: return make_tuple(200, LEFT, UNDEFINED); + case TRUE: return make_tuple(100, LEFT, UNDEFINED); + case FALSE: return make_tuple(22, LEFT, UNDEFINED); + } + case 22: // right hand side - new decision + switch (symbolRead) { + case UNDEFINED: return make_tuple(200, RIGHT, UNDEFINED); + case TRUE: return make_tuple(13, LEFT, UNDEFINED); + case FALSE: return make_tuple(23, LEFT, UNDEFINED); + } + case 23: // look for left hand side - we need FALSE + switch (symbolRead) { + case UNDEFINED: return make_tuple(24, RIGHT, UNDEFINED); + case TRUE: return make_tuple(23, LEFT, TRUE); + case FALSE: return make_tuple(23, LEFT, FALSE); + } + case 24: // left hand side - should be FALSE + switch (symbolRead) { + case UNDEFINED: return make_tuple(200, RIGHT, UNDEFINED); + case TRUE: return make_tuple(100, RIGHT, UNDEFINED); + case FALSE: return make_tuple(0, RIGHT, UNDEFINED); + } + default: + return make_tuple(100, RIGHT, UNDEFINED); + } +} + +bool reject(int state) { + return state == 100; +} + +bool accept(int state) { + return state == 200; +} + +int getNextPosition(int position, Direction direction) { + if (direction == LEFT) { + return position - 1; + } else { + return position + 1; + } +} + +void initBand(Symbol band[MAX_BAND_SIZE], int input) { + int numberOfDigits = input == 0 ? 1 : static_cast(floor(log2(input)) + 1); + + int i = 0; + for (; i < numberOfDigits; i++) { + band[i] = (input & (1 << (numberOfDigits - i - 1))) ? TRUE : FALSE; + } + for (; i < MAX_BAND_SIZE; i++) { + band[i] = UNDEFINED; + } +} + +Symbol getFromBand(Symbol band[MAX_BAND_SIZE], int position) { + if (position < 0 || position >= MAX_BAND_SIZE) { + return UNDEFINED; + } else { + return band[position]; + } +} + +void setOnBand(Symbol band[MAX_BAND_SIZE], int position, Symbol symbol) { + if (!(position < 0 || position >= MAX_BAND_SIZE)) { + band[position] = symbol; + } +} + +bool abort(int state) { + return reject(state) || accept(state); +} + +bool runMachine(Symbol band[MAX_BAND_SIZE]) { + int state = 0; + int position = 0; + + while(!abort(state)) { + Symbol read = getFromBand(band, position); + auto transition = transitionTable(state, read); + state = get<0>(transition); + setOnBand(band, position, get<2>(transition)); + position = getNextPosition(position, get<1>(transition)); + } + + return accept(state); +} + + +bool test(int input) { + Symbol band[MAX_BAND_SIZE]; + initBand(band, input); + + return runMachine(band); +} + +int main() { + resetTestData(); + + auto t1 = high_resolution_clock::now(); + for (int i = 0; i < CASES; i++) { + if (test(inputs[i]) != results[i]) { + cout << i << ": " << inputs[i] << ", " << results[i] << " -> "<< "FAIL" << endl; + } + } + auto t2 = high_resolution_clock::now(); + + duration ms = t2 - t1; + cout << ms.count() << " ms, " << (ms.count() / CASES) << " ms/case" << endl; + +} \ No newline at end of file diff --git a/benchmarkTuringSPnoTuples.cpp b/benchmarkTuringSPnoTuples.cpp new file mode 100644 index 0000000..d5d704a --- /dev/null +++ b/benchmarkTuringSPnoTuples.cpp @@ -0,0 +1,290 @@ +#include +#include +#include +#include + +using namespace std; +using namespace std::chrono; + +#define CASES (100000) +#define MAX_VALUE (0xffff) + +#define MAX_BAND_SIZE (MAX_VALUE + 1) + +#define SEED (1337) + +int inputs[CASES]; +bool results[CASES]; + +bool isBinaryPalindrome(int input) { + int numberOfDigits = input == 0 ? 1 : static_cast(floor(log2(input)) + 1); + + for (int i = 0; i < numberOfDigits / 2; i++) { + if (((input & (1 << i)) ? 1 : 0) != ((input & (1 << (numberOfDigits - i - 1))) ? 1 : 0)) { + return false; + } + } + + return true; +} + +void resetTestData() { + srand(SEED); + + for (int i = 0; i < CASES; i++) { + inputs[i] = rand() % (MAX_VALUE + 1); + results[i] = isBinaryPalindrome(inputs[i]); + } +} + +enum Direction { + LEFT, RIGHT +}; + +enum Symbol { + UNDEFINED, TRUE, FALSE +}; + +inline auto stateTransitionTable(int state, Symbol symbolRead) { + switch (state) { + case 0: // init; look for first symbol + switch (symbolRead) { + case UNDEFINED: return 200; + case TRUE: return 10; + case FALSE: return 20; + } + case 10: // look for right hand side - we need TRUE + switch (symbolRead) { + case UNDEFINED: return 11; + case TRUE: return 10; + case FALSE: return 10; + } + case 11: // right hand side - this should be TRUE + switch (symbolRead) { + case UNDEFINED: return 200; + case TRUE: return 12; + case FALSE: return 100; + } + case 12: // right hand side - new decision + switch (symbolRead) { + case UNDEFINED: return 200; + case TRUE: return 13; + case FALSE: return 23; + } + case 13: // look for left hand side - we need TRUE + switch (symbolRead) { + case UNDEFINED: return 14; + case TRUE: return 13; + case FALSE: return 13; + } + case 14: // left hand side - should be TRUE + switch (symbolRead) { + case UNDEFINED: return 200; + case TRUE: return 0; + case FALSE: return 100; + } + + case 20: // look for right hand side - we need FALSE + switch (symbolRead) { + case UNDEFINED: return 21; + case TRUE: return 20; + case FALSE: return 20; + } + case 21: // right hand side - this should be FALSE + switch (symbolRead) { + case UNDEFINED: return 200; + case TRUE: return 100; + case FALSE: return 22; + } + case 22: // right hand side - new decision + switch (symbolRead) { + case UNDEFINED: return 200; + case TRUE: return 13; + case FALSE: return 23; + } + case 23: // look for left hand side - we need FALSE + switch (symbolRead) { + case UNDEFINED: return 24; + case TRUE: return 23; + case FALSE: return 23; + } + case 24: // left hand side - should be FALSE + switch (symbolRead) { + case UNDEFINED: return 200; + case TRUE: return 100; + case FALSE: return 0; + } + default: + return 100; + } +} + + +inline auto directionTransitionTable(int state, Symbol symbolRead) { + switch (state) { + case 0: // init; look for first symbol + return RIGHT; + case 10: // look for right hand side - we need TRUE + switch (symbolRead) { + case UNDEFINED: return LEFT; + case TRUE: return RIGHT; + case FALSE: return RIGHT; + } + case 11: // right hand side - this should be TRUE + return LEFT; + case 12: // right hand side - new decision + switch (symbolRead) { + case UNDEFINED: return RIGHT; + case TRUE: return LEFT; + case FALSE: return LEFT; + } + case 13: // look for left hand side - we need TRUE + switch (symbolRead) { + case UNDEFINED: return RIGHT; + case TRUE: return LEFT; + case FALSE: return LEFT; + } + case 14: // left hand side - should be TRUE + return RIGHT; + + case 20: // look for right hand side - we need FALSE + switch (symbolRead) { + case UNDEFINED: return LEFT; + case TRUE: return RIGHT; + case FALSE: return RIGHT; + } + case 21: // right hand side - this should be FALSE + return LEFT; + case 22: // right hand side - new decision + switch (symbolRead) { + case UNDEFINED: return RIGHT; + case TRUE: return LEFT; + case FALSE: return LEFT; + } + case 23: // look for left hand side - we need FALSE + switch (symbolRead) { + case UNDEFINED: return RIGHT; + case TRUE: return LEFT; + case FALSE: return LEFT; + } + case 24: // left hand side - should be FALSE + return RIGHT; + default: + return RIGHT; + } +} + + +inline auto writeTransitionTable(int state, Symbol symbolRead) { + switch (state) { + case 0: // init; look for first symbol + return UNDEFINED; + case 10: // look for right hand side - we need TRUE + return symbolRead; + case 11: // right hand side - this should be TRUE + return UNDEFINED; + case 12: // right hand side - new decision + return UNDEFINED; + case 13: // look for left hand side - we need TRUE + return symbolRead; + case 14: // left hand side - should be TRUE + return UNDEFINED; + + case 20: // look for right hand side - we need FALSE + return symbolRead; + case 21: // right hand side - this should be FALSE + return UNDEFINED; + case 22: // right hand side - new decision + return UNDEFINED; + case 23: // look for left hand side - we need FALSE + return symbolRead; + case 24: // left hand side - should be FALSE + return UNDEFINED; + default: + return UNDEFINED; + } +} + +bool reject(int state) { + return state == 100; +} + +bool accept(int state) { + return state == 200; +} + +int getNextPosition(int position, Direction direction) { + if (direction == LEFT) { + return position - 1; + } else { + return position + 1; + } +} + +void initBand(Symbol band[MAX_BAND_SIZE], int input) { + int numberOfDigits = input == 0 ? 1 : static_cast(floor(log2(input)) + 1); + + int i = 0; + for (; i < numberOfDigits; i++) { + band[i] = (input & (1 << (numberOfDigits - i - 1))) ? TRUE : FALSE; + } + for (; i < MAX_BAND_SIZE; i++) { + band[i] = UNDEFINED; + } +} + +Symbol getFromBand(Symbol band[MAX_BAND_SIZE], int position) { + if (position < 0 || position >= MAX_BAND_SIZE) { + return UNDEFINED; + } else { + return band[position]; + } +} + +void setOnBand(Symbol band[MAX_BAND_SIZE], int position, Symbol symbol) { + if (!(position < 0 || position >= MAX_BAND_SIZE)) { + band[position] = symbol; + } +} + +bool abort(int state) { + return reject(state) || accept(state); +} + +bool runMachine(Symbol band[MAX_BAND_SIZE]) { + int state = 0; + int position = 0; + + while(!abort(state)) { + Symbol read = getFromBand(band, position); + setOnBand(band, position, writeTransitionTable(state, read)); + position = getNextPosition(position, directionTransitionTable(state, read)); + state = stateTransitionTable(state, read); + } + + return accept(state); +} + + +bool test(int input) { + Symbol band[MAX_BAND_SIZE]; + initBand(band, input); + + return runMachine(band); +} + +int main() { + resetTestData(); + + auto t1 = high_resolution_clock::now(); + for (int i = 0; i < CASES; i++) { + if (test(inputs[i]) != results[i]) { + cout << i << ": " << inputs[i] << ", " << results[i] << " -> "<< "FAIL" << endl; + } + } + auto t2 = high_resolution_clock::now(); + + duration ms = t2 - t1; + cout << ms.count() << " ms, " << (ms.count() / CASES) << " ms/case" << endl; + +} \ No newline at end of file diff --git a/runAll.sh b/runAll.sh new file mode 100755 index 0000000..6bdc8bf --- /dev/null +++ b/runAll.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +run() { + test="$1" + optimization="$2" + + clang++ -std=c++14 -O"$optimization" "benchmarkTuring$test.cpp" + echo "$test $optimization: " + ./a.out +} + +runOpt() { + run "$1" 0 + run "$1" 3 +} + +runOpt "OOP" +runOpt "FP" +runOpt "SP" +runOpt "SPnoTuples" \ No newline at end of file