All Downloads are FREE. Search and download functionalities are using the official Maven repository.

hep.aida.tfloat.bin.MightyStaticFloatBin1D Maven / Gradle / Ivy

Go to download

Parallel Colt is a multithreaded version of Colt - a library for high performance scientific computing in Java. It contains efficient algorithms for data analysis, linear algebra, multi-dimensional arrays, Fourier transforms, statistics and histogramming.

The newest version!
package hep.aida.tfloat.bin;

import cern.colt.list.tfloat.FloatArrayList;
import cern.jet.stat.tfloat.FloatDescriptive;

/**
 * Static and the same as its superclass, except that it can do more:
 * Additionally computes moments of arbitrary integer order, harmonic mean,
 * geometric mean, etc.
 * 
 * Constructors need to be told what functionality is required for the given use
 * case. Only maintains aggregate measures (incrementally) - the added elements
 * themselves are not kept.
 * 
 * @author [email protected]
 * @version 0.9, 03-Jul-99
 */
public class MightyStaticFloatBin1D extends StaticFloatBin1D {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    protected boolean hasSumOfLogarithms = false;

    protected float sumOfLogarithms = 0.0f; // Sum( Log(x[i]) )

    protected boolean hasSumOfInversions = false;

    protected float sumOfInversions = 0.0f; // Sum( 1/x[i] )

    protected float[] sumOfPowers = null; // Sum( x[i]^3 ) .. Sum( x[i]^max_k

    // )

    /**
     * Constructs and returns an empty bin with limited functionality but good
     * performance; equivalent to MightyStaticBin1D(false,false,4).
     */
    public MightyStaticFloatBin1D() {
        this(false, false, 4);
    }

