1 /* 2 * Copyright (c) 2018, 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 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @modules jdk.incubator.vector 27 * @run testng/othervm --add-opens jdk.incubator.vector/jdk.incubator.vector=ALL-UNNAMED 28 * ByteMaxVectorLoadStoreTests 29 * 30 */ 31 32 import jdk.incubator.vector.Vector.Shape; 33 import jdk.incubator.vector.Vector.Species; 34 import jdk.incubator.vector.Vector; 35 36 import jdk.incubator.vector.ByteVector; 37 38 import org.testng.Assert; 39 import org.testng.annotations.DataProvider; 40 import org.testng.annotations.Test; 41 42 import java.lang.invoke.MethodHandles; 43 import java.lang.invoke.VarHandle; 44 import java.nio.ByteBuffer; 45 import java.nio.ByteOrder; 46 import java.util.List; 47 import java.util.function.IntFunction; 48 49 @Test 50 public class ByteMaxVectorLoadStoreTests extends AbstractVectorTest { 51 static final Species<Byte> SPECIES = 52 ByteVector.SPECIES_MAX; 53 54 static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 10); 55 56 static Shape getMaxBit() { 57 return Shape.S_Max_BIT; 58 } 59 60 static void assertArraysEquals(byte[] a, byte[] r, boolean[] mask) { 61 int i = 0; 62 try { 63 for (; i < a.length; i++) { 64 Assert.assertEquals(mask[i % SPECIES.length()] ? a[i] : (byte) 0, r[i]); 65 } 66 } catch (AssertionError e) { 67 Assert.assertEquals(mask[i % SPECIES.length()] ? a[i] : (byte) 0, r[i], "at index #" + i); 68 } 69 } 70 71 static void assertArraysEquals(byte[] a, byte[] r, int[] im) { 72 int i = 0; 73 try { 74 for (; i < a.length; i++) { 75 Assert.assertEquals(a[im[i]], r[i]); 76 } 77 } catch (AssertionError e) { 78 Assert.assertEquals(a[im[i]], r[i], "at index #" + i); 79 } 80 } 81 82 static void assertArraysEquals(byte[] a, byte[] r, int[] im, boolean[] mask) { 83 int i = 0; 84 try { 85 for (; i < a.length; i++) { 86 Assert.assertEquals(mask[i % SPECIES.length()] ? a[im[i]] : (byte) 0, r[i]); 87 } 88 } catch (AssertionError e) { 89 Assert.assertEquals(mask[i % SPECIES.length()] ? a[im[i]] : (byte) 0, r[i], "at index #" + i); 90 } 91 } 92 93 static final List<IntFunction<byte[]>> BYTE_GENERATORS = List.of( 94 withToString("byte[i * 5]", (int s) -> { 95 return fill(s * 1000, 96 i -> (byte)(i * 5)); 97 }), 98 withToString("byte[i + 1]", (int s) -> { 99 return fill(s * 1000, 100 i -> (((byte)(i + 1) == 0) ? 1 : (byte)(i + 1))); 101 }) 102 ); 103 104 @DataProvider 105 public Object[][] byteProvider() { 106 return BYTE_GENERATORS.stream(). 107 map(f -> new Object[]{f}). 108 toArray(Object[][]::new); 109 } 110 111 @DataProvider 112 public Object[][] byteMaskProvider() { 113 return BOOLEAN_MASK_GENERATORS.stream(). 114 flatMap(fm -> BYTE_GENERATORS.stream().map(fa -> { 115 return new Object[] {fa, fm}; 116 })). 117 toArray(Object[][]::new); 118 } 119 120 @DataProvider 121 public Object[][] byteIndexMapProvider() { 122 return INDEX_GENERATORS.stream(). 123 flatMap(fim -> BYTE_GENERATORS.stream().map(fa -> { 124 return new Object[] {fa, fim}; 125 })). 126 toArray(Object[][]::new); 127 } 128 129 @DataProvider 130 public Object[][] byteIndexMapMaskProvider() { 131 return BOOLEAN_MASK_GENERATORS.stream(). 132 flatMap(fm -> INDEX_GENERATORS.stream(). 133 flatMap(fim -> BYTE_GENERATORS.stream().map(fa -> { 134 return new Object[] {fa, fim, fm}; 135 }))). 136 toArray(Object[][]::new); 137 } 138 139 @DataProvider 140 public Object[][] byteByteBufferProvider() { 141 return BYTE_GENERATORS.stream(). 142 flatMap(fa -> BYTE_BUFFER_GENERATORS.stream().map(fb -> { 143 return new Object[]{fa, fb}; 144 })). 145 toArray(Object[][]::new); 146 } 147 148 @DataProvider 149 public Object[][] byteByteBufferMaskProvider() { 150 return BOOLEAN_MASK_GENERATORS.stream(). 151 flatMap(fm -> BYTE_GENERATORS.stream(). 152 flatMap(fa -> BYTE_BUFFER_GENERATORS.stream().map(fb -> { 153 return new Object[]{fa, fb, fm}; 154 }))). 155 toArray(Object[][]::new); 156 } 157 158 static ByteBuffer toBuffer(byte[] a, IntFunction<ByteBuffer> fb) { 159 ByteBuffer bb = fb.apply(a.length * SPECIES.elementSize() / 8); 160 for (byte v : a) { 161 bb.put(v); 162 } 163 return bb.clear(); 164 } 165 166 static byte[] bufferToArray(ByteBuffer bb) { 167 ByteBuffer db = bb; 168 byte[] d = new byte[db.capacity()]; 169 db.get(d); 170 return d; 171 } 172 173 interface ToByteF { 174 byte apply(int i); 175 } 176 177 static byte[] fill(int s , ToByteF f) { 178 return fill(new byte[s], f); 179 } 180 181 static byte[] fill(byte[] a, ToByteF f) { 182 for (int i = 0; i < a.length; i++) { 183 a[i] = f.apply(i); 184 } 185 return a; 186 } 187 188 @Test(dataProvider = "byteProvider") 189 static void loadStoreArray(IntFunction<byte[]> fa) { 190 byte[] a = fa.apply(SPECIES.length()); 191 byte[] r = new byte[a.length]; 192 193 for (int ic = 0; ic < INVOC_COUNT; ic++) { 194 for (int i = 0; i < a.length; i += SPECIES.length()) { 195 ByteVector av = ByteVector.fromArray(SPECIES, a, i); 196 av.intoArray(r, i); 197 } 198 } 199 Assert.assertEquals(a, r); 200 } 201 202 @Test(dataProvider = "byteMaskProvider") 203 static void loadStoreMaskArray(IntFunction<byte[]> fa, 204 IntFunction<boolean[]> fm) { 205 byte[] a = fa.apply(SPECIES.length()); 206 byte[] r = new byte[a.length]; 207 boolean[] mask = fm.apply(SPECIES.length()); 208 Vector.Mask<Byte> vmask = ByteVector.maskFromValues(SPECIES, mask); 209 210 for (int ic = 0; ic < INVOC_COUNT; ic++) { 211 for (int i = 0; i < a.length; i += SPECIES.length()) { 212 ByteVector av = ByteVector.fromArray(SPECIES, a, i, vmask); 213 av.intoArray(r, i); 214 } 215 } 216 assertArraysEquals(a, r, mask); 217 218 r = new byte[a.length]; 219 for (int ic = 0; ic < INVOC_COUNT; ic++) { 220 for (int i = 0; i < a.length; i += SPECIES.length()) { 221 ByteVector av = ByteVector.fromArray(SPECIES, a, i); 222 av.intoArray(r, i, vmask); 223 } 224 } 225 226 assertArraysEquals(a, r, mask); 227 } 228 229 230 @Test(dataProvider = "byteByteBufferProvider") 231 static void loadStoreByteBuffer(IntFunction<byte[]> fa, 232 IntFunction<ByteBuffer> fb) { 233 ByteBuffer a = toBuffer(fa.apply(SPECIES.length()), fb); 234 ByteBuffer r = fb.apply(a.limit()); 235 236 int l = a.limit(); 237 int s = SPECIES.length() * SPECIES.elementSize() / 8; 238 239 for (int ic = 0; ic < INVOC_COUNT; ic++) { 240 for (int i = 0; i < l; i += s) { 241 ByteVector av = ByteVector.fromByteBuffer(SPECIES, a, i); 242 av.intoByteBuffer(r, i); 243 } 244 } 245 Assert.assertEquals(a.position(), 0, "Input buffer position changed"); 246 Assert.assertEquals(a.limit(), l, "Input buffer limit changed"); 247 Assert.assertEquals(r.position(), 0, "Result buffer position changed"); 248 Assert.assertEquals(r.limit(), l, "Result buffer limit changed"); 249 Assert.assertEquals(a, r, "Buffers not equal"); 250 } 251 252 @Test(dataProvider = "byteByteBufferProvider") 253 static void loadReadOnlyStoreByteBuffer(IntFunction<byte[]> fa, 254 IntFunction<ByteBuffer> fb) { 255 ByteBuffer a = toBuffer(fa.apply(SPECIES.length()), fb); 256 a = a.asReadOnlyBuffer().order(a.order()); 257 ByteBuffer r = fb.apply(a.limit()); 258 259 int l = a.limit(); 260 int s = SPECIES.length() * SPECIES.elementSize() / 8; 261 262 for (int ic = 0; ic < INVOC_COUNT; ic++) { 263 for (int i = 0; i < l; i += s) { 264 ByteVector av = ByteVector.fromByteBuffer(SPECIES, a, i); 265 av.intoByteBuffer(r, i); 266 } 267 } 268 Assert.assertEquals(a.position(), 0, "Input buffer position changed"); 269 Assert.assertEquals(a.limit(), l, "Input buffer limit changed"); 270 Assert.assertEquals(r.position(), 0, "Result buffer position changed"); 271 Assert.assertEquals(r.limit(), l, "Result buffer limit changed"); 272 Assert.assertEquals(a, r, "Buffers not equal"); 273 } 274 275 @Test(dataProvider = "byteByteBufferMaskProvider") 276 static void loadStoreByteBufferMask(IntFunction<byte[]> fa, 277 IntFunction<ByteBuffer> fb, 278 IntFunction<boolean[]> fm) { 279 ByteBuffer a = toBuffer(fa.apply(SPECIES.length()), fb); 280 ByteBuffer r = fb.apply(a.limit()); 281 boolean[] mask = fm.apply(SPECIES.length()); 282 Vector.Mask<Byte> vmask = ByteVector.maskFromValues(SPECIES, mask); 283 284 int l = a.limit(); 285 int s = SPECIES.length() * SPECIES.elementSize() / 8; 286 287 for (int ic = 0; ic < INVOC_COUNT; ic++) { 288 for (int i = 0; i < l; i += s) { 289 ByteVector av = ByteVector.fromByteBuffer(SPECIES, a, i, vmask); 290 av.intoByteBuffer(r, i); 291 } 292 } 293 Assert.assertEquals(a.position(), 0, "Input buffer position changed"); 294 Assert.assertEquals(a.limit(), l, "Input buffer limit changed"); 295 Assert.assertEquals(r.position(), 0, "Result buffer position changed"); 296 Assert.assertEquals(r.limit(), l, "Result buffer limit changed"); 297 assertArraysEquals(bufferToArray(a), bufferToArray(r), mask); 298 299 a = toBuffer(fa.apply(SPECIES.length()), fb); 300 r = fb.apply(a.limit()); 301 for (int ic = 0; ic < INVOC_COUNT; ic++) { 302 for (int i = 0; i < l; i += s) { 303 ByteVector av = ByteVector.fromByteBuffer(SPECIES, a, i); 304 av.intoByteBuffer(r, i, vmask); 305 } 306 } 307 Assert.assertEquals(a.position(), 0, "Input buffer position changed"); 308 Assert.assertEquals(a.limit(), l, "Input buffer limit changed"); 309 Assert.assertEquals(r.position(), 0, "Result buffer position changed"); 310 Assert.assertEquals(r.limit(), l, "Result buffer limit changed"); 311 assertArraysEquals(bufferToArray(a), bufferToArray(r), mask); 312 } 313 314 @Test(dataProvider = "byteByteBufferMaskProvider") 315 static void loadReadOnlyStoreByteBufferMask(IntFunction<byte[]> fa, 316 IntFunction<ByteBuffer> fb, 317 IntFunction<boolean[]> fm) { 318 ByteBuffer a = toBuffer(fa.apply(SPECIES.length()), fb); 319 a = a.asReadOnlyBuffer().order(a.order()); 320 ByteBuffer r = fb.apply(a.limit()); 321 boolean[] mask = fm.apply(SPECIES.length()); 322 Vector.Mask<Byte> vmask = ByteVector.maskFromValues(SPECIES, mask); 323 324 int l = a.limit(); 325 int s = SPECIES.length() * SPECIES.elementSize() / 8; 326 327 for (int ic = 0; ic < INVOC_COUNT; ic++) { 328 for (int i = 0; i < l; i += s) { 329 ByteVector av = ByteVector.fromByteBuffer(SPECIES, a, i, vmask); 330 av.intoByteBuffer(r, i); 331 } 332 } 333 Assert.assertEquals(a.position(), 0, "Input buffer position changed"); 334 Assert.assertEquals(a.limit(), l, "Input buffer limit changed"); 335 Assert.assertEquals(r.position(), 0, "Result buffer position changed"); 336 Assert.assertEquals(r.limit(), l, "Result buffer limit changed"); 337 assertArraysEquals(bufferToArray(a), bufferToArray(r), mask); 338 } 339 }