mirror of
https://github.com/sigmasternchen/oop-benchmarks
synced 2025-03-15 07:08:57 +00:00
restructure of turing benchmark
This commit is contained in:
parent
c6043c6eaf
commit
b920b78d09
10 changed files with 477 additions and 411 deletions
|
@ -1,212 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <stdexcept>
|
||||
#include <chrono>
|
||||
|
||||
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<int>(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<Symbol (int)> _f = x; return _f; }
|
||||
|
||||
auto emptyBand() {
|
||||
return [](int _) { return UNDEFINED; };
|
||||
}
|
||||
|
||||
auto setOnBand(int pos, Symbol symbol, const function<Symbol (int)>& 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<int>(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<Symbol (int)> 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<double, std::milli> ms = t2 - t1;
|
||||
cout << ms.count() << " ms, " << (ms.count() / CASES) << " ms/case" << endl;
|
||||
|
||||
}
|
52
c++/turing/benchmark.cpp
Normal file
52
c++/turing/benchmark.cpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <chrono>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace std::chrono;
|
||||
|
||||
#define SEED (1337)
|
||||
|
||||
int inputs[CASES];
|
||||
bool results[CASES];
|
||||
|
||||
extern bool test(int input);
|
||||
|
||||
bool isBinaryPalindrome(int input) {
|
||||
int numberOfDigits = input == 0 ? 1 : static_cast<int>(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]);
|
||||
}
|
||||
}
|
||||
|
||||
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<double, std::milli> ms = t2 - t1;
|
||||
cout << ms.count() << " ms, " << (ms.count() / CASES) << " ms/case" << endl;
|
||||
|
||||
}
|
18
c++/turing/common.h
Normal file
18
c++/turing/common.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef OOP_BENCHMARK_COMMON_H
|
||||
#define OOP_BENCHMARK_COMMON_H
|
||||
|
||||
#define CASES (100000)
|
||||
#define MAX_VALUE (0xffff)
|
||||
|
||||
#define MAX_BAND_SIZE (MAX_VALUE + 1)
|
||||
|
||||
enum Direction {
|
||||
LEFT, RIGHT
|
||||
};
|
||||
|
||||
enum Symbol {
|
||||
UNDEFINED, TRUE, FALSE
|
||||
};
|
||||
|
||||
|
||||
#endif //OOP_BENCHMARK_COMMON_H
|
|
@ -1,49 +1,9 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <stdexcept>
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
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<int>(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:
|
||||
|
@ -265,20 +225,4 @@ bool test(int input) {
|
|||
|
||||
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<double, std::milli> ms = t2 - t1;
|
||||
cout << ms.count() << " ms, " << (ms.count() / CASES) << " ms/case" << endl;
|
||||
|
||||
}
|
221
c++/turing/oop-without-virtual-methods.cpp
Normal file
221
c++/turing/oop-without-virtual-methods.cpp
Normal file
|
@ -0,0 +1,221 @@
|
|||
#include <stdexcept>
|
||||
#include <cmath>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
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 PalindromeRecognizer {
|
||||
private:
|
||||
int state;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 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<int>(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;
|
||||
PalindromeRecognizer* stateMachine;
|
||||
|
||||
public:
|
||||
TuringMachine(PalindromeRecognizer* 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();
|
||||
}
|
21
c++/turing/runAll.sh
Executable file
21
c++/turing/runAll.sh
Executable file
|
@ -0,0 +1,21 @@
|
|||
#!/bin/sh
|
||||
|
||||
run() {
|
||||
test="$1"
|
||||
optimization="$2"
|
||||
|
||||
clang++ -std=c++14 -O"$optimization" "benchmark.cpp" "$1.cpp"
|
||||
echo "$test $optimization: "
|
||||
./a.out
|
||||
}
|
||||
|
||||
runOpt() {
|
||||
run "$1" 0
|
||||
run "$1" 3
|
||||
}
|
||||
|
||||
runOpt "oop-with-virtual-methods"
|
||||
runOpt "oop-without-virtual-methods"
|
||||
runOpt "sp-with-tuples"
|
||||
runOpt "sp-with-function-per-value"
|
||||
runOpt "sp-with-structs"
|
|
@ -1,49 +1,8 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <stdexcept>
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
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<int>(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) {
|
||||
|
@ -271,20 +230,4 @@ bool test(int input) {
|
|||
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<double, std::milli> ms = t2 - t1;
|
||||
cout << ms.count() << " ms, " << (ms.count() / CASES) << " ms/case" << endl;
|
||||
|
||||
}
|
155
c++/turing/sp-with-structs.cpp
Normal file
155
c++/turing/sp-with-structs.cpp
Normal file
|
@ -0,0 +1,155 @@
|
|||
#include <cmath>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
typedef struct transition {
|
||||
int state;
|
||||
Direction direction;
|
||||
Symbol write;
|
||||
} transition_t;
|
||||
|
||||
|
||||
transition_t transitionTable(int state, Symbol symbolRead) {
|
||||
switch (state) {
|
||||
case 0: // init; look for first symbol
|
||||
switch (symbolRead) {
|
||||
case UNDEFINED: return {200, RIGHT, UNDEFINED};
|
||||
case TRUE: return {10, RIGHT, UNDEFINED};
|
||||
case FALSE: return {20, RIGHT, UNDEFINED};
|
||||
}
|
||||
case 10: // look for right hand side - we need TRUE
|
||||
switch (symbolRead) {
|
||||
case UNDEFINED: return {11, LEFT, UNDEFINED};
|
||||
case TRUE: return {10, RIGHT, TRUE};
|
||||
case FALSE: return {10, RIGHT, FALSE};
|
||||
}
|
||||
case 11: // right hand side - this should be TRUE
|
||||
switch (symbolRead) {
|
||||
case UNDEFINED: return {200, LEFT, UNDEFINED};
|
||||
case TRUE: return {12, LEFT, UNDEFINED};
|
||||
case FALSE: return {100, LEFT, UNDEFINED};
|
||||
}
|
||||
case 12: // right hand side - new decision
|
||||
switch (symbolRead) {
|
||||
case UNDEFINED: return {200, RIGHT, UNDEFINED};
|
||||
case TRUE: return {13, LEFT, UNDEFINED};
|
||||
case FALSE: return {23, LEFT, UNDEFINED};
|
||||
}
|
||||
case 13: // look for left hand side - we need TRUE
|
||||
switch (symbolRead) {
|
||||
case UNDEFINED: return {14, RIGHT, UNDEFINED};
|
||||
case TRUE: return {13, LEFT, TRUE};
|
||||
case FALSE: return {13, LEFT, FALSE};
|
||||
}
|
||||
case 14: // left hand side - should be TRUE
|
||||
switch (symbolRead) {
|
||||
case UNDEFINED: return {200, RIGHT, UNDEFINED};
|
||||
case TRUE: return {0, RIGHT, UNDEFINED};
|
||||
case FALSE: return {100, RIGHT, UNDEFINED};
|
||||
}
|
||||
|
||||
case 20: // look for right hand side - we need FALSE
|
||||
switch (symbolRead) {
|
||||
case UNDEFINED: return {21, LEFT, UNDEFINED};
|
||||
case TRUE: return {20, RIGHT, TRUE};
|
||||
case FALSE: return {20, RIGHT, FALSE};
|
||||
}
|
||||
case 21: // right hand side - this should be FALSE
|
||||
switch (symbolRead) {
|
||||
case UNDEFINED: return {200, LEFT, UNDEFINED};
|
||||
case TRUE: return {100, LEFT, UNDEFINED};
|
||||
case FALSE: return {22, LEFT, UNDEFINED};
|
||||
}
|
||||
case 22: // right hand side - new decision
|
||||
switch (symbolRead) {
|
||||
case UNDEFINED: return {200, RIGHT, UNDEFINED};
|
||||
case TRUE: return {13, LEFT, UNDEFINED};
|
||||
case FALSE: return {23, LEFT, UNDEFINED};
|
||||
}
|
||||
case 23: // look for left hand side - we need FALSE
|
||||
switch (symbolRead) {
|
||||
case UNDEFINED: return {24, RIGHT, UNDEFINED};
|
||||
case TRUE: return {23, LEFT, TRUE};
|
||||
case FALSE: return {23, LEFT, FALSE};
|
||||
}
|
||||
case 24: // left hand side - should be FALSE
|
||||
switch (symbolRead) {
|
||||
case UNDEFINED: return {200, RIGHT, UNDEFINED};
|
||||
case TRUE: return {100, RIGHT, UNDEFINED};
|
||||
case FALSE: return {0, RIGHT, UNDEFINED};
|
||||
}
|
||||
default:
|
||||
return {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<int>(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 = transition.state;
|
||||
setOnBand(band, position, transition.write);
|
||||
position = getNextPosition(position, transition.direction);
|
||||
}
|
||||
|
||||
return accept(state);
|
||||
}
|
||||
|
||||
|
||||
bool test(int input) {
|
||||
Symbol band[MAX_BAND_SIZE];
|
||||
initBand(band, input);
|
||||
|
||||
return runMachine(band);
|
||||
}
|
|
@ -1,49 +1,9 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <stdexcept>
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <tuple>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
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<int>(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) {
|
||||
|
@ -186,20 +146,4 @@ bool test(int input) {
|
|||
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<double, std::milli> ms = t2 - t1;
|
||||
cout << ms.count() << " ms, " << (ms.count() / CASES) << " ms/case" << endl;
|
||||
|
||||
}
|
20
runAll.sh
20
runAll.sh
|
@ -1,20 +0,0 @@
|
|||
#!/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"
|
Loading…
Reference in a new issue