/* --------------------------------------------------------------------- * Numenta Platform for Intelligent Computing (NuPIC) * Copyright (C) 2014, Numenta, Inc. Unless you have an agreement * with Numenta, Inc., for a separate license for this software code, the * following terms and conditions apply: * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero Public License version 3 as * published by the Free Software Foundation. * * This program 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 Affero Public License for more details. * * You should have received a copy of the GNU Affero Public License * along with this program. If not, see http://www.gnu.org/licenses. * * http://numenta.org/licenses/ * --------------------------------------------------------------------- */ package org.numenta.nupic.util; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.junit.Test; import org.numenta.nupic.model.Cell; import org.numenta.nupic.model.Column; public class ArrayUtilsTest { @Test public void testToBytes() { boolean[] ba = { true, true, }; byte[] bytes = ArrayUtils.toBytes(ba); assertEquals(0, bytes.length); // 8 positions -> binary 1 ba = new boolean[] { false, false, false, false, false, false, false, true }; bytes = ArrayUtils.toBytes(ba); assertEquals(1, bytes.length); assertEquals(1, bytes[0]); // 8 positions -> binary 3 ba = new boolean[] { false, false, false, false, false, false, true, true }; bytes = ArrayUtils.toBytes(ba); assertEquals(1, bytes.length); assertEquals(3, bytes[0]); // 9 positions -> squeezes last bit out ba = new boolean[] { false, false, false, false, false, false, false, true, true }; bytes = ArrayUtils.toBytes(ba); assertEquals(1, bytes.length); assertEquals(1, bytes[0]); // 10 positions -> squeeze last to bits out ba = new boolean[] { false, false, false, false, false, false, false, false, true, true }; bytes = ArrayUtils.toBytes(ba); assertEquals(1, bytes.length); assertEquals(0, bytes[0]); // 16 positions -> enough for two bytes, array length increases to 2 ba = new boolean[] { false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true }; bytes = ArrayUtils.toBytes(ba); assertEquals(2, bytes.length); assertEquals(0, bytes[0]); assertEquals(3, bytes[1]); } @Test public void testSubst() { int[] original = new int[] { 30, 30, 30, 30, 30 }; int[] substitutes = new int[] { 0, 1, 2, 3, 4 }; int[] substInds = new int[] { 4, 1, 3 }; int[] expected = { 30, 1, 30, 3, 4 }; assertTrue(Arrays.equals(expected, ArrayUtils.subst(original, substitutes, substInds))); } @Test public void testMaxIndex() { int max = ArrayUtils.maxIndex(new int[] { 2, 4, 5 }); assertEquals(39, max); } @Test public void testToCoordinates() { int[] coords = ArrayUtils.toCoordinates(19, new int[] { 2, 4, 5 }, false); assertTrue(Arrays.equals(new int[] { 0, 3, 4 }, coords)); coords = ArrayUtils.toCoordinates(19, new int[] { 2, 4, 5 }, true); assertTrue(Arrays.equals(new int[] { 4, 3, 0 }, coords)); } @Test public void testArgsort() { int[] args = ArrayUtils.argsort(new int[] { 11, 2, 3, 7, 0 }); assertTrue(Arrays.equals(new int[] {4, 1, 2, 3, 0}, args)); args = ArrayUtils.argsort(new int[] { 11, 2, 3, 7, 0 }, -1, -1); assertTrue(Arrays.equals(new int[] {4, 1, 2, 3, 0}, args)); args = ArrayUtils.argsort(new int[] { 11, 2, 3, 7, 0 }, 0, 3); assertTrue(Arrays.equals(new int[] {4, 1, 2}, args)); } @Test public void testShape() { int[][] inputPattern = { { 2, 3, 4, 5 }, { 6, 7, 8, 9} }; int[] shape = ArrayUtils.shape(inputPattern); assertTrue(Arrays.equals(new int[] { 2, 4 }, shape)); } @Test public void testReshape() { int[][] test = { { 0, 1, 2, 3, 4, 5 }, { 6, 7, 8, 9, 10, 11 } }; int[][] expected = { { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 }, { 9, 10, 11 } }; int[][] result = ArrayUtils.reshape(test, 3); for(int i = 0;i < result.length;i++) { for(int j = 0;j < result[i].length;j++) { assertEquals(expected[i][j], result[i][j]); } } // Unhappy case try { ArrayUtils.reshape(test, 5); }catch(Exception e) { assertTrue(e instanceof IllegalArgumentException); assertEquals("12 is not evenly divisible by 5", e.getMessage()); } // Test zero-length case int[] result4 = ArrayUtils.unravel(new int[0][]); assertNotNull(result4); assertTrue(result4.length == 0); } @Test public void testRavelAndUnRavel() { int[] test = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; int[][] expected = { { 0, 1, 2, 3, 4, 5 }, { 6, 7, 8, 9, 10, 11 } }; int[][] result = ArrayUtils.ravel(test, 6); for(int i = 0;i < result.length;i++) { for(int j = 0;j < result[i].length;j++) { assertEquals(expected[i][j], result[i][j]); } } int[] result2 = ArrayUtils.unravel(result); for(int i = 0;i < result2.length;i++) { assertEquals(test[i], result2[i]); } // Unhappy case try { ArrayUtils.ravel(test, 5); }catch(Exception e) { assertTrue(e instanceof IllegalArgumentException); assertEquals("12 is not evenly divisible by 5", e.getMessage()); } // Test zero-length case int[] result4 = ArrayUtils.unravel(new int[0][]); assertNotNull(result4); assertTrue(result4.length == 0); } @Test public void testRotateRight() { int[][] test = new int[][] { { 1, 0, 1, 0 }, { 1, 0, 1, 0 }, { 1, 0, 1, 0 }, { 1, 0, 1, 0 } }; int[][] expected = new int[][] { { 1, 1, 1, 1 }, { 0, 0, 0, 0 }, { 1, 1, 1, 1 }, { 0, 0, 0, 0 } }; int[][] result = ArrayUtils.rotateRight(test); for(int i = 0;i < result.length;i++) { for(int j = 0;j < result[i].length;j++) { assertEquals(result[i][j], expected[i][j]); } } } @Test public void testRotateLeft() { int[][] test = new int[][] { { 1, 0, 1, 0 }, { 1, 0, 1, 0 }, { 1, 0, 1, 0 }, { 1, 0, 1, 0 } }; int[][] expected = new int[][] { { 0, 0, 0, 0 }, { 1, 1, 1, 1 }, { 0, 0, 0, 0 }, { 1, 1, 1, 1 } }; int[][] result = ArrayUtils.rotateLeft(test); for(int i = 0;i < result.length;i++) { for(int j = 0;j < result[i].length;j++) { assertEquals(result[i][j], expected[i][j]); } } } @Test public void testConcat() { // Test happy path double[] one = new double[] { 1., 2., 3. }; double[] two = new double[] { 4., 5., 6. }; double[] retVal = ArrayUtils.concat(one, two); assertEquals(6, retVal.length); for(int i = 0;i < retVal.length;i++) { assertEquals(i + 1, retVal[i], 0); } // Test unequal sizes one = new double[] { 1., 2. }; retVal = ArrayUtils.concat(one, two); assertEquals(5, retVal.length); for(int i = 0;i < retVal.length;i++) { if(i == 2) continue; assertEquals(i + 1, retVal[i > 2 ? i - 1 : i], 0); } one = new double[] { 1., 2., 3. }; two = new double[] { 4., 5. }; retVal = ArrayUtils.concat(one, two); assertEquals(5, retVal.length); for(int i = 0;i < retVal.length;i++) { assertEquals(i + 1, retVal[i], 0); } //Test zero length one = new double[0]; two = new double[] { 4., 5., 6. }; retVal = ArrayUtils.concat(one, two); assertEquals(3, retVal.length); for(int i = 0;i < retVal.length;i++) { assertEquals(i + 4, retVal[i], 0); } one = new double[] { 1., 2., 3. }; two = new double[0]; retVal = ArrayUtils.concat(one, two); assertEquals(3, retVal.length); for(int i = 0;i < retVal.length;i++) { assertEquals(i + 1, retVal[i], 0); } } @Test public void testInterleave() { String[] f = { "0" }; double[] s = { 0.8 }; // Test most simple interleave of equal length arrays Object[] result = ArrayUtils.interleave(f, s); assertEquals("0", result[0]); assertEquals(0.8, result[1]); // Test simple interleave of larger array f = new String[] { "0", "1" }; s = new double[] { 0.42, 2.5 }; result = ArrayUtils.interleave(f, s); assertEquals("0", result[0]); assertEquals(0.42, result[1]); assertEquals("1", result[2]); assertEquals(2.5, result[3]); // Test complex interleave of larger array f = new String[] { "0", "1", "bob", "harry", "digit", "temperature" }; s = new double[] { 0.42, 2.5, .001, 1e-2, 34.0, .123 }; result = ArrayUtils.interleave(f, s); for(int i = 0, j = 0;j < result.length;i++, j+=2) { assertEquals(f[i], result[j]); assertEquals(s[i], result[j + 1]); } // Test interleave with zero length of first f = new String[0]; s = new double[] { 0.42, 2.5 }; result = ArrayUtils.interleave(f, s); assertEquals(0.42, result[0]); assertEquals(2.5, result[1]); // Test interleave with zero length of second f = new String[] { "0", "1" }; s = new double[0]; result = ArrayUtils.interleave(f, s); assertEquals("0", result[0]); assertEquals("1", result[1]); // Test complex unequal length: left side smaller f = new String[] { "0", "1", "bob" }; s = new double[] { 0.42, 2.5, .001, 1e-2, 34.0, .123 }; result = ArrayUtils.interleave(f, s); assertEquals("0", result[0]); assertEquals(0.42, result[1]); assertEquals("1", result[2]); assertEquals(2.5, result[3]); assertEquals("bob", result[4]); assertEquals(.001, result[5]); assertEquals(1e-2, result[6]); assertEquals(34.0, result[7]); assertEquals(.123, result[8]); // Test complex unequal length: right side smaller f = new String[] { "0", "1", "bob", "harry", "digit", "temperature" }; s = new double[] { 0.42, 2.5, .001 }; result = ArrayUtils.interleave(f, s); assertEquals("0", result[0]); assertEquals(0.42, result[1]); assertEquals("1", result[2]); assertEquals(2.5, result[3]); assertEquals("bob", result[4]); assertEquals(.001, result[5]); assertEquals("harry", result[6]); assertEquals("digit", result[7]); assertEquals("temperature", result[8]); // Negative testing try { f = null; s = new double[] { 0.42, 2.5, .001 }; result = ArrayUtils.interleave(f, s); fail(); }catch(Exception e) { assertEquals(NullPointerException.class, e.getClass()); } } @Test public void testIn1d() { int[] ar1 = { 0, 1, 5, 9, 3, 1000 }; int[] ar2 = Arrays.copyOf(ar1, ar1.length); assertTrue(Arrays.equals(ar1, ar2)); int[] retVal = ArrayUtils.in1d(ar1, ar2); assertTrue(Arrays.equals(ar1, ArrayUtils.reverse(retVal))); ar1 = new int[] { 0, 2, 1000 }; int[] expected = { 0, 1000 }; assertTrue(Arrays.equals(expected, ArrayUtils.reverse(ArrayUtils.in1d(ar1, ar2)))); ar1 = new int[] { 2, 6, 4 }; expected = new int[0]; assertTrue(Arrays.equals(expected, ArrayUtils.in1d(ar1, ar2))); // Test none in the second assertTrue(Arrays.equals(expected, ArrayUtils.in1d(ar1, expected))); // Test none in both assertTrue(Arrays.equals(expected, ArrayUtils.in1d(expected, expected))); } @Test public void testTo1d() { double[][] da = new double[][] { { 1., 1.}, {2., 2.}}; double[] expected = new double[] { 1., 1., 2., 2. }; assertTrue(Arrays.equals(expected, ArrayUtils.to1D(da))); int[][] ia = new int[][] { { 1, 1 }, { 2, 2 } }; int[] expectedia = new int[] { 1, 1, 2, 2 }; assertTrue(Arrays.equals(expectedia, ArrayUtils.to1D(ia))); } @Test public void testZip_ArrayOfLists() { Cell cell0 = new Cell(new Column(1, 0), 0); Cell cell1 = new Cell(new Column(1, 1), 1); List<?> o1 = Arrays.asList(new Cell[] { cell0, cell1 }); List<?> o2 = Arrays.asList(new Integer[] { new Integer(1), new Integer(2) }); List<?> o3 = Arrays.asList(new Double[] { 2.3, 4.5 }); List<Tuple> zipped = ArrayUtils.zip(o1, o2, o3); assertEquals(2, zipped.size()); assertTrue(zipped.get(0).get(0) instanceof Cell && zipped.get(0).get(1) instanceof Integer); assertTrue(zipped.get(0).get(0).equals(cell0) && zipped.get(0).get(1).equals(new Integer(1)) && zipped.get(0).get(2).equals(new Double(2.3))); assertTrue(zipped.get(1).get(0).equals(cell1) && zipped.get(1).get(1).equals(new Integer(2)) && zipped.get(1).get(2).equals(new Double(4.5))); // Negative tests assertFalse(zipped.get(0).get(0).equals(cell0) && zipped.get(0).get(1).equals(new Integer(2))); // Bad Integer assertFalse(zipped.get(1).get(0).equals(cell0) && zipped.get(1).get(1).equals(new Integer(2))); // Bad Cell } @Test public void testZip_ArrayOfIntArrays() { int[] o1 = { 3, 4 }; int[] o2 = { 5, 5 }; int[] o3 = { -1, 7 }; List<Tuple> zipped = ArrayUtils.zip(o1, o2, o3); assertEquals(2, zipped.size()); assertTrue(Arrays.equals((int[])zipped.get(0).all().stream().mapToInt(i -> (int)i).toArray(), new int[] { 3, 5, -1 })); assertTrue(Arrays.equals((int[])zipped.get(1).all().stream().mapToInt(i -> (int)i).toArray(), new int[] { 4, 5, 7 })); } @Test public void testZip() { Cell cell0 = new Cell(new Column(1, 0), 0); Cell cell1 = new Cell(new Column(1, 1), 1); Object[] o1 = new Object[] { cell0, cell1 }; Object[] o2 = new Object[] { new Integer(1), new Integer(2) }; List<Tuple> zipped = ArrayUtils.zip(o1, o2); assertEquals(2, zipped.size()); assertTrue(zipped.get(0).get(0) instanceof Cell && zipped.get(0).get(1) instanceof Integer); assertTrue(zipped.get(0).get(0).equals(cell0) && zipped.get(0).get(1).equals(new Integer(1))); assertTrue(zipped.get(1).get(0).equals(cell1) && zipped.get(1).get(1).equals(new Integer(2))); // Negative tests assertFalse(zipped.get(0).get(0).equals(cell0) && zipped.get(0).get(1).equals(new Integer(2))); // Bad Integer assertFalse(zipped.get(1).get(0).equals(cell0) && zipped.get(1).get(1).equals(new Integer(2))); // Bad Cell } @Test public void testMaximum() { double value = 6.7; double[] input = new double[] { 3.2, 6.8 }; double[] expected = new double[] { 6.7, 6.8 }; double[] result = ArrayUtils.maximum(input, value); assertTrue(Arrays.equals(expected, result)); } @Test public void testRoundDivide() { assertEquals(2.35, 4.7 / 2, 0.01); assertEquals(2.45, 4.9 / 2, 0.01); assertEquals(2.70, 5.4 / 2, 0.01); double[] inputDividend = new double[] { 4.7, 4.9, 5.4 }; double[] inputDivisor = new double[] { 2., 2., 2. }; double[] expected0 = new double[] { 2.4, 2.5, 2.7 }; double[] expected1 = new double[] { 2.0, 2.0, 3.0 }; double[] result = ArrayUtils.roundDivide(inputDividend, inputDivisor, 2); assertTrue(Arrays.equals(expected0, result)); double[] result2 = ArrayUtils.roundDivide(inputDividend, inputDivisor, 1); assertTrue(Arrays.equals(expected1, result2)); } @Test public void testSubtract() { // minuend - subtrahend = difference List<Integer> minuend = Arrays.asList(new Integer[] { 2, 2, 2 }); List<Integer> subtrahend = Arrays.asList(new Integer[] { 0, 1, 2 }); List<Integer> difference = Arrays.asList(new Integer[] { 2, 1, 0 }); List<Integer> result = ArrayUtils.subtract(subtrahend, minuend); assertEquals(difference, result); } @Test public void testRecursiveCoordinatesAssemble() throws InterruptedException { /*Create huge 5 dimensional matrix*/ int dimSize = 14, dimNumber = 5; int[] dimCoordinates = new int[dimSize]; List<int[]> dimensions = new ArrayList<int[]>(); for (int i = 0; i < dimNumber; i++) { for (int j = 0; j < dimSize; j++) { dimCoordinates[j] = j; } dimensions.add(dimCoordinates); } long startTime = System.currentTimeMillis(); List<int[]> neighborList = ArrayUtils.dimensionsToCoordinateList(dimensions); long take = System.currentTimeMillis() - startTime; System.out.print("Execute in:" + take + " milliseconds"); assertEquals(neighborList.size(), 537824); } /** * Python does modulus operations differently than the rest of the world * (C++ or Java) so... */ @Test public void testModulo() { int a = -7; int n = 5; assertEquals(3, ArrayUtils.modulo(a, n)); //Example A a = 5; n = 2; assertEquals(1, ArrayUtils.modulo(a, n)); //Example B a = 5; n = 3; assertEquals(2, ArrayUtils.modulo(a, n)); //Example C a = 10; n = 3; assertEquals(1, ArrayUtils.modulo(a, n)); //Example D a = 9; n = 3; assertEquals(0, ArrayUtils.modulo(a, n)); //Example E a = 3; n = 0; try { assertEquals(3, ArrayUtils.modulo(a, n)); fail(); }catch(Exception e) { assertEquals("Division by Zero!", e.getMessage()); } //Example F a = 2; n = 10; assertEquals(2, ArrayUtils.modulo(a, n)); } @Test public void testAnd() { int[] a = new int[] { 0, 0, 0, 0, 1, 1, 1 }; int[] b = new int[] { 0, 0, 0, 0, 1, 1, 1 }; int[] result = ArrayUtils.and(a, b); assertTrue(Arrays.equals(a , result)); a = new int[] { 0, 0, 0, 0, 1, 0, 1 }; result = ArrayUtils.and(a, b); assertTrue(Arrays.equals(a, result)); a = new int[] { 0, 0, 0, 0, 0, 0, 0 }; result = ArrayUtils.and(a, b); assertTrue(Arrays.equals(a, result)); a = new int[] { 1, 1, 1, 1, 0, 0, 0 }; int[] expected = new int[] { 0, 0, 0, 0, 0, 0, 0 }; result = ArrayUtils.and(a, b); assertTrue(Arrays.equals(expected, result)); } @Test public void testBitsToString() { String expected = "c....***"; String result = ArrayUtils.bitsToString(new int[] { 0, 0, 0, 0, 1, 1, 1 }); assertEquals(expected, result); } @Test public void testDiff() { double[] t = new double[] { 5, 4, 3, 2, 1, 0 }; double[] result = ArrayUtils.diff(t); assertEquals(5, result.length); assertTrue(Arrays.equals(new double[] { -1, -1, -1, -1, -1 }, result)); assertEquals(-5, ArrayUtils.sum(result), 0); } @Test public void testMultiDimensionArrayOperation() { int[] dimensions = {5, 5 ,5}; Object multiDimArray = createMultiDimensionArray(dimensions); ArrayUtils.fillArray(multiDimArray, 1); assertEquals(125, ArrayUtils.aggregateArray(multiDimArray)); } private Object createMultiDimensionArray(int[] sizes){ return Array.newInstance(int.class, sizes); } @Test public void testConcatAll() { assertTrue(Arrays.equals(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, ArrayUtils.concatAll(new int[]{1, 2}, new int[]{3, 4, 5, 6, 7}, new int[]{8, 9, 0}))); } @Test public void testReplace() { assertTrue(Arrays.equals(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, ArrayUtils.replace(5, 10, new int[]{1, 2, 3, 4, 5, -1, -1, -1, -1, -1}, new int[] { 6, 7, 8, 9, 0}))); } @Test public void testIsSparse() { int[] t = new int[] { 0, 1, 0 }; int[] t1 = new int[] { 4, 5, 6, 7 }; assertFalse(ArrayUtils.isSparse(t)); assertTrue(ArrayUtils.isSparse(t1)); } @Test public void testNGreatest() { double[] overlaps = new double[] { 1, 2, 1, 4, 8, 3, 12, 5, 4, 1 }; assertTrue(Arrays.equals(new int[] { 6, 4, 7 }, ArrayUtils.nGreatest(overlaps, 3))); } @Test public void testGreaterThanXFunctions() { int[] overlaps = new int[] { 0, 1, 0, 0, 3, 0, 6, 7, 1, 2, 0}; double[] overlapArray = new double[overlaps.length]; ArrayUtils.greaterThanXThanSetToYInB(overlaps, overlapArray, 0, 1); assertArrayEquals(new double[] { 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0 }, overlapArray, 0.0001); int[] arrayInt = new int[] { 0, 1, 0, 0, 3, 0, 6, 7, 1, 2, 0}; ArrayUtils.greaterThanXThanSetToY(arrayInt, 0, 1); assertArrayEquals(new int[] { 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0}, arrayInt); double[] arrayDouble = new double[] { 0, 5, 3, 0, 2, 0, 0, 7, 1, 2, 0}; ArrayUtils.greaterThanXThanSetToY(arrayDouble, 0, 2); assertArrayEquals(new double[] { 0, 2, 2, 0, 2, 0, 0, 2, 2, 2, 0}, arrayDouble, 0.0001); } @Test public void testArgmax() { int[] iarray = new int[] { 0, 1, 0, 0, 3, 0, 6, 7, 1, 2, 0}; double[] darray = new double[] { 0, 1, 10, 0, 3, 0, 6, 7, 1, 2, 0}; assertEquals(ArrayUtils.argmax(iarray), 7 ); assertEquals(ArrayUtils.argmax(darray), 2 ); } }