/* * JVSTM: a Java library for Software Transactional Memory * Copyright (C) 2005 INESC-ID Software Engineering Group * http://www.esw.inesc-id.pt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author's contact: * INESC-ID Software Engineering Group * Rua Alves Redol 9 * 1000 - 029 Lisboa * Portugal */ package jvstm.util; import jvstm.VArray; /** Multidimensional versioned array implemented using a (linear) VArray. **/ /* Math: * Creation: * new VMultiArray(A, B, C, ..., Z) => new VArray(A*B*C*...*Z) * * Access: * VMultiArray.get(a, b, c, ..., z) => VArray.get(a + b*(A) + c*(A*B) + d*(A*B*C) + ... + z*(A*B*C*...*Y) * with 0 <= a < A, 0 <= b < B, ... 0 <= z < Z */ public class VMultiArray<E> { public final VArray<E> array; public final int[] dimensions; public VMultiArray(int ... dimensions) { if (dimensions.length <= 1) { throw new UnsupportedOperationException("Cannot create multidimensional array with less than two dimensions"); } int size = 1; for (int i : dimensions) { if (i <= 0) throw new NegativeArraySizeException(); size *= i; } this.array = new VArray<E>(size); this.dimensions = dimensions.clone(); // Keep our copy private, to avoid unpleasantries } private final int coordinatesToIndex(int ... coordinates) { if (coordinates.length != dimensions.length) { throw new ArrayIndexOutOfBoundsException("Number of coordinates does not match number of dimensions"); } int arrayIndex = 0; int currentDim = 0; int partialDim = 1; // Length of previous dimensions. Could be precalculated, but we will have to read their // sizes for bounds checking anyway, so we trade having to keep some other array for // a couple more cpu instructions. for (; currentDim < dimensions.length; currentDim++) { int coordIndex = coordinates[currentDim]; int dimSize = dimensions[currentDim]; if (coordIndex < 0 || coordIndex >= dimSize) throw new ArrayIndexOutOfBoundsException(); arrayIndex += coordIndex * partialDim; partialDim *= dimSize; } return arrayIndex; } public E get(int ... coordinates) { return array.get(coordinatesToIndex(coordinates)); } // Argument order inverted due to programming language limitations, sorry public void put(E newE, int ... coordinates) { array.put(coordinatesToIndex(coordinates), newE); } }