From 68952f0ce0ce30180d5f6c5cf7a3c98c07d55e94 Mon Sep 17 00:00:00 2001
From: brinn <brinn>
Date: Sat, 4 Feb 2012 13:55:28 +0000
Subject: [PATCH] Make MDAbstractArray an Iterable<ArrayEntry>. Add methods
 computeReverseIndex(), numberOfHyperRows(). Add methods getAsObject(int) and
 setToObject(T, int) (1D, i.e.linear index). Make computeIndex() methods
 public.

SVN: 24341
---
 .../cisd/base/mdarray/MDAbstractArray.java    | 127 +++++++++++++++--
 .../systemsx/cisd/base/mdarray/MDArray.java   |  12 ++
 .../cisd/base/mdarray/MDByteArray.java        |  12 ++
 .../cisd/base/mdarray/MDDoubleArray.java      |  12 ++
 .../cisd/base/mdarray/MDFloatArray.java       |  12 ++
 .../cisd/base/mdarray/MDIntArray.java         |  12 ++
 .../cisd/base/mdarray/MDLongArray.java        |  12 ++
 .../cisd/base/mdarray/MDShortArray.java       |  12 ++
 .../cisd/base/mdarray/MDArrayTests.java       | 133 ++++++++----------
 9 files changed, 258 insertions(+), 86 deletions(-)

diff --git a/base/source/java/ch/systemsx/cisd/base/mdarray/MDAbstractArray.java b/base/source/java/ch/systemsx/cisd/base/mdarray/MDAbstractArray.java
index 6986d7a4930..4c11abfe31b 100644
--- a/base/source/java/ch/systemsx/cisd/base/mdarray/MDAbstractArray.java
+++ b/base/source/java/ch/systemsx/cisd/base/mdarray/MDAbstractArray.java
@@ -17,6 +17,7 @@
 package ch.systemsx.cisd.base.mdarray;
 
 import java.io.Serializable;
+import java.util.Iterator;
 
 import org.apache.commons.lang.ArrayUtils;
 import org.apache.commons.lang.ClassUtils;
@@ -30,9 +31,9 @@ import org.apache.commons.lang.ClassUtils;
  * 
  * @author Bernd Rinn
  */
-public abstract class MDAbstractArray<T> implements Serializable
+public abstract class MDAbstractArray<T> implements Serializable,
+        Iterable<MDAbstractArray<T>.ArrayEntry>
 {
-
     private static final long serialVersionUID = 1L;
 
     protected final int[] dimensions;
@@ -40,9 +41,46 @@ public abstract class MDAbstractArray<T> implements Serializable
     protected int hyperRowLength;
 
     protected int capacityHyperRows;
-    
+
     protected int size;
 
+    /**
+     * A class to represent an entry (index and value) of a {@link MDArray}, used for iteration.
+     */
+    public class ArrayEntry
+    {
+        private final int linearIndex;
+
+        ArrayEntry(int linearIndex)
+        {
+            this.linearIndex = linearIndex;
+        }
+
+        /**
+         * The multi-dimensional index of this entry.
+         */
+        public int[] getIndex()
+        {
+            return computeReverseIndex(linearIndex);
+        }
+
+        /**
+         * The linear index of this entry.
+         */
+        public int getLinearIndex()
+        {
+            return linearIndex;
+        }
+
+        /**
+         * The value of this entry.
+         */
+        public T getValue()
+        {
+            return getAsObject(linearIndex);
+        }
+    }
+
     protected MDAbstractArray(int[] dimensions, int arrayLength, int capacityHyperRows)
     {
         assert dimensions != null;
@@ -61,8 +99,8 @@ public abstract class MDAbstractArray<T> implements Serializable
                         + " does not match hyper-row length " + hyperRowLength + ".");
             }
             this.capacityHyperRows =
