package hep.aida.bin; import cern.colt.list.DoubleArrayList; import cern.jet.stat.Descriptive; /** * 1-dimensional non-rebinnable bin consuming <tt>double</tt> elements; * Efficiently computes basic statistics of data sequences. * First see the <a href="package-summary.html">package summary</a> and javadoc <a href="package-tree.html">tree view</a> to get the broad picture. * <p> * The data streamed into a <tt>SimpleBin1D</tt> is not preserved! * As a consequence infinitely many elements can be added to this bin. * As a further consequence this bin cannot compute more than basic statistics. * It is also not rebinnable. * If these drawbacks matter, consider to use a {@link DynamicBin1D}, * which overcomes them at the expense of increased memory requirements. * <p> * This class is fully thread safe (all public methods are synchronized). * Thus, you can have one or more threads adding to the bin as well as one or more threads reading and viewing the statistics of the bin <i>while it is filled</i>. * For high performance, add data in large chunks (buffers) via method <tt>addAllOf</tt> rather than piecewise via method <tt>add</tt>. * <p> * <b>Implementation</b>: * Incremental maintainance. Performance linear in the number of elements added. * * @author wolfgang.hoschek@cern.ch * @version 0.9, 03-Jul-99 */ public class StaticBin1D extends AbstractBin1D { /** * The number of elements consumed by incremental parameter maintainance. */ protected int size = 0; // cached parameters protected double min = 0.0; // Min( x[i] ) protected double max = 0.0; // Max( x[i] ) protected double sum = 0.0; // Sum( x[i] ) protected double sum_xx = 0.0; // Sum( x[i]*x[i] ) /** * Function arguments used by method addAllOf(...) * For memory tuning only. Avoids allocating a new array of arguments each time addAllOf(...) is called. * * Each bin does not need its own set of argument vars since they are declared as "static". * addAllOf(...) of this class uses only 4 entries. * Subclasses computing additional incremental statistics may need more arguments. * So, to be on the safe side we allocate space for 20 args. * Be sure you access this arguments only in synchronized blocks like * synchronized (arguments) { do it } * * By the way, the whole fuss would be unnecessary if Java would know INOUT parameters (call by reference). */ static transient protected double[] arguments = new double[20]; /** * Constructs and returns an empty bin. */ public StaticBin1D() { clear(); } /** * Adds the specified element to the receiver. * * @param element element to be appended. */ public synchronized void add(double element) { // prototyping implementation; inefficient; TODO this.addAllOf(new DoubleArrayList(new double[] {element})); /* sumSquares += element * element; if (this.done == 0) { // initial setup this.min = element; this.max = element; } else { if (element < this.min) this.min = element; if (element > this.max) this.max = element; double oldMean = this.mean; this.mean += (element - this.mean)/(done+1); this.sumsq += (element-this.mean)*(element-oldMean); // cool, huh? } this.done++; */ } /** * Adds the part of the specified list between indexes <tt>from</tt> (inclusive) and <tt>to</tt> (inclusive) to the receiver. * * @param list the list of which elements shall be added. * @param from the index of the first element to be added (inclusive). * @param to the index of the last element to be added (inclusive). * @throws IndexOutOfBoundsException if <tt>list.size()>0 && (from<0 || from>to || to>=list.size())</tt>. */ public synchronized void addAllOfFromTo(DoubleArrayList list, int from, int to) { //if (this.arguments == null) setUpCache(); synchronized (arguments) { // prepare arguments arguments[0] = this.min; arguments[1] = this.max; arguments[2] = this.sum; arguments[3] = this.sum_xx; Descriptive.incrementalUpdate(list, from, to, arguments); // store the new parameters back this.min = arguments[0]; this.max = arguments[1]; this.sum = arguments[2]; this.sum_xx = arguments[3]; this.size += to-from+1; } } /** * Removes all elements from the receiver. * The receiver will be empty after this call returns. */ public synchronized void clear() { clearAllMeasures(); this.size = 0; } /** * Resets the values of all measures. */ protected void clearAllMeasures() { this.min = Double.POSITIVE_INFINITY; this.max = Double.NEGATIVE_INFINITY; this.sum = 0.0; this.sum_xx = 0.0; } /** * Returns <tt>false</tt>. * Returns whether a client can obtain all elements added to the receiver. * In other words, tells whether the receiver internally preserves all added elements. * If the receiver is rebinnable, the elements can be obtained via <tt>elements()</tt> methods. * */ public synchronized boolean isRebinnable() { return false; } /** * Returns the maximum. */ public synchronized double max() { return this.max; } /** * Returns the minimum. */ public synchronized double min() { return this.min; } /** * Returns the number of elements contained in the receiver. * * @returns the number of elements contained in the receiver. */ public synchronized int size() { return this.size; } /** * Returns the sum of all elements, which is <tt>Sum( x[i] )</tt>. */ public synchronized double sum() { return this.sum; } /** * Returns the sum of squares, which is <tt>Sum( x[i] * x[i] )</tt>. */ public synchronized double sumOfSquares() { return this.sum_xx; } }