/*
 * $Header: /usr/u/wjr/src/ADT/RCS/hist.h,v 1.5 1991/09/02 19:28:40 wjr Exp $
 */
/*
 * Header file for the histogram ADT
 */

#ifndef HIST_H
#define HIST_H

#if      0
BEGIN DOCUMENTATION

/*
 *	hist.c - Histograms.
 *
 * What's a histogram, really? Well, it's got a bunch of bins, and you
 * accumulate counts in each bin. That's about it, really...
 *
 * Exports:
 *	type Histogram
 *
 *	constant Histogram NULLHIST
 *
 *	Histogram hiNew(unsigned nbins, double low, double high) - create a
 *		new, empty, histogram.
 *
 *	void hiFree(Histogram h) - free histogram h.
 *
 *	void hiAdd(Histogram h, double val, double howmuch) - accumulate
 *		into val's bin in h.
 *
 *	void hiInc(Histogram h, double val) - add 1 to val's bin in h.
 *
 *	double hiCount(Histogram h, unsigned n) - return the n'th
 *		count entry of h.
 *
 *	double hiLow(Histogram h) - return the low bound of h.
 *
 *	double hiHigh(Histogram h) - return the high bound of h.
 *
 *	unsigned hiNBins(Histogram h) - return the number of bins of h.
 *
 *	double hiBinL(Histogram h, unsigned n) - return the left edge of
 *		the n'th bin of h.
 *
 *	double hiBinR(Histogram h, unsigned n) - return the right edge of
 *		the n'th bin of h (which is the same as the left edge of
 *		the n+1'th bin).
 *
 *	double hiBinC(Histogram h, unsigned n) - return the centre of
 *		the n'th bin of h.
 *
 * hiNew creates a new Histogram, with the specified number of bins,
 *	which will be used to count values in the range [low,high).
 *
 * hiFree frees the storage associated with a Histogram.
 *
 * hiAdd adds the given value to the appropriate bin in the given
 *	histogram. If the binning value is not in the range [low,high) for that
 *	histogram, it is added to the (low or high) "end" bin. This is
 *	so that minor numerical errors around the edges do not cause
 *	assert failures.
 *
 * hiInc is just an abbreviation for hiAdd(h, val, 1.)
 *
 * hiCount returns the number of values which have fallen into that bin of
 *	that histogram. The bins are numbered 0..nbins-1, and n must lie
 *	in this range. This is actually an lvalue, and so the value of
 *	a particular bin may be modified.
 *
 * hiLow returns the low bound of the given histogram (the low value which
 *	was passed to the call to hiNew which created it).
 *
 * hiHigh returns the high bound of the given histogram (the high value which
 *	was passed to the call to hiNew which created it).
 *
 * hiNBins returns the number of bins in the given histogram.
 *
 */


END DOCUMENTATION
#endif   


/* One opaque type, coming right up... */
typedef struct {
    double *bins;
    unsigned nbins;
    double low;
    double high;
    } *Histogram;

/* Exported routines */
extern Histogram hiNew(unsigned nbins, double low, double high);
extern void hiFree(Histogram h);
extern void hiAdd(Histogram h, double val, double howmuch);

/* These are routines which happen to be implemented as macros, at present. */
/*
 * Note that these do not return lvalues, but *rvalues only*. If you use
 * these to get lvalues, a pox be upon you and your offspring unto the
 * seventh generation!
 *
 * These have less error checking than is really desirable.
 */
#define hiLow(h)	((h)->low)
#define	hiHigh(h)	((h)->high)
#define hiNBins(h)	((h)->nbins)

/* This allows access to a particular bin. It would be nice if it checked... */
#define hiCount(h,n)	(((h)->bins)[n])

/* and a useful abbreviation */
#define	hiInc(h,val)	hiAdd((h), (val), 1.)

/* Some useful things to find the locations of bins */
#define	hiBinL(h,n)	((h)->low + ((h)->high - (h)->low) / (h)->nbins * (n))
#define	hiBinR(h,n)	((h)->low + ((h)->high - (h)->low) / (h)->nbins * ((n)+1))
#define	hiBinC(h,n)	((h)->low + ((h)->high - (h)->low) / (h)->nbins * ((n)+.5))

/* The constant null histogram, used as an error return from hiNew */
#define	NULLHIST	((Histogram)NULL)

#endif