-                    (capacityHyperRows > 0) ? capacityHyperRows : Math.max(dimensions[0], arrayLength
-                            / hyperRowLength);
+                    (capacityHyperRows > 0) ? capacityHyperRows : Math.max(dimensions[0],
+                            arrayLength / hyperRowLength);
             this.size = dimensions[0] * hyperRowLength;
         }
     }
@@ -124,6 +162,23 @@ public abstract class MDAbstractArray<T> implements Serializable
     {
         return size;
     }
+    
+    /**
+     * Returns the current number of hyper rows of of this array.
+     */
+    public int numberOfHyperRows()
+    {
+        return numberOfHyperRows();
+    }
+
+    /**
+     * Return an object which has the same value as the element of the array specified by
+     * <var>linearIndex</var>.
+     * 
+     * @param linearIndex The index in the linear array returned by {@link #getAsFlatArray()}.
+     * @return The value at the specified index.
+     */
+    public abstract T getAsObject(int linearIndex);
 
     /**
      * Return an object which has the same value as the element of the array specified by
@@ -137,6 +192,15 @@ public abstract class MDAbstractArray<T> implements Serializable
      */
     public abstract void setToObject(T value, int... indices);
 
+    /**
+     * Sets the element of the array specified by <var>linearIndex</var> to the particular
+     * <var>value</var>.
+     * 
+     * @param value The new value to set.
+     * @param linearIndex The index in the linear array returned by {@link #getAsFlatArray()}.
+     */
+    public abstract void setToObject(T value, int linearIndex);
+
     /**
      * Returns the array in flattened form. Changes to the returned object will change the
      * multi-dimensional array directly.
@@ -188,7 +252,7 @@ public abstract class MDAbstractArray<T> implements Serializable
     /**
      * Computes the linear index for the multi-dimensional <var>indices</var> provided.
      */
-    protected int computeIndex(int... indices)
+    public int computeIndex(int... indices)
     {
         assert indices != null;
         assert indices.length == dimensions.length;
@@ -201,10 +265,27 @@ public abstract class MDAbstractArray<T> implements Serializable
         return index;
     }
 
+    /**
+     * Computes the multi-dimensional index from the <var>linearIndex</var>.
+     */
+    public int[] computeReverseIndex(int linearIndex)
+    {
+        final int[] index = new int[dimensions.length];
+        int workIndex = linearIndex;
+        int blockSize = size;
+        for (int i = 0; i < dimensions.length; ++i)
+        {
+            blockSize /= dimensions[i];
+            index[i] = workIndex / blockSize;
+            workIndex = workIndex - index[i] * blockSize;
+        }
+        return index;
+    }
+
     /**
      * Computes the linear index for the two-dimensional (<var>indexX, indexY</var>) provided.
      */
-    protected int computeIndex(int indexX, int indexY)
+    public int computeIndex(int indexX, int indexY)
     {
         assert 2 == dimensions.length;
 
@@ -215,7 +296,7 @@ public abstract class MDAbstractArray<T> implements Serializable
      * Computes the linear index for the three-dimensional (<var>indexX, indexY, indexZ</var>)
      * provided.
      */
-    protected int computeIndex(int indexX, int indexY, int indexZ)
+    public int computeIndex(int indexX, int indexY, int indexZ)
     {
         assert 3 == dimensions.length;
 
@@ -335,6 +416,36 @@ public abstract class MDAbstractArray<T> implements Serializable
         return intLength;
     }
 
+    //
+    // Iterable
+    //
+
+    public Iterator<ArrayEntry> iterator()
+    {
+        return new Iterator<ArrayEntry>()
+            {
+                int linearIndex = 0;
+
+                public boolean hasNext()
+                {
+                    return linearIndex < size;
+                }
+
+                public ArrayEntry next()
+                {
+                    final ArrayEntry next = new ArrayEntry(linearIndex);
+                    ++linearIndex;
+                    return next;
+                }
+
+                public void remove()
+                {
+                    throw new UnsupportedOperationException();
+                }
+
+            };
+    }
+
     //
     // Object
     //
diff --git a/base/source/java/ch/systemsx/cisd/base/mdarray/MDArray.java b/base/source/java/ch/systemsx/cisd/base/mdarray/MDArray.java
index 861acd77b9d..1a4a2360b77 100644
--- a/base/source/java/ch/systemsx/cisd/base/mdarray/MDArray.java
+++ b/base/source/java/ch/systemsx/cisd/base/mdarray/MDArray.java
@@ -149,6 +149,18 @@ public class MDArray<T> extends MDAbstractArray<T>
         set(value, indices);
     }
 
