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) 2013 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 . */ /** * Histogram class storing double values. * * The histogram will start with "bin" bins, but it can grow dynamicall to the * left and right. * * @author Erich Schubert * * @param Data type */ public abstract class AbstractObjStaticHistogram extends AbstractStaticHistogram implements ObjHistogram { /** * Data store */ Object[] data; /** * Special value storage: infinity, NaN */ Object[] special = null; /** * Constructor. * * @param bins Number of bins * @param min Cover minimum * @param max Cover maximum */ public AbstractObjStaticHistogram(int bins, double min, double max) { super(bins, min, max); if (bins >= 0) { // -1 will be used by FlexiHistogram to delay initialization. data = new Object[bins]; for (int i = 0; i < bins; i++) { data[i] = makeObject(); } } } /** * Access the value of a bin with new data. * * @param coord Coordinate * @return bin contents */ @SuppressWarnings("unchecked") public T get(double coord) { if (coord == Double.NEGATIVE_INFINITY) { return getSpecial(0); } if (coord == Double.POSITIVE_INFINITY) { return getSpecial(1); } if (Double.isNaN(coord)) { return getSpecial(2); } int bin = getBinNr(coord); if (bin < 0) { if (size - bin > data.length) { // Reallocate. TODO: use an arraylist-like grow strategy! Object[] tmpdata = new Object[growSize(data.length, size - bin)]; System.arraycopy(data, 0, tmpdata, -bin, size); data = tmpdata; } else { // Shift in place System.arraycopy(data, 0, data, -bin, size); } for (int i = 0; i < -bin; i++) { data[i] = makeObject(); } // Note that bin is negative, -bin is the shift offset! offset -= bin; size -= bin; // TODO: modCounter++; and have iterators fast-fail // Unset max value when resizing max = Double.MAX_VALUE; return (T) data[0]; } else if (bin >= size) { if (bin >= data.length) { Object[] tmpdata = new Object[growSize(data.length, bin + 1)]; System.arraycopy(data, 0, tmpdata, 0, size); data = tmpdata; } for (int i = size; i <= bin; i++) { data[i] = makeObject(); } size = bin + 1; // TODO: modCounter++; and have iterators fast-fail // Unset max value when resizing max = Double.MAX_VALUE; return (T) data[bin]; } else { return (T) data[bin]; } } /** * Ensure that we have storage for special values (infinity, NaN) * * @param idx Index to return. */ @SuppressWarnings("unchecked") protected T getSpecial(int idx) { if (special == null) { special = new Object[] { makeObject(), makeObject(), makeObject() }; } return (T) special[idx]; } /** * Class to make a new object for the data store. * * @return New instance. */ protected abstract T makeObject(); @Override public Iter iter() { return new Iter(); } /** * Iterator class. * * @author Erich Schubert */ public class Iter extends AbstractStaticHistogram.Iter implements ObjHistogram.Iter { @SuppressWarnings("unchecked") @Override public T getValue() { return (T) data[bin]; } } }