Difference between revisions of "User:Chase-san/VDA"

From Robowiki
Jump to navigation Jump to search
m (minor fix)
m (reformatting)
Line 13: Line 13:
 
  *  
 
  *  
 
  * @author Chase
 
  * @author Chase
  *
+
  *  
  * @param <T> Type of data contained
+
  * @param <T>
 +
*            Type of data contained
 
  */
 
  */
 
public class VDA<T> implements Serializable, Cloneable {
 
public class VDA<T> implements Serializable, Cloneable {
 
private static final long serialVersionUID = 3816532930303382063L;
 
private static final long serialVersionUID = 3816532930303382063L;
+
 
 
private T[] data = null;
 
private T[] data = null;
 
private int[] dims = null;
 
private int[] dims = null;
 
private boolean constructed = false;
 
private boolean constructed = false;
+
 
 
/**
 
/**
 
* Initializes the VDA with 0 dimensions.
 
* Initializes the VDA with 0 dimensions.
Line 29: Line 30:
 
dims = new int[0];
 
dims = new int[0];
 
}
 
}
+
 
 
/**
 
/**
 
* Initializes the VDA with the given number of dimensions
 
* Initializes the VDA with the given number of dimensions
 +
*
 
* @param dimensions
 
* @param dimensions
 
*/
 
*/
public VDA(int ... dimensions) {
+
public VDA(int... dimensions) {
 
if(dimensions == null)
 
if(dimensions == null)
 
throw new NullPointerException();
 
throw new NullPointerException();
 
dims = (int[])dimensions.clone();
 
dims = (int[])dimensions.clone();
 
}
 
}
+
 
 
/**
 
/**
* @param size Must be at least 2
+
* @param size
 +
*            Must be at least 2
 
*/
 
*/
 
public void add(int size) {
 
public void add(int size) {
 
if(size < 2)
 
if(size < 2)
 
throw new IllegalArgumentException("Dimension size must be at least 2.");
 
throw new IllegalArgumentException("Dimension size must be at least 2.");
dims = Arrays.copyOf(dims, dims.length+1);
+
dims = Arrays.copyOf(dims, dims.length + 1);
dims[dims.length-1] = size;
+
dims[dims.length - 1] = size;
 
constructed = false;
 
constructed = false;
 
}
 
}
+
 
 
/**
 
/**
* @param index Must be between 0 and number of dimensions
+
* @param index
 +
*            Must be between 0 and number of dimensions
 
*/
 
*/
 
public void remove(int index) {
 
public void remove(int index) {
Line 58: Line 62:
 
throw new IndexOutOfBoundsException();
 
throw new IndexOutOfBoundsException();
 
int[] tmp = dims;
 
int[] tmp = dims;
dims = Arrays.copyOf(dims, dims.length-1);
+
dims = Arrays.copyOf(dims, dims.length - 1);
 
if(index < dims.length) {
 
if(index < dims.length) {
System.arraycopy(tmp, index+1, dims, index, dims.length - index);
+
System.arraycopy(tmp, index + 1, dims, index, dims.length - index);
 
}
 
}
 
constructed = false;
 
constructed = false;
 
}
 
}
+
 
 
/**
 
/**
 
* Get the value at the given dimension
 
* Get the value at the given dimension
 
*/
 
*/
public T get(int ... pos) {
+
public T get(int... pos) {
 
if(pos == null)
 
if(pos == null)
 
throw new NullPointerException();
 
throw new NullPointerException();
 
if(dims.length == 0 || pos.length != dims.length)
 
if(dims.length == 0 || pos.length != dims.length)
 
throw new IllegalArgumentException("Incorrect or Bad Dimensionality.");
 
throw new IllegalArgumentException("Incorrect or Bad Dimensionality.");
if(!constructed) construct();
+
if(!constructed)
 +
construct();
 
return data[getIndex(pos)];
 
return data[getIndex(pos)];
 
}
 
}
+
 
 
/**
 
/**
 
* Set the value at the given dimension
 
* Set the value at the given dimension
 
*/
 
*/
public void set(T value, int ... pos) {
+
public void set(T value, int... pos) {
 
if(pos == null)
 
if(pos == null)
 
throw new NullPointerException();
 
throw new NullPointerException();
 
if(dims.length == 0 || pos.length != dims.length)
 
if(dims.length == 0 || pos.length != dims.length)
 
throw new IllegalArgumentException("Incorrect or Bad Dimensionality.");
 
throw new IllegalArgumentException("Incorrect or Bad Dimensionality.");
if(!constructed) construct();
+
if(!constructed)
 +
construct();
 
data[getIndex(pos)] = value;
 
data[getIndex(pos)] = value;
 
}
 
}
+
 
 
 
/**
 
/**
 
* Returns the bottom array at the given position
 
* Returns the bottom array at the given position
 
*/
 
*/
public Object[] getSubArray(int ... pos) {
+
public Object[] getSubArray(int... pos) {
 
if(pos.length != dims.length - 1)
 
if(pos.length != dims.length - 1)
throw new UnsupportedOperationException(
+
throw new UnsupportedOperationException("Dimensionality must be one less than the total supported.");
"Dimensionality must be one less than the total supported.");
+
if(!constructed)
if(!constructed) construct();
+
construct();
 
int start = getIndex(pos);
 
int start = getIndex(pos);
int length = dims[dims.length-1];
+
int length = dims[dims.length - 1];
 
T[] output = createArray(length);
 
T[] output = createArray(length);
 
System.arraycopy(data, start, output, 0, length);
 
System.arraycopy(data, start, output, 0, length);
 
return output;
 
return output;
 
}
 
}
+
 
 
/**
 
/**
 
* Sets the bottom array at the given position
 
* Sets the bottom array at the given position
 
*/
 
*/
public void setSubArray(T[] array, int ... pos) {
+
public void setSubArray(T[] array, int... pos) {
 
if(pos.length != dims.length - 1)
 
if(pos.length != dims.length - 1)
throw new UnsupportedOperationException(
+
throw new UnsupportedOperationException("Dimensionality must be one less than the total supported.");
"Dimensionality must be one less than the total supported.");
+
if(!constructed)
if(!constructed) construct();
+
construct();
 
int start = getIndex(pos);
 
int start = getIndex(pos);
int length = Math.min(dims[dims.length-1], array.length);
+
int length = Math.min(dims[dims.length - 1], array.length);
 
System.arraycopy(array, 0, data, start, length);
 
System.arraycopy(array, 0, data, start, length);
 
}
 
}
+
 
 
/**
 
/**
 
* @return the array that backs this VDA
 
* @return the array that backs this VDA
 
*/
 
*/
 
public Object[] getBackingArray() {
 
public Object[] getBackingArray() {
if(!constructed) construct();
+
if(!constructed)
 +
construct();
 
return data;
 
return data;
 
}
 
}
+
 
 
/**
 
/**
 
* Returns an array containing all of the elements in this VDA
 
* Returns an array containing all of the elements in this VDA
 
*/
 
*/
 
public Object[] toArray() {
 
public Object[] toArray() {
if(!constructed) construct();
+
if(!constructed)
 +
construct();
 
return data.clone();
 
return data.clone();
 
}
 
}
+
 
 
/**
 
/**
 
* Returns an array containing all of the elements in this VDA
 
* Returns an array containing all of the elements in this VDA
 
*/
 
*/
    @SuppressWarnings("unchecked")
+
@SuppressWarnings("unchecked")
 
public T[] toArray(T[] a) {
 
public T[] toArray(T[] a) {
    if(!constructed) construct();
+
if(!constructed)
    return (T[])Arrays.copyOf(data, data.length, a.getClass());
+
construct();
    }
+
return (T[])Arrays.copyOf(data, data.length, a.getClass());
+
}
 +
 
 
/**
 
/**
* Sets this VDA to be equal to the given VDA. Data and dimensions are copied.
+
* Sets this VDA to be equal to the given VDA. Data and dimensions are
 +
* copied.
 
*/
 
*/
 
public void set(VDA<T> vda) {
 
public void set(VDA<T> vda) {
Line 151: Line 160:
 
constructed = vda.constructed;
 
constructed = vda.constructed;
 
}
 
}
+
 
 
/**
 
/**
 
* Returns a shallow copy of this VDA (dimensions but not data)
 
* Returns a shallow copy of this VDA (dimensions but not data)
Line 158: Line 167:
 
return new VDA<T>(dims);
 
return new VDA<T>(dims);
 
}
 
}
+
 
 
/**
 
/**
 
* Creates the final data array
 
* Creates the final data array
Line 164: Line 173:
 
private void construct() {
 
private void construct() {
 
Integer size = 1;
 
Integer size = 1;
for(Integer i : dims) size *= i;
+
for(Integer i : dims)
 +
size *= i;
 
data = createArray(size);
 
data = createArray(size);
 
constructed = true;
 
constructed = true;
 
}
 
}
+
 
 
@SuppressWarnings("unchecked")
 
@SuppressWarnings("unchecked")
 
private T[] createArray(int size) {
 
private T[] createArray(int size) {
//Warning: Dangerous
+
// Warning: Dangerous
 
return (T[])new Object[size];
 
return (T[])new Object[size];
 
}
 
}
+
 
 
/**
 
/**
 
* Gets the main arrays index from pos
 
* Gets the main arrays index from pos
Line 180: Line 190:
 
private int getIndex(int[] pos) {
 
private int getIndex(int[] pos) {
 
Integer index = 0;
 
Integer index = 0;
for(int i=0; i<pos.length; ++i) {
+
for(int i = 0; i < pos.length; ++i) {
 
if(pos[i] < 0 || pos[i] >= dims[i])
 
if(pos[i] < 0 || pos[i] >= dims[i])
throw new IndexOutOfBoundsException(
+
throw new IndexOutOfBoundsException("Index " + pos[i] + " is out of bounds for dimension " + i + ".");
"Index " + pos[i] + " is out of bounds for dimension " + i + ".");
+
 
+
index += sizeUnder(i) * pos[i];
index += sizeUnder(i)*pos[i];
 
 
}
 
}
 
System.out.println("Index " + index);
 
System.out.println("Index " + index);
 
return index;
 
return index;
 
}
 
}
 +
 
/**
 
/**
 
* Gets the number of elements under the given level
 
* Gets the number of elements under the given level
Line 195: Line 205:
 
private int sizeUnder(int level) {
 
private int sizeUnder(int level) {
 
Integer size = 1;
 
Integer size = 1;
for(int i=level+1; i<dims.length; ++i) {
+
for(int i = level + 1; i < dims.length; ++i) {
 
size *= dims[i];
 
size *= dims[i];
 
}
 
}

Revision as of 02:35, 1 July 2010

A variable dimension array I wrote up trying to figure out a way I could have a variable number of segment buffers without having to know how many I had in advance. It turned out pretty well!

package org.csdgn.utils;

import java.io.Serializable;
import java.util.Arrays;

/**
 * Variable Dimension Array, an array class with flexible dimensionality.
 * 
 * Just remember (int ... x) means it accepts (0,0,0) and new int[]{0,0,0}.
 * 
 * @author Chase
 * 
 * @param <T>
 *            Type of data contained
 */
public class VDA<T> implements Serializable, Cloneable {
	private static final long serialVersionUID = 3816532930303382063L;

