// $Id: MultiArrayProxy.java,v 1.3 2003-02-03 20:09:07 donm Exp $ /* * Copyright 1997-2000 Unidata Program Center/University Corporation for * Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, * support@unidata.ucar.edu. * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package ucar.multiarray; import java.io.IOException; /** * This MultiArray implementation wraps another MultiArray * and an IndexMap to provide a different view of the * wrapped MultiArray. Indices passed to access methods * are passed through a chain of mappings. * * @see MultiArray * @see IndexMap * @author $Author: donm $ * @version $Revision: 1.3 $ $Date: 2003-02-03 20:09:07 $ */ public class MultiArrayProxy implements MultiArray { /** * Construct a new proxy. * @param delegate MultiArray backing the proxy view provided. * @param im IndexMap defining the proxy view. */ public MultiArrayProxy(MultiArray delegate, IndexMap im) { delegate_ = delegate; im_ = im; dlengths_ = delegate_.getLengths(); im_.setLengths(dlengths_); } /* Begin MultiArrayInfo */ /** * Returns the Class object representing the component * type of the array. * @return Class The componentType * @see java.lang.Class#getComponentType */ public Class getComponentType() { return delegate_.getComponentType(); } /** * Returns the number of dimensions of the backing MultiArray, * as transformed by the <code>rankInverseMap()</code> method of * the IndexMap. * @return int number of dimensions */ public int getRank() { return im_.getRank(); } /** * Returns the shape of the backing MultiArray as transformed * by the <code>dimensionsInverseMap()</code> method of * the IndexMap. * @return int array whose length is the rank of this * MultiArray and whose elements represent the * length of each of it's dimensions */ public int [] getLengths() { if(isUnlimited()) { // The delegate lengths might have changed. // This could better be handle by an event. System.arraycopy(delegate_.getLengths(), 0, dlengths_, 0, dlengths_.length); } final int [] lengths = new int[getRank()]; return im_.getLengths(lengths); } /** * Returns <code>true</code> if and only if the effective dimension * lengths can change. */ public boolean isUnlimited() { return delegate_.isUnlimited(); } /** * Convenience interface; return <code>true</code> * if and only if the rank is zero. * @return boolean <code>true</code> iff rank == 0 */ public boolean isScalar() { return 0 == this.getRank(); } /* End MultiArrayInfo */ /* Begin Accessor */ /** * @return Object value at <code>index</code> * Length of index must equal rank() of this. * Values of index components must be less than corresponding * values from getLengths(). */ public Object get(int [] index) throws IOException { return delegate_.get(map(index)); } public boolean getBoolean(int[] index) throws IOException { return delegate_.getBoolean(map(index)); } public char getChar(int[] index) throws IOException { return delegate_.getChar(map(index)); } public byte getByte(int[] index) throws IOException { return delegate_.getByte(map(index)); } public short getShort(int[] index) throws IOException { return delegate_.getShort(map(index)); } public int getInt(int[] index) throws IOException { return delegate_.getInt(map(index)); } public long getLong(int[] index) throws IOException { return delegate_.getLong(map(index)); } public float getFloat(int[] index) throws IOException { return delegate_.getFloat(map(index)); } public double getDouble(int[] index) throws IOException { return delegate_.getDouble(map(index)); } /** * Length of index must equal rank() of this. * Values of index components must be less than corresponding * values from getLengths(). */ public void set(int [] index, Object value) throws IOException { delegate_.set(map(index), value); } public void setBoolean(int [] index, boolean value) throws IOException { delegate_.setBoolean(map(index), value); } public void setChar(int [] index, char value) throws IOException { delegate_.setChar(map(index), value); } public void setByte(int [] index, byte value) throws IOException { delegate_.setByte(map(index), value); } public void setShort(int [] index, short value) throws IOException { delegate_.setShort(map(index), value); } public void setInt(int [] index, int value) throws IOException { delegate_.setInt(map(index), value); } public void setLong(int [] index, long value) throws IOException { delegate_.setLong(map(index), value); } public void setFloat(int [] index, float value) throws IOException { delegate_.setFloat(map(index), value); } public void setDouble(int[] index, double value) throws IOException { delegate_.setDouble(map(index), value); } /** * @see Accessor#copyout */ public MultiArray copyout(int [] origin, int [] shape) throws IOException { final int rank = getRank(); if(origin.length != rank || shape.length != rank) throw new IllegalArgumentException("Rank Mismatch"); final MultiArrayImpl data = new MultiArrayImpl( getComponentType(), shape); AbstractAccessor.copyO(this, origin, data, shape); return data; } /** * @see Accessor#copyin */ public void copyin(int [] origin, MultiArray data) throws IOException { final int rank = getRank(); if(origin.length != rank || data.getRank() != rank) throw new IllegalArgumentException("Rank Mismatch"); // else if(data.getComponentType() != getComponentType()) throw new ArrayStoreException(); // else AbstractAccessor.copy(data, data.getLengths(), this, origin); } public Object getStorage () { return delegate_.getStorage (); } /** * @see Accessor#toArray * TODO: optimize? */ public Object toArray() throws IOException { return this.toArray(null, null, null); } /** * @see Accessor#toArray * TODO: optimize? */ public Object toArray(Object dst, int [] origin, int [] shape) throws IOException { final int rank = getRank(); if(origin == null) origin = new int[rank]; else if(origin.length != rank) throw new IllegalArgumentException("Rank Mismatch"); int [] shp = null; if(shape == null) shp = getLengths(); else if(shape.length == rank) shp = (int []) shape.clone(); else throw new IllegalArgumentException("Rank Mismatch"); final int [] products = new int[rank]; final int length = MultiArrayImpl.numberOfElements(shp, products); dst = MultiArrayImpl.fixDest(dst, length, getComponentType()); final MultiArrayImpl data = new MultiArrayImpl(shp, products, dst); AbstractAccessor.copyO(this, origin, data, shp); return dst; } /* End Accessor */ private synchronized int [] map(int [] index) { // TODO speedup? // safe inline im_.transform(converted_, index); im_.setInput(index); return im_.getTransformed(new int[im_.getOutputLength()]); } private final MultiArray delegate_; private final IndexMap im_; /** * Storage of delegate dimension lengths */ private final int [] dlengths_; // TODO better test /* Begin Test */ public static void main(String[] args) { System.out.println(">> " + System.currentTimeMillis()); final int [] shape = {48, 64}; MultiArrayImpl delegate = new MultiArrayImpl(Integer.TYPE, shape); { final int size = MultiArrayImpl.numberOfElements(shape); for(int ii = 0; ii < size; ii++) java.lang.reflect.Array.setInt(delegate.storage, ii, ii); } IndexMap im = new ClipMap(0, 4, 40); MultiArray src = new MultiArrayProxy(delegate, im); int [] clip = new int[] {32, 64}; int [] origin = new int[] {4, 0}; MultiArray ma = (MultiArray) null; try { ma = src.copyout(origin, clip); System.out.println("Rank " + ma.getRank()); int [] lengths = ma.getLengths(); System.out.println("Shape { " + lengths[0] + ", " + lengths[1] + " }"); System.out.println(ma.getInt(new int[] {0, 0})); System.out.println(ma.getInt(new int[] {1, 0})); System.out.println(ma.getInt(new int[] {lengths[0] -1, lengths[1] -1})); } catch (java.io.IOException ee) {} MultiArrayImpl destD = new MultiArrayImpl(Integer.TYPE, shape); im = new ClipMap(0, 8, 36); MultiArray dest = new MultiArrayProxy(destD, im); try { origin = new int[] {0, 0}; dest.copyin(origin, ma); System.out.println("***Rank " + dest.getRank()); int [] lengths = dest.getLengths(); System.out.println("Shape { " + lengths[0] + ", " + lengths[1] + " }"); System.out.println(destD.getInt(new int[] {0, 0})); System.out.println(destD.getInt(new int[] {7, 63})); System.out.println(destD.getInt(new int[] {8, 0})); System.out.println(destD.getInt(new int[] {8, 63})); System.out.println(destD.getInt(new int[] {9, 0})); System.out.println(destD.getInt(new int[] {39, 0})); System.out.println(destD.getInt(new int[] {40, 0})); System.out.println(destD.getInt(new int[] {47, 63})); } catch (java.io.IOException ee) {} } /* Test output java ucar.multiarray.MultiArrayProxy Rank 2 Shape { 32, 64 } 512 576 2559 ***Rank 2 Shape { 36, 64 } 0 0 512 575 576 2496 0 0 */ /* End Test */ }