blob: 1b52e1b278212e847659d833dbea42be3636e3e6 [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;
}