/* $Header$ */ #include #include #include #include #include #include #include #include #define START_RABBITS 1 typedef struct user_args user_args; struct user_args { double probReproduce; unsigned int numTimeSteps; long unsigned int timeLimitNs; }; void carp(const char *msg,const char *file,const int line) { fprintf(stderr,"%s: %s at %s:%d\n", msg,strerror(errno),file,line ); } int get_realtime(struct timespec *timestamp) { if((clock_gettime(CLOCK_REALTIME,timestamp)) == -1) { carp("Getting timestamp failed", __FILE__,__LINE__ ); return -1; } return 0; } void time_diff(const struct timespec *start, const struct timespec *end, struct timespec *diff_time) { if((end->tv_nsec-start->tv_nsec)<0) { diff_time->tv_sec = end->tv_sec-start->tv_sec-1; diff_time->tv_nsec = 1000000000 + (end->tv_nsec-start->tv_nsec); } else { diff_time->tv_sec = end->tv_sec-start->tv_sec; diff_time->tv_nsec = end->tv_nsec-start->tv_nsec; } } unsigned long int elapsed_time(const struct timespec *initial_ts) { struct timespec now_ts,diff_time; if((clock_gettime(CLOCK_REALTIME,&now_ts)) == -1) { carp("Getting final time failed", __FILE__,__LINE__ ); return -1; } time_diff(initial_ts,&now_ts,&diff_time); return diff_time.tv_sec*1000000000 + diff_time.tv_nsec; } void usage(const char *name) { fprintf(stderr,"%s -n -p \n", name ); } unsigned long int breed_rabbits( const struct user_args arg_struct, struct drand48_data *rand_buffer, const unsigned int curNumRabbits ) { unsigned long int newNumRabbits; unsigned int i; double rand; newNumRabbits = curNumRabbits; #ifdef OPENMP #pragma omp parallel for reduction(+: newNumRabbits) #endif for (i = 0; i < curNumRabbits; i++) { /* see manpage for drand48_r, part of strlib.h */ drand48_r(rand_buffer,&rand); #ifdef DEBUG fprintf(stderr,"RNG produced %f for rabbit %u\n", rand,i ); #endif if (rand < arg_struct.probReproduce) { newNumRabbits++; #ifdef DEBUG fprintf(stderr,"Rabbit %u spawned, %u total rabbits\n", i,newNumRabbits ); #endif } } return newNumRabbits; } /* This is the master breeding function * It takes in the struct containing the user-supplied arguments * and will return the number of rabbits bred. */ unsigned long int master_breeding( const struct user_args arg_struct ) { unsigned long int curNumRabbits; /* rabbit counter */ unsigned int i; /* loop control variable */ struct drand48_data rand_buffer; struct timespec tp0; unsigned long int elapsed_ns; if((get_realtime(&tp0)) != 0) { carp("get_realtime failed",__FILE__,__LINE__); abort(); } /* Seed thread-safe random number generator. */ /* see manpage for srand48_r, part of strlib.h */ srand48_r((time(NULL)+getpid()),&rand_buffer); /* Run algorithm */ curNumRabbits = START_RABBITS; for (i = 0; i < arg_struct.numTimeSteps; i++) { curNumRabbits = breed_rabbits(arg_struct,&rand_buffer,curNumRabbits); if(arg_struct.timeLimitNs > 0) { elapsed_ns = elapsed_time(&tp0); if(elapsed_ns > arg_struct.timeLimitNs) { fprintf(stderr,"Time step %i, %ld nanoseconds\n", i,elapsed_ns ); break; } } } #ifdef DEBUG fprintf(stderr,"%d rabbits\n",curNumRabbits); #endif return curNumRabbits; } bool get_args( const int argc, char **argv, struct user_args *arg_struct ) { int c; arg_struct->numTimeSteps = 0; arg_struct->probReproduce = -1; arg_struct->timeLimitNs = 0; while ((c = getopt(argc,argv,":l:n:p:")) != -1) { switch(c) { case 'l': /* Convert to nanoseconds */ arg_struct->timeLimitNs = strtoll(optarg,NULL,10) * 1000 * 1000 * 1000; break; case 'n': arg_struct->numTimeSteps = atoi(optarg); break; case 'p': arg_struct->probReproduce = strtod(optarg,NULL); break; case '?': usage(argv[0]); return false; break; default: return false; break; } } if(arg_struct->numTimeSteps == 0 || arg_struct->probReproduce < 0 ) { fprintf(stderr,"Supply valid options!\n"); usage(argv[0]); return false; } #ifdef DEBUG fprintf(stderr,"User supplied %d time steps and %f reproduce rate\n", arg_struct->numTimeSteps,arg_struct->probReproduce ); #endif return true; } int main(int argc,char **argv) { struct user_args arg_struct; if(!get_args(argc,argv,&arg_struct)) { fprintf(stderr,"Getting arguments failed!\n"); exit(EXIT_FAILURE); } printf("%ld rabbits at %f reproduction probability and %d time steps\n", master_breeding(arg_struct), arg_struct.probReproduce, arg_struct.numTimeSteps ); exit(EXIT_SUCCESS); }