| /* 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; | |
| } |