/* The Computer Language Benchmarks Game http://shootout.alioth.debian.org/ contributed by Andrew Moon */ #include #include #include // 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; }