	private T[] data = null;
	private int[] dims = null;
	private boolean constructed = false;

	/**
	 * Initializes the VDA with 0 dimensions.
	 */
	public VDA() {
		dims = new int[0];
	}

	/**
	 * Initializes the VDA with the given number of dimensions
	 * 
	 * @param dimensions
	 */
	public VDA(int... dimensions) {
		if(dimensions == null)
			throw new NullPointerException();
		dims = (int[])dimensions.clone();
	}

	/**
	 * @param size
	 *            Must be at least 2
	 */
	public void add(int size) {
		if(size < 2)
			throw new IllegalArgumentException("Dimension size must be at least 2.");
		dims = Arrays.copyOf(dims, dims.length + 1);
		dims[dims.length - 1] = size;
		constructed = false;
	}

	/**
	 * @param index
	 *            Must be between 0 and number of dimensions
	 */
	public void remove(int index) {
		if(index < 0 || index >= dims.length)
			throw new IndexOutOfBoundsException();
		int[] tmp = dims;
		dims = Arrays.copyOf(dims, dims.length - 1);
		if(index < dims.length) {
			System.arraycopy(tmp, index + 1, dims, index, dims.length - index);
		}
		constructed = false;
	}

	/**
	 * Get the value at the given dimension
	 */
	public T get(int... pos) {
		if(pos == null)
			throw new NullPointerException();
		if(dims.length == 0 || pos.length != dims.length)
			throw new IllegalArgumentException("Incorrect or Bad Dimensionality.");
		if(!constructed)
			construct();
		return data[getIndex(pos)];
	}