+    @Override
+    public T getAsObject(int linearIndex)
+    {
+        return get(linearIndex);
+    }
+
+    @Override
+    public void setToObject(T value, int linearIndex)
+    {
+        set(value, linearIndex);
+    }
+
     @Override
     public T[] getAsFlatArray()
     {
diff --git a/base/source/java/ch/systemsx/cisd/base/mdarray/MDByteArray.java b/base/source/java/ch/systemsx/cisd/base/mdarray/MDByteArray.java
index b724d6fce00..4bb36ad7d58 100644
--- a/base/source/java/ch/systemsx/cisd/base/mdarray/MDByteArray.java
+++ b/base/source/java/ch/systemsx/cisd/base/mdarray/MDByteArray.java
@@ -179,6 +179,18 @@ public final class MDByteArray extends MDAbstractArray<Byte>
         set(value, indices);
     }
 
+    @Override
+    public Byte getAsObject(int linearIndex)
+    {
+        return get(linearIndex);
+    }
+
+    @Override
+    public void setToObject(Byte value, int linearIndex)
+    {
+        set(value, linearIndex);
+    }
+
     @Override
     public byte[] getAsFlatArray()
     {
diff --git a/base/source/java/ch/systemsx/cisd/base/mdarray/MDDoubleArray.java b/base/source/java/ch/systemsx/cisd/base/mdarray/MDDoubleArray.java
index 40c60fef379..8a755f442ab 100644
--- a/base/source/java/ch/systemsx/cisd/base/mdarray/MDDoubleArray.java
+++ b/base/source/java/ch/systemsx/cisd/base/mdarray/MDDoubleArray.java
@@ -179,6 +179,18 @@ public final class MDDoubleArray extends MDAbstractArray<Double>
         set(value, indices);
     }
 
+    @Override
+    public Double getAsObject(int linearIndex)
+    {
+        return get(linearIndex);
+    }
+
+    @Override
+    public void setToObject(Double value, int linearIndex)
+    {
+        set(value, linearIndex);
+    }
+
     @Override
     public double[] getAsFlatArray()
     {
diff --git a/base/source/java/ch/systemsx/cisd/base/mdarray/MDFloatArray.java b/base/source/java/ch/systemsx/cisd/base/mdarray/MDFloatArray.java
index 69e7e076d2f..4b10fb8da65 100644
--- a/base/source/java/ch/systemsx/cisd/base/mdarray/MDFloatArray.java
+++ b/base/source/java/ch/systemsx/cisd/base/mdarray/MDFloatArray.java
@@ -179,6 +179,18 @@ public final class MDFloatArray extends MDAbstractArray<Float>
         set(value, indices);
     }
 
+    @Override
+    public Float getAsObject(int linearIndex)
+    {
+        return get(linearIndex);
+    }
+
+    @Override
+    public void setToObject(Float value, int linearIndex)
+    {
+        set(value, linearIndex);
+    }
+
     @Override
     public float[] getAsFlatArray()
     {
diff --git a/base/source/java/ch/systemsx/cisd/base/mdarray/MDIntArray.java b/base/source/java/ch/systemsx/cisd/base/mdarray/MDIntArray.java
index 7fea30fdd8b..76cbcd144e3 100644
--- a/base/source/java/ch/systemsx/cisd/base/mdarray/MDIntArray.java
+++ b/base/source/java/ch/systemsx/cisd/base/mdarray/MDIntArray.java
@@ -179,6 +179,18 @@ public final class MDIntArray extends MDAbstractArray<Integer>
         set(value, indices);
     }
 
