diff options
Diffstat (limited to 'elki/src/main/java/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/AbstractStaticHistogram.java')
-rw-r--r-- | elki/src/main/java/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/AbstractStaticHistogram.java | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/AbstractStaticHistogram.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/AbstractStaticHistogram.java new file mode 100644 index 00000000..b0728ddb --- /dev/null +++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/AbstractStaticHistogram.java @@ -0,0 +1,224 @@ +package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2015 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +/** + * Abstract base class for histograms. + * + * Note that this is abstracted from the actual data storage, so it can be + * adapted for multiple use cases. + * + * @author Erich Schubert + */ +public abstract class AbstractStaticHistogram implements Histogram { + /** + * Array shift to account for negative indices. + */ + protected int offset = 0; + + /** + * Size of array storage. + */ + protected int size; + + /** + * Array 'base', i.e. the point of 0.0. Usually the minimum. + */ + protected double base; + + /** + * To avoid introducing an extra bucket for the maximum value. + */ + protected double max; + + /** + * Width of a bin. + */ + protected double binsize; + + /** + * Histogram constructor + * + * @param bins Number of bins to use. + * @param min Minimum Value + * @param max Maximum Value + */ + public AbstractStaticHistogram(int bins, double min, double max) { + this.base = min; + this.max = max; + this.binsize = (max - min) / bins; + this.size = bins; + } + + /** + * Compute the bin number. Has a special case for rounding max down to the + * last bin. + * + * @param coord Coordinate + * @return bin number + */ + protected int getBinNr(double coord) { + if (Double.isInfinite(coord) || Double.isNaN(coord)) { + throw new UnsupportedOperationException("Encountered non-finite value in Histogram: " + coord); + } + if (coord == max) { + // System.err.println("Triggered special case: "+ (Math.floor((coord - + // base) / binsize) + offset) + " vs. " + (size - 1)); + return size - 1; + } + return (int) Math.floor((coord - base) / binsize) + offset; + } + + /** + * Compute the size to grow to. + * + * @param current Current size + * @param requiredSize Required size + * @return Size to allocate + */ + protected static int growSize(int current, int requiredSize) { + // Double until 64, then increase by 50% each time. + int newCapacity = ((current < 64) ? ((current + 1) << 1) : ((current >> 1) * 3)); + // overflow? + if (newCapacity < 0) { + throw new OutOfMemoryError(); + } + if (requiredSize > newCapacity) { + newCapacity = requiredSize; + } + return requiredSize; + } + + /** + * Get the number of bins actually in use. + * + * @return number of bins + */ + @Override + public int getNumBins() { + return size; + } + + /** + * Get the size (width) of a bin. + * + * @return bin size + */ + @Override + public double getBinsize() { + return binsize; + } + + /** + * Get minimum (covered by bins, not data!) + * + * @return minimum + */ + @Override + public double getCoverMinimum() { + return base - offset * binsize; + } + + /** + * Get maximum (covered by bins, not data!) + * + * @return maximum + */ + @Override + public double getCoverMaximum() { + return base + (size - offset) * binsize; + } + + /** + * Get an iterator over all histogram bins. + * + * @return Iterator + */ + @Override + public abstract Iter iter(); + + /** + * Iterator class to iterate over all bins. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public abstract class Iter implements Histogram.Iter { + /** + * Current bin number + */ + int bin = 0; + + @Override + public double getCenter() { + return base + (bin + 0.5 - offset) * binsize; + } + + @Override + public double getLeft() { + return base + (bin - offset) * binsize; + } + + @Override + public double getRight() { + return base + (bin + 1 - offset) * binsize; + } + + @Override + public boolean valid() { + return bin >= 0 && bin < size; + } + + @Override + public Iter advance() { + bin++; + return this; + } + + @Override + public int getOffset() { + return bin; + } + + @Override + public Iter advance(int count) { + bin += count; + return this; + } + + @Override + public Iter retract() { + bin--; + return this; + } + + @Override + public Iter seek(int off) { + bin = off; + return this; + } + } +} |