	/**
	 * Set the value at the given dimension
	 */
	public void set(T value, int... pos) {
		if(pos == null)
			throw new NullPointerException();
		if(dims.length == 0 || pos.length != dims.length)
			throw new IllegalArgumentException("Incorrect or Bad Dimensionality.");
		if(!constructed)
			construct();
		data[getIndex(pos)] = value;
	}

	/**
	 * Returns the bottom array at the given position
	 */
	public Object[] getSubArray(int... pos) {
		if(pos.length != dims.length - 1)
			throw new UnsupportedOperationException("Dimensionality must be one less than the total supported.");
		if(!constructed)
			construct();
		int start = getIndex(pos);
		int length = dims[dims.length - 1];
		T[] output = createArray(length);
		System.arraycopy(data, start, output, 0, length);
		return output;
	}

	/**
	 * Sets the bottom array at the given position
	 */
	public void setSubArray(T[] array, int... pos) {
		if(pos.length != dims.length - 1)
			throw new UnsupportedOperationException("Dimensionality must be one less than the total supported.");
		if(!constructed)
			construct();
		int start = getIndex(pos);
		int length = Math.min(dims[dims.length - 1], array.length);
		System.arraycopy(array, 0, data, start, length);
	}

	/**
	 * @return the array that backs this VDA
	 */
	public Object[] getBackingArray() {
		if(!constructed)
			construct();
		return data;
	}

