blob: 4216665ea30bd4eba8ad9786648afb4f27923bda [file] [log] [blame]
/* The Computer Language Benchmarks Game
http://shootout.alioth.debian.org/
contributed by Andrew Moon
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// limit output, so we do not benchmark speed of printing
void puts_limited(char* x) {
static int left = 550;
int len = strlen(x);
if (len <= left) {
puts(x);
left -= len;
return;
}
if (left > 0) {
x[left] = '\0';
puts(x);
x[left] = 'z';
left = 0;
}
}
struct Random {
enum { IM = 139968, IA = 3877, IC = 29573 };
Random() : last(42) {}
float get(float max = 1.0f) {
last = (last * IA + IC) % IM;
return max * last / IM;
}
protected:
unsigned int last;
} rng;
struct IUB {
int c;
double p;
unsigned int pi;
};
struct Cumulative {
enum {
slots = 512,
};
Cumulative(IUB* start) {
double p = 0;
for (IUB* iter = start; iter->c; ++iter) {
p += iter->p;
iter->p = p < 1.0 ? p : 1.0;
iter->pi = (unsigned int)(iter->p * slots);
}
for (unsigned int i = 0; i <= slots; i++) {
while (i > start->pi && start->pi != 0) {
++start;
}
table[i] = start;
}
}
const char operator[](float pct) const {
IUB* iter = table[(unsigned int)(pct * slots)];
while (iter->p < pct)
++iter;
return iter->c;
}
protected:
IUB* table[slots + 1];
};
static const size_t lineLength = 60;
struct LineBuffer {
LineBuffer() : lastN(0) {}
LineBuffer& genrand(Cumulative& table, size_t N) {
// assert(N <= lineLength);
for (size_t i = 0; i < N; i++)
buffer[i] = table[rng.get()];
buffer[N] = '\n';
buffer[N + 1] = '\0';
lastN = N + 1;
return *this;
}
void writeline() { puts_limited(buffer); }
protected:
char buffer[lineLength + 2];
size_t lastN;
};
struct RotatingString {
RotatingString(const char* in) : pos(0) {
size = strlen(in);
buffer = new char[size + lineLength];
memcpy(buffer, in, size);
memcpy(buffer + size, in, lineLength);
}
~RotatingString() { delete[] buffer; }
void write(size_t bytes) {
char* temp = new char[bytes + 2];
memcpy(temp, buffer + pos, bytes);
temp[bytes] = '\n';
temp[bytes] = '\0';
puts_limited(temp);
delete temp;
pos += bytes;
if (pos > size)
pos -= size;
}
protected:
char* buffer;
size_t size, pos;
};
template<class Output>
void makeFasta(const char* id, const char* desc, size_t N, Output& output) {
while (N) {
const size_t bytes = N < lineLength ? N : lineLength;
output.writeline(bytes);
N -= bytes;
}
}
struct Repeater {
Repeater(const char* alu) : rot(alu) {}
void writeline(size_t bytes) { rot.write(bytes); }
void run(const char* id, const char* desc, size_t N) {
makeFasta(id, desc, N, *this);
}
protected:
RotatingString rot;
};
struct Randomized {
Randomized(IUB* start) : table(start) {}
void writeline(size_t bytes) { line.genrand(table, bytes).writeline(); }
void run(const char* id, const char* desc, size_t N) {
makeFasta(id, desc, N, *this);
}
protected:
Cumulative table;
LineBuffer line;
};
IUB iub[] = {
{'a', 0.27, 0},
{'c', 0.12, 0},
{'g', 0.12, 0},
{'t', 0.27, 0},
{'B', 0.02, 0},
{'D', 0.02, 0},
{'H', 0.02, 0},
{'K', 0.02, 0},
{'M', 0.02, 0},
{'N', 0.02, 0},
{'R', 0.02, 0},
{'S', 0.02, 0},
{'V', 0.02, 0},
{'W', 0.02, 0},
{'Y', 0.02, 0},
{0, 0, 0},
};
IUB homosapiens[] = {
{'a', 0.3029549426680, 0},
{'c', 0.1979883004921, 0},
{'g', 0.1975473066391, 0},
{'t', 0.3015094502008, 0},
{0, 0, 0},
};
static const char alu[] = "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTG"
"GGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGA"
"GACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAA"
"AATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAAT"
"CCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAAC"
"CCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTG"
"CACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";
int main(int argc, const char* argv[]) {
const size_t n = (argc > 1) ? atoi(argv[1]) : 512;
Repeater(alu).run("ONE", "Homo sapiens alu", n * 2);
Randomized(iub).run("TWO", "IUB ambiguity codes", n * 3);
Randomized(homosapiens).run("THREE", "Homo sapiens frequency", n * 5);
return 0;
}