/**
* Copyright (C) 2001-2017 by RapidMiner and the contributors
*
* Complete list of developers available at our web site:
*
* http://rapidminer.com
*
* 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/.
*/
package com.rapidminer.tools.container;
/**
* This class represents a multidimensional array whose dimensions have to be specified during
* construction. The multidimensional array is modeled by an underlying single dimension array.
*
* @author Tobias Malbrecht
*
* @param <E>
* the class of the array elements
*/
public class MultidimensionalArraySet<E> {
/** The underlying single dimension array. */
private E[] array;
// /**
// * The dimensions of the multidimensional array.
// */
// private int[] dimensions;
/**
* The number of combinations that is possible with specifying the last following attributes.
* These are used for computing the single array index from multidimensional indices.
*/
private int[] combinations;
/**
* The constructor.
*
* @param dimensions
* int array which contains the size of each dimension
*/
@SuppressWarnings("unchecked")
public MultidimensionalArraySet(int[] dimensions) {
// this.dimensions = dimensions;
int splits = dimensions.length;
int numberOfCombinations = 1;
combinations = new int[splits];
for (int i = splits - 1; i > 0; i--) {
numberOfCombinations *= dimensions[i];
combinations[i - 1] = numberOfCombinations;
}
numberOfCombinations *= dimensions[0];
combinations[splits - 1] = 1;
array = (E[]) new Object[numberOfCombinations];
}
/**
* Returns the array element at the specified single dimension array position.
*
* @param index
* the index
* @return an element
*/
public E get(int index) {
return array[index];
}
/**
* Returns the array element at the position specified by the given indices.
*
* @param indices
* the indices
* @return an element
*/
public E get(int[] indices) {
return array[getIndex(indices)];
}
/**
* Sets the array element at the specified single dimension array position.
*
* @param index
* the index
* @param e
* an element
*/
public void set(int index, E e) {
array[index] = e;
}
/**
* Sets the array element at the position specified by the given indices
*
* @param indices
* the indices
* @param e
* an element
*/
public void set(int[] indices, E e) {
array[getIndex(indices)] = e;
}
/**
* Computes the single dimension array index from the given multidimensional indices.
*
* @param indices
* the indices
* @return the corresponding index
*/
private int getIndex(int[] indices) {
return sumProduct(indices, combinations);
}
/**
* Computes the multidimensional indices corresponding to a single dimension array index.
*
* @param index
* the index
* @return the corresponding indices
*/
public int[] getIndices(int index) {
int[] indices = new int[combinations.length];
int r = index;
for (int i = 0; i < indices.length; i++) {
indices[i] = r / combinations[i];
r = r % combinations[i];
}
return indices;
}
/**
* Returns the number of elements this array can hold.
*
* @return size
*/
public int size() {
return array.length;
}
// /**
// * Returns an int array holding the dimensions of the
// * multidimensional array.
// *
// * @return dimensions
// */
// public int[] getDimensions() {
// return dimensions;
// }
/**
* Calculates the sum product of two int arrays. Used for the calculation of a single dimension
* array index from multidimensional indices.
*/
private int sumProduct(int[] firstIndices, int[] secondIndices) {
int firstLength = firstIndices.length;
int secondLength = secondIndices.length;
int length = secondLength > firstLength ? firstLength : secondLength;
int product = 0;
for (int i = 0; i < length; i++) {
product += firstIndices[i] * secondIndices[i];
}
return product;
}
}