1 /*
  2  * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 /*
 25  * @test
 26  * @run testng TestReshape
 27  */
 28 
 29 import jdk.incubator.foreign.MemoryLayout;
 30 import jdk.incubator.foreign.MemoryLayouts;
 31 import jdk.incubator.foreign.SequenceLayout;
 32 
 33 import java.util.ArrayList;
 34 import java.util.Iterator;
 35 import java.util.List;
 36 import java.util.stream.LongStream;
 37 
 38 import org.testng.annotations.*;
 39 import static org.testng.Assert.*;
 40 
 41 public class TestReshape {
 42 
 43     @Test(dataProvider = "shapes")
 44     public void testReshape(MemoryLayout layout, long[] expectedShape) {
 45         long flattenedSize = LongStream.of(expectedShape).reduce(1L, Math::multiplyExact);
 46         SequenceLayout seq_flattened = MemoryLayout.sequenceLayout(flattenedSize, layout);
 47         assertDimensions(seq_flattened, flattenedSize);
 48         for (long[] shape : new Shape(expectedShape)) {
 49             SequenceLayout seq_shaped = seq_flattened.reshape(shape);
 50             assertDimensions(seq_shaped, expectedShape);
 51             assertEquals(seq_shaped.flatten(), seq_flattened);
 52         }
 53     }
 54 
 55     @Test(expectedExceptions = IllegalArgumentException.class)
 56     public void testInvalidReshape() {
 57         SequenceLayout seq = MemoryLayout.sequenceLayout(4, MemoryLayouts.JAVA_INT);
 58         seq.reshape(3, 2);
 59     }
 60 
 61     @Test(expectedExceptions = IllegalArgumentException.class)
 62     public void testBadReshapeInference() {
 63         SequenceLayout seq = MemoryLayout.sequenceLayout(4, MemoryLayouts.JAVA_INT);
 64         seq.reshape(-1, -1);
 65     }
 66 
 67     @Test(expectedExceptions = IllegalArgumentException.class)
 68     public void testBadReshapeParameterZero() {
 69         SequenceLayout seq = MemoryLayout.sequenceLayout(4, MemoryLayouts.JAVA_INT);
 70         seq.reshape(0, 4);
 71     }
 72 
 73     @Test(expectedExceptions = IllegalArgumentException.class)
 74     public void testBadReshapeParameterNegative() {
 75         SequenceLayout seq = MemoryLayout.sequenceLayout(4, MemoryLayouts.JAVA_INT);
 76         seq.reshape(-2, 2);
 77     }
 78 
 79     @Test(expectedExceptions = UnsupportedOperationException.class)
 80     public void testReshapeOnUnboundSequence() {
 81         SequenceLayout seq = MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT);
 82         seq.reshape(3, 2);
 83     }
 84 
 85     @Test(expectedExceptions = UnsupportedOperationException.class)
 86     public void testFlattenOnUnboundSequence() {
 87         SequenceLayout seq = MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT);
 88         seq.flatten();
 89     }
 90 
 91     @Test(expectedExceptions = UnsupportedOperationException.class)
 92     public void testFlattenOnUnboundNestedSequence() {
 93         SequenceLayout seq = MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT));
 94         seq.flatten();
 95     }
 96 
 97     static void assertDimensions(SequenceLayout layout, long... dims) {
 98         SequenceLayout prev = null;
 99         for (int i = 0 ; i < dims.length ; i++) {
100             if (prev != null) {
101                 layout = (SequenceLayout)prev.elementLayout();
102             }
103             assertEquals(layout.elementCount().getAsLong(), dims[i]);
104             prev = layout;
105         }
106     }
107 
108     static class Shape implements Iterable<long[]> {
109         long[] shape;
110 
111         Shape(long... shape) {
112             this.shape = shape;
113         }
114 
115         public Iterator<long[]> iterator() {
116             List<long[]> shapes = new ArrayList<>();
117             shapes.add(shape);
118             for (int i = 0 ; i < shape.length ; i++) {
119                 long[] inferredShape = shape.clone();
120                 inferredShape[i] = -1;
121                 shapes.add(inferredShape);
122             }
123             return shapes.iterator();
124         }
125     }
126 
127     static MemoryLayout POINT = MemoryLayout.structLayout(
128             MemoryLayouts.JAVA_INT,
129             MemoryLayouts.JAVA_INT
130     );
131 
132     @DataProvider(name = "shapes")
133     Object[][] shapes() {
134         return new Object[][] {
135                 { MemoryLayouts.JAVA_BYTE, new long[] { 256 } },
136                 { MemoryLayouts.JAVA_BYTE, new long[] { 16, 16 } },
137                 { MemoryLayouts.JAVA_BYTE, new long[] { 4, 4, 4, 4 } },
138                 { MemoryLayouts.JAVA_BYTE, new long[] { 2, 8, 16 } },
139                 { MemoryLayouts.JAVA_BYTE, new long[] { 16, 8, 2 } },
140                 { MemoryLayouts.JAVA_BYTE, new long[] { 8, 16, 2 } },
141 
142                 { MemoryLayouts.JAVA_SHORT, new long[] { 256 } },
143                 { MemoryLayouts.JAVA_SHORT, new long[] { 16, 16 } },
144                 { MemoryLayouts.JAVA_SHORT, new long[] { 4, 4, 4, 4 } },
145                 { MemoryLayouts.JAVA_SHORT, new long[] { 2, 8, 16 } },
146                 { MemoryLayouts.JAVA_SHORT, new long[] { 16, 8, 2 } },
147                 { MemoryLayouts.JAVA_SHORT, new long[] { 8, 16, 2 } },
148 
149                 { MemoryLayouts.JAVA_CHAR, new long[] { 256 } },
150                 { MemoryLayouts.JAVA_CHAR, new long[] { 16, 16 } },
151                 { MemoryLayouts.JAVA_CHAR, new long[] { 4, 4, 4, 4 } },
152                 { MemoryLayouts.JAVA_CHAR, new long[] { 2, 8, 16 } },
153                 { MemoryLayouts.JAVA_CHAR, new long[] { 16, 8, 2 } },
154                 { MemoryLayouts.JAVA_CHAR, new long[] { 8, 16, 2 } },
155 
156                 { MemoryLayouts.JAVA_INT, new long[] { 256 } },
157                 { MemoryLayouts.JAVA_INT, new long[] { 16, 16 } },
158                 { MemoryLayouts.JAVA_INT, new long[] { 4, 4, 4, 4 } },
159                 { MemoryLayouts.JAVA_INT, new long[] { 2, 8, 16 } },
160                 { MemoryLayouts.JAVA_INT, new long[] { 16, 8, 2 } },
161                 { MemoryLayouts.JAVA_INT, new long[] { 8, 16, 2 } },
162 
163                 { MemoryLayouts.JAVA_LONG, new long[] { 256 } },
164                 { MemoryLayouts.JAVA_LONG, new long[] { 16, 16 } },
165                 { MemoryLayouts.JAVA_LONG, new long[] { 4, 4, 4, 4 } },
166                 { MemoryLayouts.JAVA_LONG, new long[] { 2, 8, 16 } },
167                 { MemoryLayouts.JAVA_LONG, new long[] { 16, 8, 2 } },
168                 { MemoryLayouts.JAVA_LONG, new long[] { 8, 16, 2 } },
169 
170                 { MemoryLayouts.JAVA_FLOAT, new long[] { 256 } },
171                 { MemoryLayouts.JAVA_FLOAT, new long[] { 16, 16 } },
172                 { MemoryLayouts.JAVA_FLOAT, new long[] { 4, 4, 4, 4 } },
173                 { MemoryLayouts.JAVA_FLOAT, new long[] { 2, 8, 16 } },
174                 { MemoryLayouts.JAVA_FLOAT, new long[] { 16, 8, 2 } },
175                 { MemoryLayouts.JAVA_FLOAT, new long[] { 8, 16, 2 } },
176 
177                 { MemoryLayouts.JAVA_DOUBLE, new long[] { 256 } },
178                 { MemoryLayouts.JAVA_DOUBLE, new long[] { 16, 16 } },
179                 { MemoryLayouts.JAVA_DOUBLE, new long[] { 4, 4, 4, 4 } },
180                 { MemoryLayouts.JAVA_DOUBLE, new long[] { 2, 8, 16 } },
181                 { MemoryLayouts.JAVA_DOUBLE, new long[] { 16, 8, 2 } },
182                 { MemoryLayouts.JAVA_DOUBLE, new long[] { 8, 16, 2 } },
183 
184                 { POINT, new long[] { 256 } },
185                 { POINT, new long[] { 16, 16 } },
186                 { POINT, new long[] { 4, 4, 4, 4 } },
187                 { POINT, new long[] { 2, 8, 16 } },
188                 { POINT, new long[] { 16, 8, 2 } },
189                 { POINT, new long[] { 8, 16, 2 } },
190         };
191     }
192 }