	/**
	 * Returns an array containing all of the elements in this VDA
	 */
	public Object[] toArray() {
		if(!constructed)
			construct();
		return data.clone();
	}

	/**
	 * Returns an array containing all of the elements in this VDA
	 */
	@SuppressWarnings("unchecked")
	public T[] toArray(T[] a) {
		if(!constructed)
			construct();
		return (T[])Arrays.copyOf(data, data.length, a.getClass());
	}

	/**
	 * Sets this VDA to be equal to the given VDA. Data and dimensions are
	 * copied.
	 */
	public void set(VDA<T> vda) {
		data = (T[])vda.data.clone();
		dims = (int[])vda.dims.clone();
		constructed = vda.constructed;
	}

	/**
	 * Returns a shallow copy of this VDA (dimensions but not data)
	 */
	public Object clone() {
		return new VDA<T>(dims);
	}

	/**
	 * Creates the final data array
	 */
	private void construct() {
		Integer size = 1;
		for(Integer i : dims)
			size *= i;
		data = createArray(size);
		constructed = true;
	}

	@SuppressWarnings("unchecked")
	private T[] createArray(int size) {
		// Warning: Dangerous
		return (T[])new Object[size];
	}

	/**
	 * Gets the main arrays index from pos
	 */
	private int getIndex(int[] pos) {
		Integer index = 0;
		for(int i = 0; i < pos.length; ++i) {
			if(pos[i] < 0 || pos[i] >= dims[i])
				throw new IndexOutOfBoundsException("Index " + pos[i] + " is out of bounds for dimension " + i + ".");

			index += sizeUnder(i) * pos[i];
		}
		System.out.println("Index " + index);
		return index;
	}

	/**
	 * Gets the number of elements under the given level
	 */
	private int sizeUnder(int level) {
		Integer size = 1;
		for(int i = level + 1; i < dims.length; ++i) {
			size *= dims[i];
		}
		return size;
	}
}