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;
}
}