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