+    @Override
+    public Integer getAsObject(int linearIndex)
+    {
+        return get(linearIndex);
+    }
+
+    @Override
+    public void setToObject(Integer value, int linearIndex)
+    {
+        set(value, linearIndex);
+    }
+
     @Override
     public int[] getAsFlatArray()
     {
diff --git a/base/source/java/ch/systemsx/cisd/base/mdarray/MDLongArray.java b/base/source/java/ch/systemsx/cisd/base/mdarray/MDLongArray.java
index 085caffb57d..3b927b131fe 100644
--- a/base/source/java/ch/systemsx/cisd/base/mdarray/MDLongArray.java
+++ b/base/source/java/ch/systemsx/cisd/base/mdarray/MDLongArray.java
@@ -179,6 +179,18 @@ public final class MDLongArray extends MDAbstractArray<Long>
         set(value, indices);
     }
 
+    @Override
+    public Long getAsObject(int linearIndex)
+    {
+        return get(linearIndex);
+    }
+
+    @Override
+    public void setToObject(Long value, int linearIndex)
+    {
+        set(value, linearIndex);
+    }
+
     @Override
     public long[] getAsFlatArray()
     {
diff --git a/base/source/java/ch/systemsx/cisd/base/mdarray/MDShortArray.java b/base/source/java/ch/systemsx/cisd/base/mdarray/MDShortArray.java
index 122213b07fb..eefb0b8459f 100644
--- a/base/source/java/ch/systemsx/cisd/base/mdarray/MDShortArray.java
+++ b/base/source/java/ch/systemsx/cisd/base/mdarray/MDShortArray.java
@@ -179,6 +179,18 @@ public final class MDShortArray extends MDAbstractArray<Short>
         set(value, indices);
     }
 