    /**
     * Constructs and returns an empty bin with the given capabilities.
     * 
     * @param hasSumOfLogarithms
     *            Tells whether {@link #sumOfLogarithms()} can return meaningful
     *            results. Set this parameter to false if measures of
     *            sum of logarithms, geometric mean and product are not
     *            required.
     *            

* @param hasSumOfInversions * Tells whether {@link #sumOfInversions()} can return meaningful * results. Set this parameter to false if measures of * sum of inversions, harmonic mean and sumOfPowers(-1) are not * required. *

* @param maxOrderForSumOfPowers * The maximum order k for which * {@link #sumOfPowers(int)} can return meaningful results. Set * this parameter to at least 3 if the skew is required, to at * least 4 if the kurtosis is required. In general, if moments * are required set this parameter at least as large as the * largest required moment. This method always substitutes * Math.max(2,maxOrderForSumOfPowers) for the parameter * passed in. Thus, sumOfPowers(0..2) always returns * meaningful results. * * @see #hasSumOfPowers(int) * @see #moment(int,float) */ public MightyStaticFloatBin1D(boolean hasSumOfLogarithms, boolean hasSumOfInversions, int maxOrderForSumOfPowers) { setMaxOrderForSumOfPowers(maxOrderForSumOfPowers); this.hasSumOfLogarithms = hasSumOfLogarithms; this.hasSumOfInversions = hasSumOfInversions; this.clear(); } /** * Adds the part of the specified list between indexes from * (inclusive) and to (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 * list.size()>0 && (from<0 || from>to || to>=list.size()) * . */ public synchronized void addAllOfFromTo(FloatArrayList list, int from, int to) { super.addAllOfFromTo(list, from, to); if (this.sumOfPowers != null) { // int max_k = this.min_k + this.sumOfPowers.length-1; FloatDescriptive.incrementalUpdateSumsOfPowers(list, from, to, 3, getMaxOrderForSumOfPowers(), this.sumOfPowers); } if (this.hasSumOfInversions) { this.sumOfInversions += FloatDescriptive.sumOfInversions(list, from, to); } if (this.hasSumOfLogarithms) { this.sumOfLogarithms += FloatDescriptive.sumOfLogarithms(list, from, to); } } /** * Resets the values of all measures. */ protected void clearAllMeasures() { super.clearAllMeasures(); this.sumOfLogarithms = 0.0f; this.sumOfInversions = 0.0f; if (this.sumOfPowers != null) { for (int i = this.sumOfPowers.length; --i >= 0;) { this.sumOfPowers[i] = 0.0f; } } } /** * Returns a deep copy of the receiver. * * @return a deep copy of the receiver. */ public synchronized Object clone() { MightyStaticFloatBin1D clone = (MightyStaticFloatBin1D) super.clone(); if (this.sumOfPowers != null) clone.sumOfPowers = clone.sumOfPowers.clone(); return clone; } /** * Computes the deviations from the receiver's measures to another bin's * measures. * * @param other * the other bin to compare with * @return a summary of the deviations. */ public String compareWith(AbstractFloatBin1D other) { StringBuffer buf = new StringBuffer(super.compareWith(other)); if (other instanceof MightyStaticFloatBin1D) { MightyStaticFloatBin1D m = (MightyStaticFloatBin1D) other; if (hasSumOfLogarithms() && m.hasSumOfLogarithms()) buf.append("geometric mean: " + relError(geometricMean(), m.geometricMean()) + " %\n"); if (hasSumOfInversions() && m.hasSumOfInversions()) buf.append("harmonic mean: " + relError(harmonicMean(), m.harmonicMean()) + " %\n"); if (hasSumOfPowers(3) && m.hasSumOfPowers(3)) buf.append("skew: " + relError(skew(), m.skew()) + " %\n"); if (hasSumOfPowers(4) && m.hasSumOfPowers(4)) buf.append("kurtosis: " + relError(kurtosis(), m.kurtosis()) + " %\n"); buf.append("\n"); } return buf.toString(); } /** * Returns the geometric mean, which is * Product( x[i] )1.0/size(). * * This method tries to avoid overflows at the expense of an equivalent but * somewhat inefficient definition: * geoMean = exp( Sum( Log(x[i]) ) / size()). Note that for a * geometric mean to be meaningful, the minimum of the data sequence must * not be less or equal to zero. * * @return the geometric mean; Float.NaN if * !hasSumOfLogarithms(). */ public synchronized float geometricMean() { return FloatDescriptive.geometricMean(size(), sumOfLogarithms()); } /** * Returns the maximum order k for which sums of powers are * retrievable, as specified upon instance construction. * * @see #hasSumOfPowers(int) * @see #sumOfPowers(int) */ public synchronized int getMaxOrderForSumOfPowers() { /* * order 0..2 is always recorded. order 0 is size() order 1 is sum() * order 2 is sum_xx() */ if (this.sumOfPowers == null) return 2; return 2 + this.sumOfPowers.length; } /** * Returns the minimum order k for which sums of powers are * retrievable, as specified upon instance construction. * * @see #hasSumOfPowers(int) * @see #sumOfPowers(int) */ public synchronized int getMinOrderForSumOfPowers() { int minOrder = 0; if (hasSumOfInversions()) minOrder = -1; return minOrder; } /** * Returns the harmonic mean, which is size() / Sum( 1/x[i] ). * Remember: If the receiver contains at least one element of 0.0, * the harmonic mean is 0.0. * * @return the harmonic mean; Float.NaN if * !hasSumOfInversions(). * @see #hasSumOfInversions() */ public synchronized float harmonicMean() { return FloatDescriptive.harmonicMean(size(), sumOfInversions()); } /** * Returns whether sumOfInversions() can return meaningful results. * * @return false if the bin was constructed with insufficient * parametrization, true otherwise. See the constructors * for proper parametrization. */ public boolean hasSumOfInversions() { return this.hasSumOfInversions; } /** * Tells whether sumOfLogarithms() can return meaningful results. * * @return false if the bin was constructed with insufficient * parametrization, true otherwise. See the constructors * for proper parametrization. */ public boolean hasSumOfLogarithms() { return this.hasSumOfLogarithms; } /** * Tells whether sumOfPowers(k) can return meaningful results. * Defined as * hasSumOfPowers(k) <==> getMinOrderForSumOfPowers() <= k && k <= getMaxOrderForSumOfPowers() * . A return value of true implies that * hasSumOfPowers(k-1) .. hasSumOfPowers(0) will also return * true. See the constructors for proper parametrization. *

* Details: hasSumOfPowers(0..2) will always yield * true. hasSumOfPowers(-1) <==> hasSumOfInversions(). * * @return false if the bin was constructed with insufficient * parametrization, true otherwise. * @see #getMinOrderForSumOfPowers() * @see #getMaxOrderForSumOfPowers() */ public boolean hasSumOfPowers(int k) { return getMinOrderForSumOfPowers() <= k && k <= getMaxOrderForSumOfPowers(); } /** * Returns the kurtosis (aka excess), which is * -3 + moment(4,mean()) / standardDeviation()4. * * @return the kurtosis; Float.NaN if !hasSumOfPowers(4). * @see #hasSumOfPowers(int) */ public synchronized float kurtosis() { return FloatDescriptive.kurtosis(moment(4, mean()), standardDeviation()); } /** * Returns the moment of k-th order with value c, which is * Sum( (x[i]-c)k ) / size(). * * @param k * the order; must be greater than or equal to zero. * @param c * any number. * @throws IllegalArgumentException * if k < 0. * @return Float.NaN if !hasSumOfPower(k). */ public synchronized float moment(int k, float c) { if (k < 0) throw new IllegalArgumentException("k must be >= 0"); // checkOrder(k); if (!hasSumOfPowers(k)) return Float.NaN; int maxOrder = Math.min(k, getMaxOrderForSumOfPowers()); FloatArrayList sumOfPows = new FloatArrayList(maxOrder + 1); sumOfPows.add(size()); sumOfPows.add(sum()); sumOfPows.add(sumOfSquares()); for (int i = 3; i <= maxOrder; i++) sumOfPows.add(sumOfPowers(i)); return FloatDescriptive.moment(k, c, size(), sumOfPows.elements()); } /** * Returns the product, which is Prod( x[i] ). In other words: * x[0]*x[1]*...*x[size()-1]. * * @return the product; Float.NaN if !hasSumOfLogarithms() * . * @see #hasSumOfLogarithms() */ public float product() { return FloatDescriptive.product(size(), sumOfLogarithms()); } /** * Sets the range of orders in which sums of powers are to be computed. In * other words, sumOfPower(k) will return Sum( x[i]^k ) if * min_k <= k <= max_k || 0 <= k <= 2 and throw an exception * otherwise. * * @see #isLegalOrder(int) * @see #sumOfPowers(int) * @see #getRangeForSumOfPowers() */ protected void setMaxOrderForSumOfPowers(int max_k) { // if (max_k < ) throw new IllegalArgumentException(); if (max_k <= 2) { this.sumOfPowers = null; } else { this.sumOfPowers = new float[max_k - 2]; } } /** * Returns the skew, which is * moment(3,mean()) / standardDeviation()3. * * @return the skew; Float.NaN if !hasSumOfPowers(3). * @see #hasSumOfPowers(int) */ public synchronized float skew() { return FloatDescriptive.skew(moment(3, mean()), standardDeviation()); } /** * Returns the sum of inversions, which is Sum( 1 / x[i] ). * * @return the sum of inversions; Float.NaN if * !hasSumOfInversions(). * @see #hasSumOfInversions() */ public float sumOfInversions() { if (!this.hasSumOfInversions) return Float.NaN; // if (! this.hasSumOfInversions) throw new // IllegalOperationException("You must specify upon instance // construction that the sum of inversions shall be computed."); return this.sumOfInversions; } /** * Returns the sum of logarithms, which is Sum( Log(x[i]) ). * * @return the sum of logarithms; Float.NaN if * !hasSumOfLogarithms(). * @see #hasSumOfLogarithms() */ public synchronized float sumOfLogarithms() { if (!this.hasSumOfLogarithms) return Float.NaN; // if (! this.hasSumOfLogarithms) throw new // IllegalOperationException("You must specify upon instance // construction that the sum of logarithms shall be computed."); return this.sumOfLogarithms; } /** * Returns the k-th order sum of powers, which is * Sum( x[i]k ). * * @param k * the order of the powers. * @return the sum of powers; Float.NaN if * !hasSumOfPowers(k). * @see #hasSumOfPowers(int) */ public synchronized float sumOfPowers(int k) { if (!hasSumOfPowers(k)) return Float.NaN; // checkOrder(k); if (k == -1) return sumOfInversions(); if (k == 0) return size(); if (k == 1) return sum(); if (k == 2) return sumOfSquares(); return this.sumOfPowers[k - 3]; } /** * Returns a String representation of the receiver. */ public synchronized String toString() { StringBuffer buf = new StringBuffer(super.toString()); if (hasSumOfLogarithms()) { buf.append("Geometric mean: " + geometricMean()); buf.append("\nProduct: " + product() + "\n"); } if (hasSumOfInversions()) { buf.append("Harmonic mean: " + harmonicMean()); buf.append("\nSum of inversions: " + sumOfInversions() + "\n"); } int maxOrder = getMaxOrderForSumOfPowers(); int maxPrintOrder = Math.min(6, maxOrder); // don't print tons of // measures if (maxOrder > 2) { if (maxOrder >= 3) { buf.append("Skew: " + skew() + "\n"); } if (maxOrder >= 4) { buf.append("Kurtosis: " + kurtosis() + "\n"); } for (int i = 3; i <= maxPrintOrder; i++) { buf.append("Sum of powers(" + i + "): " + sumOfPowers(i) + "\n"); } for (int k = 0; k <= maxPrintOrder; k++) { buf.append("Moment(" + k + ",0): " + moment(k, 0) + "\n"); } for (int k = 0; k <= maxPrintOrder; k++) { buf.append("Moment(" + k + ",mean()): " + moment(k, mean()) + "\n"); } } return buf.toString(); } /** * @throws IllegalOperationException * if ! isLegalOrder(k). */ protected void xcheckOrder(int k) { // if (! isLegalOrder(k)) return Float.NaN; // if (! xisLegalOrder(k)) throw new IllegalOperationException("Illegal // order of sum of powers: k="+k+". Upon instance construction legal // range was fixed to be "+getMinOrderForSumOfPowers()+" <= k <= // "+getMaxOrderForSumOfPowers()); } /** * Returns whether two bins are equal; They are equal if the other object is * of the same class or a subclass of this class and both have the same * size, minimum, maximum, sum, sumOfSquares, sumOfInversions and * sumOfLogarithms. */ protected boolean xequals(Object object) { if (!(object instanceof MightyStaticFloatBin1D)) return false; MightyStaticFloatBin1D other = (MightyStaticFloatBin1D) object; return super.equals(other) && sumOfInversions() == other.sumOfInversions() && sumOfLogarithms() == other.sumOfLogarithms(); } /** * Tells whether sumOfPowers(fromK) .. sumOfPowers(toK) can return * meaningful results. * * @return false if the bin was constructed with insufficient * parametrization, true otherwise. See the constructors * for proper parametrization. * @throws IllegalArgumentException * if fromK > toK. */ protected boolean xhasSumOfPowers(int fromK, int toK) { if (fromK > toK) throw new IllegalArgumentException("fromK must be less or equal to toK"); return getMinOrderForSumOfPowers() <= fromK && toK <= getMaxOrderForSumOfPowers(); } /** * Returns * getMinOrderForSumOfPowers() <= k && k <= getMaxOrderForSumOfPowers() * . */ protected synchronized boolean xisLegalOrder(int k) { return getMinOrderForSumOfPowers() <= k && k <= getMaxOrderForSumOfPowers(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy