//
// BinTest
//
// This program tests a random number generator by running it n times
// with m bins for sorting over the interval [0, 1].
//


#import "Random.h"
#import <math.h>
#import <stdio.h>
#import <stdlib.h>


#define DEFAULT_N	1000
#define DEFAULT_M	10
#define RANGE		3.5

#define MAX_BAR		40


int main(int argc, char *argv[])
{
    id		myRand;				// Random number generator.
    int		n;				// Quantity of numbers to generate.
    int		m;				// Number of bins in which to sort them.
    int		max;				// Size of largest bin.
    int		i;				// Generic loop variable.
    int		j;				// Generic loop variable.
    double	x;				// The random number.
    int		slot;				// The sorted position of a number.
    int		barsize;			// The length of a result bar.
    int		*binneg;			// The bin array (dynamically allocated).
    int		*binpos;			// The bin array (dynamically allocated).
    int		which;
    
    myRand = [[Random alloc] init];
    [myRand setGOrigin:1.5];
    
    switch(argc) {
        case 2:
	    sscanf(argv[1], "%d", &n);
	    m = DEFAULT_M;
	    break;
	case 3:
	    sscanf(argv[1], "%d", &n);
	    sscanf(argv[2], "%d", &m);
	    break;
	default:
	    n = DEFAULT_N;
	    m = DEFAULT_M;
	    break;
    }
    
    //
    // Allocate and initialize slot array:
    //
    
    binneg = (int *)malloc(m * sizeof(int));
    binpos = (int *)malloc(m * sizeof(int));
    for(i = 0; i < m; i++) {
        binneg[i] = 0;
	binpos[i] = 0;
    }
    
    //
    // Make n random numbers:
    //
        
    for(i = 0; i < n; i++) {
        do {
	    x = [myRand gaussian];
	} while (x == 0.0);
	
	which = (x > 0);
	slot = (int)floor(fabs(x) * m / RANGE);
	if((slot >= 0) && (slot < m) && (x != 0.0)) {		// If it is in range,
	    switch(which) {					//   count it.
	        case 0:
		    if((++binneg[slot]) > max) {
			max = binneg[slot];
		    }
		    break;
		case 1:
		    if((++binpos[slot]) > max) {
			max = binpos[slot];
		    }
		    break;
		default:
		    printf("Why is which = %d?\n", which);
		    break;
	    }
	}
    }
    
    //
    // Print the results:
    //
    
    for(i = m - 1; i >= 0; i--) {
        printf("%+1.6f to %+1.6f: %6d:", -((i + 1) * (RANGE / m)),
		-(i * (RANGE / m)), binneg[i]);
	
	barsize = (int)((double)binneg[i] / ((double)max / (double)MAX_BAR));
	for(j = 0; j < barsize; j++)
	    printf("*");
	printf("\n");
    }
    for(i = 0; i < m; i++) {
        printf("%+1.6f to %+1.6f: %6d:", i * (RANGE / m), (i + 1) * (RANGE / m), binpos[i]);
	
	barsize = (int)((double)binpos[i] / ((double)max / (double)MAX_BAR));
	for(j = 0; j < barsize; j++)
	    printf("*");
	printf("\n");
    }
    
    printf("Max = %d\n\n", max);
    
    //
    // Clean up:
    //
    
    free(binneg);
    free(binpos);
    
    //
    // Return to caller:
    //
    
    return 0;
}


//
// End of file.
//