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

org.numenta.nupic.util.AbstractFlatMatrix Maven / Gradle / Ivy

/* ---------------------------------------------------------------------
 * Numenta Platform for Intelligent Computing (NuPIC)
 * Copyright (C) 2016, 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 java.io.Serializable;
import java.lang.reflect.Array;
import java.util.Arrays;

/**
 * Base class for flat {@link Matrix} implementations.
 * 
 * @author David Ray
 * @author Jose Luis Martin
 * 
 * @param  element type
 */
public abstract class AbstractFlatMatrix implements FlatMatrix, Serializable {
    /** keep it simple */
    private static final long serialVersionUID = 1L;

    protected int[] dimensions;
    protected int[] dimensionMultiples;
    protected boolean isColumnMajor;
    protected int numDimensions;

    /**
     * Constructs a new {@link AbstractFlatMatrix} object to be configured with specified
     * dimensions and major ordering.
     * @param dimensions  the dimensions of this matrix	
     */
    public AbstractFlatMatrix(int[] dimensions) {
        this(dimensions, false);
    }

    /**
     * Constructs a new {@link AbstractFlatMatrix} object to be configured with specified
     * dimensions and major ordering.
     * 
     * @param dimensions				the dimensions of this sparse array	
     * @param useColumnMajorOrdering	flag indicating whether to use column ordering or
     * 									row major ordering. if false (the default), then row
     * 									major ordering will be used. If true, then column major
     * 									ordering will be used.
     */
    public AbstractFlatMatrix(int[] dimensions, boolean useColumnMajorOrdering) {
        this.dimensions = dimensions;
        this.numDimensions = dimensions.length;
        this.dimensionMultiples = initDimensionMultiples(
                useColumnMajorOrdering ? reverse(dimensions) : dimensions);
        isColumnMajor = useColumnMajorOrdering;
    }

    /**
     * Compute the flat index of a multidimensional array.
     * @param indexes multidimensional indexes
     * @return the flat array index;
     */
    public int computeIndex(int[] indexes) {
        return computeIndex(indexes, true);
    }

    /**
     * Returns a flat index computed from the specified coordinates
     * which represent a "dimensioned" index.
     * 
     * @param   coordinates     an array of coordinates
     * @param   doCheck         enforce validated comparison to locally stored dimensions
     * @return  a flat index
     */
    public int computeIndex(int[] coordinates, boolean doCheck) {
        if(doCheck) checkDims(coordinates);

        int[] localMults = isColumnMajor ? reverse(dimensionMultiples) : dimensionMultiples;
        int base = 0;
        for(int i = 0;i < coordinates.length;i++) {
            base += (localMults[i] * coordinates[i]);
        }
        return base;
    }

    /**
     * Checks the indexes specified to see whether they are within the
     * configured bounds and size parameters of this array configuration.
     * 
     * @param index the array dimensions to check
     */
    protected void checkDims(int[] index) {
        if(index.length != numDimensions) {
            throw new IllegalArgumentException("Specified coordinates exceed the configured array dimensions " +
                    "input dimensions: " + index.length + " > number of configured dimensions: " + numDimensions);
        }
        for(int i = 0;i < index.length - 1;i++) {
            if(index[i] >= dimensions[i]) {
                throw new IllegalArgumentException("Specified coordinates exceed the configured array dimensions " +
                        print1DArray(index) + " > " + print1DArray(dimensions));
            }
        }
    }

    /**
     * Returns an array of coordinates calculated from
     * a flat index.
     * 
     * @param   index   specified flat index
     * @return  a coordinate array
     */
    @Override
    public int[] computeCoordinates(int index) {
        int[] returnVal = new int[getNumDimensions()];
        int base = index;
        for(int i = 0;i < dimensionMultiples.length; i++) {
            int quotient = base / dimensionMultiples[i];
            base %= dimensionMultiples[i];
            returnVal[i] = quotient;
        }
        return isColumnMajor ? reverse(returnVal) : returnVal;
    }

    /**
     * Initializes internal helper array which is used for multidimensional
     * index computation.
     * @param dimensions matrix dimensions
     * @return array for use in coordinates to flat index computation.
     */
    protected int[] initDimensionMultiples(int[] dimensions) {
        int holder = 1;
        int len = dimensions.length;
        int[] dimensionMultiples = new int[getNumDimensions()];
        for(int i = 0;i < len;i++) {
            holder *= (i == 0 ? 1 : dimensions[len - i]);
            dimensionMultiples[len - 1 - i] = holder;
        }
        return dimensionMultiples;
    }

    /**
     * Utility method to shrink a single dimension array by one index.
     * @param array the array to shrink
     * @return
     */
    protected int[] copyInnerArray(int[] array) {
        if(array.length == 1) return array;

        int[] retVal = new int[array.length - 1];
        System.arraycopy(array, 1, retVal, 0, array.length - 1);
        return retVal;
    }

    /**
     * Reverses the specified array.
     * @param input
     * @return
     */
    public static int[] reverse(int[] input) {
        int[] retVal = new int[input.length];
        for(int i = input.length - 1, j = 0;i >= 0;i--, j++) {
            retVal[j] = input[i];
        }
        return retVal;
    }

    /**
     * Prints the specified array to a returned String.
     * 
     * @param aObject   the array object to print.
     * @return  the array in string form suitable for display.
     */
    public static String print1DArray(Object aObject) {
        if (aObject.getClass().isArray()) {
            if (aObject instanceof Object[]) // can we cast to Object[]
                return Arrays.toString((Object[]) aObject);
            else {  // we can't cast to Object[] - case of primitive arrays
                int length = Array.getLength(aObject);
                Object[] objArr = new Object[length];
                for (int i=0; i set(int index, T value);

    @Override
    public T get(int... indexes) {
        return get(computeIndex(indexes));
    }

    @Override
    public AbstractFlatMatrix set(int[] indexes, T value) {
        set(computeIndex(indexes), value); 
        return this;
    }

    public int getSize() {
        return Arrays.stream(this.dimensions).reduce((n,i) -> n*i).getAsInt();
    }

    @Override
    public int getMaxIndex() {
        return getDimensions()[0] * Math.max(1, getDimensionMultiples()[0]) - 1;
    }

    @Override
    public int[] getDimensions() {
        return this.dimensions;
    }

    public void setDimensions(int[] dimensions) {
        this.dimensions = dimensions;
    }

    @Override
    public int getNumDimensions() {
        return this.dimensions.length;
    }

    @Override
    public int[] getDimensionMultiples() {
        return this.dimensionMultiples;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + Arrays.hashCode(dimensionMultiples);
        result = prime * result + Arrays.hashCode(dimensions);
        result = prime * result + (isColumnMajor ? 1231 : 1237);
        result = prime * result + numDimensions;
        return result;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @SuppressWarnings("rawtypes")
    @Override
    public boolean equals(Object obj) {
        if(this == obj)
            return true;
        if(obj == null)
            return false;
        if(getClass() != obj.getClass())
            return false;
        AbstractFlatMatrix other = (AbstractFlatMatrix)obj;
        if(!Arrays.equals(dimensionMultiples, other.dimensionMultiples))
            return false;
        if(!Arrays.equals(dimensions, other.dimensions))
            return false;
        if(isColumnMajor != other.isColumnMajor)
            return false;
        if(numDimensions != other.numDimensions)
            return false;
        return true;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy