/* --------------------------------------------------------------------- * Numenta Platform for Intelligent Computing (NuPIC) * Copyright (C) 2014, Numenta, Inc. Unless you have an agreement * with Numenta, Inc., for a separate license for this software code, the * following terms and conditions apply: * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as * published by the Free Software Foundation. * * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses. * * http://numenta.org/licenses/ * --------------------------------------------------------------------- */ package org.numenta.nupic.util; import gnu.trove.list.TIntList; import gnu.trove.list.array.TIntArrayList; import java.io.Serializable; import java.lang.reflect.Array; /** * Allows storage of array data in sparse form, meaning that the indexes * of the data stored are maintained while empty indexes are not. This allows * savings in memory and computational efficiency because iterative algorithms * need only query indexes containing valid data. The dimensions of matrix defined * at construction time and immutable - matrix fixed size data structure. * * @author David Ray * @author Jose Luis Martin * * @param <T> */ public abstract class AbstractSparseMatrix<T> extends AbstractFlatMatrix<T> implements SparseMatrix<T>, Serializable { /** keep it simple */ private static final long serialVersionUID = 1L; /** * Constructs a new {@code AbstractSparseMatrix} with the specified * dimensions (defaults to row major ordering) * * @param dimensions each indexed value is a dimension size */ public AbstractSparseMatrix(int[] dimensions) { this(dimensions, false); } /** * Constructs a new {@code AbstractSparseMatrix} with the specified dimensions, * allowing the specification of column major ordering if desired. * (defaults to row major ordering) * * @param dimensions each indexed value is a dimension size * @param useColumnMajorOrdering if true, indicates column first iteration, otherwise * row first iteration is the default (if false). */ public AbstractSparseMatrix(int[] dimensions, boolean useColumnMajorOrdering) { super(dimensions, useColumnMajorOrdering); } /** * Sets the object to occupy the specified index. * * @param index the index the object will occupy * @param value the value to be indexed. * * @return this {@code SparseMatrix} implementation */ protected <S extends AbstractSparseMatrix<T>> S set(int index, int value) { return null; } /** * Sets the object to occupy the specified index. * * @param index the index the object will occupy * @param value the value to be indexed. * * @return this {@code SparseMatrix} implementation */ protected <S extends AbstractSparseMatrix<T>> S set(int index, double value) { return null; } /** * Sets the specified object to be indexed at the index * computed from the specified coordinates. * @param object the object to be indexed. * @param coordinates the row major coordinates [outer --> ,...,..., inner] * * @return this {@code SparseMatrix} implementation */ @Override public AbstractSparseMatrix<T> set(int[] coordinates, T object) { return null; } /** * Sets the specified object to be indexed at the index * computed from the specified coordinates. * @param value the value to be indexed. * @param coordinates the row major coordinates [outer --> ,...,..., inner] * * @return this {@code SparseMatrix} implementation */ protected <S extends AbstractSparseMatrix<T>> S set(int value, int... coordinates) { return null; } /** * Sets the specified object to be indexed at the index * computed from the specified coordinates. * @param value the value to be indexed. * @param coordinates the row major coordinates [outer --> ,...,..., inner] * * @return this {@code SparseMatrix} implementation */ protected <S extends AbstractSparseMatrix<T>> S set(double value, int... coordinates) { return null; } /** * Returns the T at the specified index. * * @param index the index of the T to return * @return the T at the specified index. */ protected T getObject(int index) { return null; } /** * Returns the T at the specified index. * * @param index the index of the T to return * @return the T at the specified index. */ protected int getIntValue(int index) { return -1; } /** * Returns the T at the specified index. * * @param index the index of the T to return * @return the T at the specified index. */ protected double getDoubleValue(int index) { return -1.0; } /** * Returns the T at the index computed from the specified coordinates * @param coordinates the coordinates from which to retrieve the indexed object * @return the indexed object */ public T get(int... coordinates) { return null; } /** * Returns the int value at the index computed from the specified coordinates * @param coordinates the coordinates from which to retrieve the indexed object * @return the indexed object */ protected int getIntValue(int... coordinates) { return -1; } /** * Returns the double value at the index computed from the specified coordinates * @param coordinates the coordinates from which to retrieve the indexed object * @return the indexed object */ protected double getDoubleValue(int... coordinates) { return -1.0; } @Override public int[] getSparseIndices() { return null; } @Override public int[] get1DIndexes() { TIntList results = new TIntArrayList(getMaxIndex() + 1); visit(getDimensions(), 0, new int[getNumDimensions()], results); return results.toArray(); } /** * Recursively loops through the matrix dimensions to fill the results * array with flattened computed array indexes. * * @param bounds * @param currentDimension * @param p * @param results */ private void visit(int[] bounds, int currentDimension, int[] p, TIntList results) { for (int i = 0; i < bounds[currentDimension]; i++) { p[currentDimension] = i; if (currentDimension == p.length - 1) { results.add(computeIndex(p)); } else visit(bounds, currentDimension + 1, p, results); } } @Override @SuppressWarnings("unchecked") public T[] asDense(TypeFactory<T> factory) { int[] dimensions = getDimensions(); T[] retVal = (T[])Array.newInstance(factory.typeClass(), dimensions); fill(factory, 0, dimensions, dimensions[0], retVal); return retVal; } /** * Uses reflection to create and fill a dynamically created multidimensional array. * * @param f the {@link TypeFactory} * @param dimensionIndex the current index into <em>this class's</em> configured dimensions array * <em>*NOT*</em> the dimensions used as this method's argument * @param dimensions the array specifying remaining dimensions to create * @param count the current dimensional size * @param arr the array to fill * @return a dynamically created multidimensional array */ @SuppressWarnings("unchecked") protected Object[] fill(TypeFactory<T> f, int dimensionIndex, int[] dimensions, int count, Object[] arr) { if(dimensions.length == 1) { for(int i = 0;i < count;i++) { arr[i] = f.make(getDimensions()); } return arr; }else{ for(int i = 0;i < count;i++) { int[] inner = copyInnerArray(dimensions); T[] r = (T[])Array.newInstance(f.typeClass(), inner); arr[i] = fill(f, dimensionIndex + 1, inner, getDimensions()[dimensionIndex + 1], r); } return arr; } } }