+    @Override
+    public Short getAsObject(int linearIndex)
+    {
+        return get(linearIndex);
+    }
+
+    @Override
+    public void setToObject(Short value, int linearIndex)
+    {
+        set(value, linearIndex);
+    }
+
     @Override
     public short[] getAsFlatArray()
     {
diff --git a/base/sourceTest/java/ch/systemsx/cisd/base/mdarray/MDArrayTests.java b/base/sourceTest/java/ch/systemsx/cisd/base/mdarray/MDArrayTests.java
index a20b743dd87..38a91820966 100644
--- a/base/sourceTest/java/ch/systemsx/cisd/base/mdarray/MDArrayTests.java
+++ b/base/sourceTest/java/ch/systemsx/cisd/base/mdarray/MDArrayTests.java
@@ -34,57 +34,6 @@ import ch.systemsx.cisd.base.BuildAndEnvironmentInfo;
  */
 public class MDArrayTests
 {
-
-    static class TestMDArray extends MDAbstractArray<Void>
-    {
-        private static final long serialVersionUID = 1L;
-
-        protected TestMDArray(int[] shape)
-        {
-            super(shape, 0, 0);
-        }
-
-        @Override
-        public Void getAsObject(int... indices)
-        {
-            return null;
-        }
-
-        @Override
-        public void setToObject(Void value, int... indices)
-        {
-        }
-
-        @Override
-        public int size()
-        {
-            return 0;
-        }
-
-        @Override
-        public int capacity()
-        {
-            return 0;
-        }
-
-        @Override
-        public Object getAsFlatArray()
-        {
-            return null;
-        }
-
-        @Override
-        public Object getCopyAsFlatArray()
-        {
-            return null;
-        }
-
-        @Override
-        protected void adaptCapacityHyperRows()
-        {
-        }
-    }
-
     @Test
     public void testGetLength()
     {
@@ -93,21 +42,21 @@ public class MDArrayTests
         assertEquals(1, MDAbstractArray.getLength(new int[]
             { 1 }, 0));
         assertEquals(2, MDAbstractArray.getLength(new int[]
-                { 1 }, 2));
+            { 1 }, 2));
         assertEquals(15, MDAbstractArray.getLength(new int[]
             { 5, 3 }, 0));
         assertEquals(21, MDAbstractArray.getLength(new int[]
-                { 5, 3 }, 7));
+            { 5, 3 }, 7));
         assertEquals(15, MDAbstractArray.getLength(new int[]
-                { 5, 3 }, 3));
+            { 5, 3 }, 3));
         assertEquals(1, MDAbstractArray.getLength(new int[]
             { 1, 1, 1 }, 0));
         assertEquals(3, MDAbstractArray.getLength(new int[]
-                { 1, 1, 1 }, 3));
+            { 1, 1, 1 }, 3));
         assertEquals(8, MDAbstractArray.getLength(new int[]
             { 2, 2, 2 }, 0));
         assertEquals(20, MDAbstractArray.getLength(new int[]
-                { 2, 2, 2 }, 5));
+            { 2, 2, 2 }, 5));
         assertEquals(2, MDAbstractArray.getLength(new int[]
             { 1, 1, 2 }, 0));
         assertEquals(2, MDAbstractArray.getLength(new int[]
@@ -132,32 +81,40 @@ public class MDArrayTests
     @Test
     public void testComputeIndex()
     {
-        TestMDArray array;
-        array = new TestMDArray(new int[]
+        MDArray<Object> array;
+        array = new MDArray<Object>(Object.class, new int[]
             { 33 });
         assertEquals(17, array.computeIndex(new int[]
             { 17 }));
-        array = new TestMDArray(new int[]
+        assertTrue(Arrays.toString(array.computeReverseIndex(17)), Arrays.equals(new int[]
+            { 17 }, array.computeReverseIndex(17)));
+        array = new MDArray<Object>(Object.class, new int[]
             { 100, 10 });
-        assertEquals(10 * 42 + 17, array.computeIndex(new int[]
-            { 42, 17 }));
-        array = new TestMDArray(new int[]
+        assertEquals(10 * 42 + 8, array.computeIndex(new int[]
+            { 42, 8 }));
+        assertTrue(Arrays.toString(array.computeReverseIndex(10 * 42 + 8)),
+                Arrays.equals(new int[]
+                    { 42, 8 }, array.computeReverseIndex(10 * 42 + 8)));
+        array = new MDArray<Object>(Object.class, new int[]
             { 2, 7, 3 });
-        assertEquals(3 * 7 * 1 + 3 * 2 + 3, array.computeIndex(new int[]
-            { 1, 2, 3 }));
+        assertEquals(3 * 7 * 1 + 3 * 3 + 2, array.computeIndex(new int[]
+            { 1, 3, 2 }));
+        assertTrue(Arrays.toString(array.computeReverseIndex(3 * 7 * 1 + 3 * 3 + 2)),
+                Arrays.equals(new int[]
+                    { 1, 3, 2 }, array.computeReverseIndex(3 * 7 * 1 + 3 * 3 + 2)));
     }
 
     @Test
     public void testComputeIndex2D()
     {
-        TestMDArray array;
-        array = new TestMDArray(new int[]
+        MDArray<Object> array;
+        array = new MDArray<Object>(Object.class, new int[]
             { 100, 10 });
         assertEquals(array.computeIndex(new int[]
             { 5, 8, }), array.computeIndex(5, 8));
         assertEquals(array.computeIndex(new int[]
             { 9, 1, }), array.computeIndex(9, 1));
-        array = new TestMDArray(new int[]
+        array = new MDArray<Object>(Object.class, new int[]
             { 101, 11 });
         assertEquals(array.computeIndex(new int[]
             { 5, 8, }), array.computeIndex(5, 8));
@@ -168,14 +125,14 @@ public class MDArrayTests
     @Test
     public void testComputeIndex3()
     {
-        TestMDArray array;
-        array = new TestMDArray(new int[]
+        MDArray<Object> array;
+        array = new MDArray<Object>(Object.class, new int[]
             { 100, 10, 17 });
         assertEquals(array.computeIndex(new int[]
             { 5, 8, 16 }), array.computeIndex(5, 8, 16));
         assertEquals(array.computeIndex(new int[]
             { 9, 1, 5 }), array.computeIndex(9, 1, 5));
-        array = new TestMDArray(new int[]
+        array = new MDArray<Object>(Object.class, new int[]
             { 101, 11, 3 });
         assertEquals(array.computeIndex(new int[]
             { 5, 8, 0 }), array.computeIndex(5, 8, 0));
@@ -190,11 +147,12 @@ public class MDArrayTests
         assertEquals(0, arr.dimensions()[0]);
         assertEquals(0, arr.dimensions()[1]);
     }
-    
+
     @Test
     public void testChangeHyperRowCountIntArray()
     {
-        final MDIntArray arr = new MDIntArray(new int[] { 2, 2 }, 3);
+        final MDIntArray arr = new MDIntArray(new int[]
+            { 2, 2 }, 3);
         assertEquals(2, arr.dimensions[0]);
         assertEquals(2, arr.dimensions[1]);
         arr.set(1, 0, 0);
@@ -204,7 +162,7 @@ public class MDArrayTests
 
         final MDIntArray arr2 = new MDIntArray(arr.getCopyAsFlatArray(), arr.dimensions());
         assertTrue(arr2.equals(arr));
-        
+
         arr.incNumberOfHyperRows(1);
         assertEquals(3, arr.dimensions[0]);
         assertEquals(1, arr.get(0, 0));
@@ -234,11 +192,12 @@ public class MDArrayTests
         assertEquals(7, arr.get(3, 0));
         assertEquals(8, arr.get(3, 1));
     }
-    
+
     @Test
     public void testChangeHyperRowCountIntArrayFromZero()
     {
-        final MDIntArray arr = new MDIntArray(new int[] { 0 });
+        final MDIntArray arr = new MDIntArray(new int[]
+            { 0 });
         assertEquals(0, arr.size(0));
         arr.incNumberOfHyperRows(1);
         assertEquals(1, arr.size(0));
@@ -248,11 +207,12 @@ public class MDArrayTests
         arr.incNumberOfHyperRows(1);
         assertEquals(3, arr.size());
     }
-    
+
     @Test
     public void testChangeHyperRowCountTArray()
     {
-        final MDArray<Integer> arr = new MDArray<Integer>(Integer.class, new int[] { 2, 2 }, 3);
+        final MDArray<Integer> arr = new MDArray<Integer>(Integer.class, new int[]
+            { 2, 2 }, 3);
         assertEquals(2, arr.dimensions[0]);
         assertEquals(2, arr.dimensions[1]);
         arr.set(1, 0, 0);
@@ -288,7 +248,24 @@ public class MDArrayTests
         assertEquals(7, (int) arr.get(3, 0));
         assertEquals(8, (int) arr.get(3, 1));
     }
-    
+
+    @Test
+    public void testMDIntArrayIterator()
+    {
+        final int[] linArray = new int[120];
+        for (int i = 0; i < linArray.length; ++i)
+        {
+            linArray[i] = i;
+        }
+        final MDIntArray array = new MDIntArray(linArray, new int[]
+            { 2, 3, 4, 5 });
+        for (MDIntArray.ArrayEntry e : array)
+        {
+            assertEquals(e.getLinearIndex(), e.getValue().intValue());
+            assertEquals(e.getLinearIndex(), array.computeIndex(e.getIndex()));
+        }
+    }
+
     @Test
     public void testMDFloatArrayMatrix()
     {
-- 
GitLab