/*
 * $Id: histogram.c,v 1.1 2000/08/07 23:15:03 emmerson Exp $
 */

/*LINTLIBRARY*/

#include "udposix.h"
#include <stddef.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>

#include "histogram.h"

#undef MAX
#define MAX(a,b)	((a) > (b) ? (a) : (b))


/*
 * Initialize a histogram.
 *
 * Returns:
 *	-1	error
 *	 0	success
 */
    int
hist_init(hist, start, inc, nbin)
    Histogram	*hist;
    HIST_TYPE	start;
    HIST_TYPE	inc;
    long	nbin;
{
    int		status	= -1;

    assert(0 != inc);
    assert(0 < nbin);

    if (0 != inc && 0 < nbin) {
	hist->bin	= (long*)malloc(MAX(nbin, 1) * sizeof(long));
	if (hist->bin) {
	    hist->start	= start;
	    hist->stop	= start + nbin*inc;
	    hist->inc	= inc;
	    hist->nbin	= nbin;

	    hist_clear(hist);

	    status	= 0;
	}
    }

    return status;
}


/*
 * Clear a histogram.
 */
    void
hist_clear(hist)
    Histogram	*hist;
{
    long	i;

    assert(hist);
    assert(hist->bin);

    hist->toolow	= 0;
    hist->toohigh	= 0;
    hist->total		= 0;

    for (i = 0; i < hist->nbin; ++i)
	hist->bin[i]	= 0;
}


/*
 * Add a value to a histogram.
 */
    void
hist_add(hist, value)
    Histogram	*hist;
    HIST_TYPE	value;
{
    assert(hist);

    if ((0 < hist->inc && hist->start > value) ||
	(0 > hist->inc && hist->start < value)) {

	hist->toolow++;
    } else if ((0 < hist->inc && hist->stop <= value) ||
	       (0 > hist->inc && hist->stop >= value)) {
	hist->toohigh++;
    } else {
	long	index	= (value - hist->start) / hist->inc;
	assert(0 != hist->inc);
	assert(hist->bin);
	hist->bin[index]++;
    }

    hist->total++;
}


/*
 * Return the count of a histogram's bin.
 */
    long
hist_get(hist, index)
    Histogram	*hist;
    long	index;
{
    long	count;

    assert(hist);

    if (0 > index) {
	count	= hist->toolow;
    } else if (hist->nbin <= index) {
	count	= hist->toohigh;
    } else {
	count	= hist->bin[index];
    }

    return count;
}


/*
 * Return the total number of a histogram.
 */
    long
hist_total(hist)
    Histogram	*hist;
{
    assert(hist);

    return hist->total;
}


/*
 * Destroy a histogram.
 */
    void
hist_destroy(hist)
    Histogram	*hist;
{
    if (hist && hist->bin) {
	(void) free((voidp)hist->bin);
	hist->bin	= NULL;
    }
}
