// $Id: AbstractAccessor.java,v 1.2 2002-05-29 20:32:38 steve 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 abstract class provides a skeletal implementation
* of the Accessor interface.
* <p>
* A minimal concrete implementation
* would provide concrete implementations
* <code>Object get(int [] index)</code>,
* <code>Object copyout(int [] origin, int [] shape)</code>,
* <code>set(int [] index, Object value)</code>.
* <code>copyin(int [] index, MultiArray value)</code>.
*
* @see Accessor
*
* @author $Author: steve $
* @version $Revision: 1.2 $ $Date: 2002-05-29 20:32:38 $
*/
public abstract class
AbstractAccessor
implements Accessor
{
/* NOTUSED, not correct?
* Analogous to System.arraycopy,
* copy elements from one Accessor to another.
* <p>
* The destination limits control the iteration.
* If the source limits are such that there is less
* data available in the source than requested in the
* destination, the source IndexIterator will silently
* "roll over", providing data from the beginning of
* the source.
*
* @param src the data source
* @param src_pos starting position in the data source
* @param src_limits limits on the source IndexIterator
* typically < ((MultiArray)src).getLengths()
* @param dst the destination, values here are modified
* @param dst_pos starting position in the data source
* @param dst_limits limits on the destination IndexIterator,
* typically < ((MultiArray)dst).getLengths()
*
static public void
copy(Accessor src, int [] src_pos, int [] src_limits,
Accessor dst, int [] dst_pos, int [] dst_limits)
throws IOException
{
IndexIterator src_odo = new IndexIterator(src_pos, src_limits);
IndexIterator dst_odo = new IndexIterator(dst_pos, dst_limits);
while(dst_odo.notDone())
{
dst.set(dst_odo.value(), src.get(src_odo.value()));
src_odo.incr();
dst_odo.incr();
}
}
*/
/**
* Used to implement copyin.
*
* @param src the data source
* @param src_limits limits on the source IndexIterator
* typically < ((MultiArray)src).getLengths()
* @param dst the destination, values here are modified
* @param dst_pos starting position in the data source
*
*/
static public void
copy(Accessor src, int [] src_limits,
Accessor dst, int [] dst_pos )
throws IOException
{
for(OffsetDualIndexIterator odo =
new OffsetDualIndexIterator(dst_pos, src_limits);
odo.notDone(); odo.incr())
{
dst.set(odo.offsetValue(), src.get(odo.value()));
}
}
/**
* Used to implement copyout.
*
* @param src the data source
* @param src_pos starting position in the data source
* @param dst the destination, values here are modified
* @param dst_limits limits on the source IndexIterator
* typically < ((MultiArray)dst).getLengths()
*
*/
static public void
copyO(Accessor src, int [] src_pos,
Accessor dst, int [] dst_limits )
throws IOException
{
for(OffsetDualIndexIterator odo =
new OffsetDualIndexIterator(src_pos, dst_limits);
odo.notDone(); odo.incr())
{
dst.set(odo.value(), src.get(odo.offsetValue()));
}
}
/* Begin MultiArray read access methods */
abstract public Object
get(int [] index)
throws IOException;
public boolean
getBoolean(int [] index)
throws IOException
{
final Boolean nn = (Boolean) get(index);
return nn.booleanValue();
}
public char
getChar(int [] index)
throws IOException
{
final Character nn = (Character) get(index);
return nn.charValue();
}
public byte
getByte(int [] index)
throws IOException
{
final Number nn = (Number) get(index);
return nn.byteValue();
}
public short
getShort(int [] index)
throws IOException
{
final Number nn = (Number) get(index);
return nn.shortValue();
}
public int
getInt(int [] index)
throws IOException
{
final Number nn = (Number) get(index);
return nn.intValue();
}
public long
getLong(int [] index)
throws IOException
{
final Number nn = (Number) get(index);
return nn.longValue();
}
public float
getFloat(int [] index)
throws IOException
{
final Number nn = (Number) get(index);
return nn.floatValue();
}
public double
getDouble(int [] index)
throws IOException
{
final Number nn = (Number) get(index);
return nn.doubleValue();
}
/* End MultiArray read access methods */
/* Begin MultiArray write access methods */
abstract public void
set(int [] index, Object value)
throws IOException;
public void
setBoolean(int [] index, boolean value)
throws IOException
{
set(index, new Boolean(value));
}
public void
setChar(int [] index, char value)
throws IOException
{
set(index, new Character(value));
}
public void
setByte(int [] index, byte value)
throws IOException
{
set(index, new Byte(value));
}
public void
setShort(int [] index, short value)
throws IOException
{
set(index, new Short(value));
}
public void
setInt(int [] index, int value)
throws IOException
{
set(index, new Integer(value));
}
public void
setLong(int [] index, long value)
throws IOException
{
set(index, new Long(value));
}
public void
setFloat(int [] index, float value)
throws IOException
{
set(index, new Float(value));
}
public void
setDouble(int [] index, double value)
throws IOException
{
set(index, new Double(value));
}
/* End MultiArray write access methods */
abstract public MultiArray
copyout(int [] origin, int [] shape)
throws IOException;
/*
{
final MultiArrayImpl data = new MultiArrayImpl(
componentType,
shape);
for(OffsetDualIndexIterator odo =
new OffsetDualIndexIterator(origin, data.getLengths());
odo.notDone(); odo.incr())
{
data.set(odo.value(), get(odo.offsetValue()));
}
return data;
}
*/
/**
* You almost always want to override this
*/
public void
copyin(int [] origin, MultiArray data)
throws IOException
{
for(OffsetDualIndexIterator odo =
new OffsetDualIndexIterator(origin, data.getLengths());
odo.notDone(); odo.incr())
{
set(odo.offsetValue(), data.get(odo.value()));
}
}
abstract public Object
toArray()
throws IOException;
abstract public Object
toArray(Object dst, int [] origin, int [] shape)
throws IOException;
}
final class
OffsetDualIndexIterator
extends IndexIterator
{
OffsetDualIndexIterator(int [] theOffset, int [] theLimits)
{
super(theLimits);
offset = theOffset; // N.B. Not a copy
offsetCounter = (int []) offset.clone();
}
/**
* Increment the odometer
*/
public void
incr()
{
int digit = counter.length -1;
if(digit < 0)
{
// counter is zero length array <==> scalar
ncycles++;
return;
}
while(digit >= 0)
{
offsetCounter[digit]++;
counter[digit]++;
if(counter[digit] < limits[digit])
{
break; // normal exit
}
// else, carry
counter[digit] = 0;
offsetCounter[digit] = offset[digit];
if(digit == 0)
{
ncycles++; // rolled over
break;
}
// else
digit--;
}
}
public int []
offsetValue() { return offsetCounter; }
private final int[] offset;
private final int[] offsetCounter;
}