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

org.integratedmodelling.collections.MultidimensionalArray Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 *  Copyright (C) 2007, 2014:
 *  
 *    - Ferdinando Villa 
 *    - integratedmodelling.org
 *    - any other authors listed in @author annotations
 *
 *    All rights reserved. This file is part of the k.LAB software suite,
 *    meant to enable modular, collaborative, integrated 
 *    development of interoperable data and model components. For
 *    details, see http://integratedmodelling.org.
 *    
 *    This program is free software; you can redistribute it and/or
 *    modify it under the terms of the Affero General Public License 
 *    Version 3 or 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
 *    Affero General Public License for more details.
 *  
 *     You should have received a copy of the Affero General Public License
 *     along with this program; if not, write to the Free Software
 *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *     The license is also available at: https://www.gnu.org/licenses/agpl.html
 *******************************************************************************/
package org.integratedmodelling.collections;

import java.util.ArrayList;
import java.util.Iterator;

public class MultidimensionalArray {

    private ArrayList   storage = new ArrayList();
    MultidimensionalCursor cursor;

    /**
     * Aggregators are supplied to the multidimensional iterator when a dimension must be collapsed
     * to size 1.
     * 
     * @author Ferdinando
     *
     * @param 
     */
    public interface Aggregator {

        public abstract void reset();

        public abstract void add(T value);

        public abstract T getAggregatedValue();
    }

    public class MultidimensionalIterator implements Iterator {

        int step;
        int current;

        ArrayList storage;

        @Override
        public boolean hasNext() {
            return (current + step) < storage.size();
        }

        @Override
        public T next() {
            current += step;
            return current < storage.size() ? storage.get(current) : null;
        }

        @Override
        public void remove() {
            storage.remove(current);
        }

        protected MultidimensionalIterator(int offset, int step, int current, ArrayList data) {
            this.current = offset + current;
            this.step = step;
            storage = data;
        }
    }

    /**
     * Return an iterator over the whole array, regardless of internal structuring. Note
     * that the storage order is Fortran-like.
     * @return iterator
     */
    public Iterator iterator() {
        return storage.iterator();
    }

    /**
     * Return an iterator over a slice along the indicated dimension, with all other dimension
     * offsets identified by the specified remaining ones. Note that the offsets passed must
     * contain the exact number of dimensions, and the offsets paired to the actual dimension. The
     * offset for the dimension of interest is ignored.
     * @param dimension
     * @param offsets
     * @return iterator
     */
    public MultidimensionalIterator iterator(int dimension, int... offsets) {

        Triple stride = cursor.getStridedOffsets(dimension, offsets);

        return new MultidimensionalIterator(stride.getFirst(), 0, stride.getThird(), storage);
    }

    /**
     * This constructor is fairly expensive for large arrays as it preallocates the whole
     * structure. The bad news is that there is no other constructor.
     * @param dimensions
     */
    public MultidimensionalArray(int... dimensions) {

        cursor = new MultidimensionalCursor(MultidimensionalCursor.StorageOrdering.ROW_FIRST);
        cursor.defineDimensions(dimensions);
        storage.ensureCapacity(cursor.getMultiplicity());
    }

    public T get(int... indexes) {
        return storage.get(cursor.getElementOffset(indexes));
    }

    public int size() {
        return cursor.multiplicity;
    }

    public void set(int i, T value) {
        storage.add(i, value);
    }

    /**
     * Create a new array where the indicated dimension has been collapsed to size 1 and
     * its values have been aggregated using the supplied aggregator.
     * 
     * @param dimensionIndex
     * @param aggregator
     * @return collapsed array
     */
    public MultidimensionalArray collapse(int dimensionIndex, Aggregator aggregator) {

        int[] dims = cursor.getExtents();
        dims[dimensionIndex] = 1;

        MultidimensionalArray ret = new MultidimensionalArray(dims);

        for (int i = 0; i < ret.size(); i++) {

            aggregator.reset();

            /*
             * each value substituted by the aggregation of the other's data along the collapsed dimension
             */
            for (Iterator it = this.iterator(dimensionIndex, this.cursor.getElementIndexes(i)); it
                    .hasNext();)
                aggregator.add(it.next());

            ret.set(i, aggregator.getAggregatedValue());
        }

        return ret;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy