1 /*
   2  * Copyright (c) 2018, 2022, 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  * @enablePreview
  27  * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation
  28  * @run testng/othervm -XX:-TieredCompilation Byte64VectorLoadStoreTests
  29  *
  30  */
  31 
  32 // -- This file was mechanically generated: Do not edit! -- //
  33 
  34 import java.lang.foreign.MemorySegment;
  35 import java.lang.foreign.Arena;
  36 import java.lang.foreign.ValueLayout;
  37 import jdk.incubator.vector.ByteVector;
  38 import jdk.incubator.vector.VectorMask;
  39 import jdk.incubator.vector.VectorSpecies;
  40 import jdk.incubator.vector.VectorShuffle;
  41 import jdk.internal.vm.annotation.DontInline;
  42 import org.testng.Assert;
  43 import org.testng.annotations.DataProvider;
  44 import org.testng.annotations.Test;
  45 
  46 import java.nio.ByteOrder;
  47 import java.util.List;
  48 import java.util.function.*;
  49 
  50 @Test
  51 public class Byte64VectorLoadStoreTests extends AbstractVectorLoadStoreTest {
  52     static final VectorSpecies<Byte> SPECIES =
  53                 ByteVector.SPECIES_64;
  54 
  55     static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 100);
  56 
  57     static final ValueLayout.OfByte ELEMENT_LAYOUT = ValueLayout.JAVA_BYTE.withByteAlignment(1);
  58 
  59 
  60     static final int BUFFER_REPS = Integer.getInteger("jdk.incubator.vector.test.buffer-vectors", 25000 / 64);
  61 
  62     static void assertArraysEquals(byte[] r, byte[] a, boolean[] mask) {
  63         int i = 0;
  64         try {
  65             for (; i < a.length; i++) {
  66                 Assert.assertEquals(r[i], mask[i % SPECIES.length()] ? a[i] : (byte) 0);
  67             }
  68         } catch (AssertionError e) {
  69             Assert.assertEquals(r[i], mask[i % SPECIES.length()] ? a[i] : (byte) 0, "at index #" + i);
  70         }
  71     }
  72 
  73     static final List<IntFunction<byte[]>> BYTE_GENERATORS = List.of(
  74             withToString("byte[i * 5]", (int s) -> {
  75                 return fill(s * BUFFER_REPS,
  76                             i -> (byte)(i * 5));
  77             }),
  78             withToString("byte[i + 1]", (int s) -> {
  79                 return fill(s * BUFFER_REPS,
  80                             i -> (((byte)(i + 1) == 0) ? 1 : (byte)(i + 1)));
  81             })
  82     );
  83 
  84     // Relative to array.length
  85     static final List<IntFunction<Integer>> INDEX_GENERATORS = List.of(
  86             withToString("-1", (int l) -> {
  87                 return -1;
  88             }),
  89             withToString("l", (int l) -> {
  90                 return l;
  91             }),
  92             withToString("l - 1", (int l) -> {
  93                 return l - 1;
  94             }),
  95             withToString("l + 1", (int l) -> {
  96                 return l + 1;
  97             }),
  98             withToString("l - speciesl + 1", (int l) -> {
  99                 return l - SPECIES.length() + 1;
 100             }),
 101             withToString("l + speciesl - 1", (int l) -> {
 102                 return l + SPECIES.length() - 1;
 103             }),
 104             withToString("l + speciesl", (int l) -> {
 105                 return l + SPECIES.length();
 106             }),
 107             withToString("l + speciesl + 1", (int l) -> {
 108                 return l + SPECIES.length() + 1;
 109             })
 110     );
 111 
 112     // Relative to byte[] array.length or MemorySegment.byteSize()
 113     static final List<IntFunction<Integer>> BYTE_INDEX_GENERATORS = List.of(
 114             withToString("-1", (int l) -> {
 115                 return -1;
 116             }),
 117             withToString("l", (int l) -> {
 118                 return l;
 119             }),
 120             withToString("l - 1", (int l) -> {
 121                 return l - 1;
 122             }),
 123             withToString("l + 1", (int l) -> {
 124                 return l + 1;
 125             }),
 126             withToString("l - speciesl*ebsize + 1", (int l) -> {
 127                 return l - SPECIES.vectorByteSize() + 1;
 128             }),
 129             withToString("l + speciesl*ebsize - 1", (int l) -> {
 130                 return l + SPECIES.vectorByteSize() - 1;
 131             }),
 132             withToString("l + speciesl*ebsize", (int l) -> {
 133                 return l + SPECIES.vectorByteSize();
 134             }),
 135             withToString("l + speciesl*ebsize + 1", (int l) -> {
 136                 return l + SPECIES.vectorByteSize() + 1;
 137             })
 138     );
 139 
 140     @DataProvider
 141     public Object[][] byteProvider() {
 142         return BYTE_GENERATORS.stream().
 143                 map(f -> new Object[]{f}).
 144                 toArray(Object[][]::new);
 145     }
 146 
 147     @DataProvider
 148     public Object[][] maskProvider() {
 149         return BOOLEAN_MASK_GENERATORS.stream().
 150                 map(f -> new Object[]{f}).
 151                 toArray(Object[][]::new);
 152     }
 153 
 154     @DataProvider
 155     public Object[][] byteProviderForIOOBE() {
 156         var f = BYTE_GENERATORS.get(0);
 157         return INDEX_GENERATORS.stream().map(fi -> {
 158                     return new Object[] {f, fi};
 159                 }).
 160                 toArray(Object[][]::new);
 161     }
 162 
 163     @DataProvider
 164     public Object[][] byteMaskProvider() {
 165         return BOOLEAN_MASK_GENERATORS.stream().
 166                 flatMap(fm -> BYTE_GENERATORS.stream().map(fa -> {
 167                     return new Object[] {fa, fm};
 168                 })).
 169                 toArray(Object[][]::new);
 170     }
 171 
 172     @DataProvider
 173     public Object[][] byteMaskProviderForIOOBE() {
 174         var f = BYTE_GENERATORS.get(0);
 175         return BOOLEAN_MASK_GENERATORS.stream().
 176                 flatMap(fm -> INDEX_GENERATORS.stream().map(fi -> {
 177                     return new Object[] {f, fi, fm};
 178                 })).
 179                 toArray(Object[][]::new);
 180     }
 181 
 182     @DataProvider
 183     public Object[][] byteMemorySegmentProvider() {
 184         return BYTE_GENERATORS.stream().
 185                 flatMap(fa -> MEMORY_SEGMENT_GENERATORS.stream().
 186                         flatMap(fb -> BYTE_ORDER_VALUES.stream().map(bo -> {
 187                             return new Object[]{fa, fb, bo};
 188                         }))).
 189                 toArray(Object[][]::new);
 190     }
 191 
 192     @DataProvider
 193     public Object[][] byteMemorySegmentMaskProvider() {
 194         return BOOLEAN_MASK_GENERATORS.stream().
 195                 flatMap(fm -> BYTE_GENERATORS.stream().
 196                         flatMap(fa -> MEMORY_SEGMENT_GENERATORS.stream().
 197                                 flatMap(fb -> BYTE_ORDER_VALUES.stream().map(bo -> {
 198                             return new Object[]{fa, fb, fm, bo};
 199                         })))).
 200                 toArray(Object[][]::new);
 201     }
 202 
 203     @DataProvider
 204     public Object[][] byteByteProviderForIOOBE() {
 205         var f = BYTE_GENERATORS.get(0);
 206         return BYTE_INDEX_GENERATORS.stream().map(fi -> {
 207                     return new Object[] {f, fi};
 208                 }).
 209                 toArray(Object[][]::new);
 210     }
 211 
 212     @DataProvider
 213     public Object[][] byteByteMaskProviderForIOOBE() {
 214         var f = BYTE_GENERATORS.get(0);
 215         return BOOLEAN_MASK_GENERATORS.stream().
 216                 flatMap(fm -> BYTE_INDEX_GENERATORS.stream().map(fi -> {
 217                     return new Object[] {f, fi, fm};
 218                 })).
 219                 toArray(Object[][]::new);
 220     }
 221 
 222     static MemorySegment toSegment(byte[] a, IntFunction<MemorySegment> fb) {
 223         MemorySegment ms = fb.apply(a.length * SPECIES.elementSize() / 8);
 224         for (int i = 0; i < a.length; i++) {
 225             ms.set(ELEMENT_LAYOUT, i * SPECIES.elementSize() / 8 , a[i]);
 226         }
 227         return ms;
 228     }
 229 
 230     static byte[] segmentToArray(MemorySegment ms) {
 231         return ms.toArray(ELEMENT_LAYOUT);
 232     }
 233 
 234 
 235     interface ToByteF {
 236         byte apply(int i);
 237     }
 238 
 239     static byte[] fill(int s , ToByteF f) {
 240         return fill(new byte[s], f);
 241     }
 242 
 243     static byte[] fill(byte[] a, ToByteF f) {
 244         for (int i = 0; i < a.length; i++) {
 245             a[i] = f.apply(i);
 246         }
 247         return a;
 248     }
 249 
 250     @DontInline
 251     static ByteVector fromArray(byte[] a, int i) {
 252         return ByteVector.fromArray(SPECIES, a, i);
 253     }
 254 
 255     @DontInline
 256     static ByteVector fromArray(byte[] a, int i, VectorMask<Byte> m) {
 257         return ByteVector.fromArray(SPECIES, a, i, m);
 258     }
 259 
 260     @DontInline
 261     static void intoArray(ByteVector v, byte[] a, int i) {
 262         v.intoArray(a, i);
 263     }
 264 
 265     @DontInline
 266     static void intoArray(ByteVector v, byte[] a, int i, VectorMask<Byte> m) {
 267         v.intoArray(a, i, m);
 268     }
 269 
 270     @DontInline
 271     static ByteVector fromMemorySegment(MemorySegment a, int i, ByteOrder bo) {
 272         return ByteVector.fromMemorySegment(SPECIES, a, i, bo);
 273     }
 274 
 275     @DontInline
 276     static ByteVector fromMemorySegment(MemorySegment a, int i, ByteOrder bo, VectorMask<Byte> m) {
 277         return ByteVector.fromMemorySegment(SPECIES, a, i, bo, m);
 278     }
 279 
 280     @DontInline
 281     static void intoMemorySegment(ByteVector v, MemorySegment a, int i, ByteOrder bo) {
 282         v.intoMemorySegment(a, i, bo);
 283     }
 284 
 285     @DontInline
 286     static void intoMemorySegment(ByteVector v, MemorySegment a, int i, ByteOrder bo, VectorMask<Byte> m) {
 287         v.intoMemorySegment(a, i, bo, m);
 288     }
 289 
 290     @Test(dataProvider = "byteProvider")
 291     static void loadStoreArray(IntFunction<byte[]> fa) {
 292         byte[] a = fa.apply(SPECIES.length());
 293         byte[] r = new byte[a.length];
 294 
 295         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 296             for (int i = 0; i < a.length; i += SPECIES.length()) {
 297                 ByteVector av = ByteVector.fromArray(SPECIES, a, i);
 298                 av.intoArray(r, i);
 299             }
 300         }
 301         Assert.assertEquals(r, a);
 302     }
 303 
 304     @Test(dataProvider = "byteProviderForIOOBE")
 305     static void loadArrayIOOBE(IntFunction<byte[]> fa, IntFunction<Integer> fi) {
 306         byte[] a = fa.apply(SPECIES.length());
 307         byte[] r = new byte[a.length];
 308 
 309         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 310             for (int i = 0; i < a.length; i += SPECIES.length()) {
 311                 ByteVector av = fromArray(a, i);
 312                 av.intoArray(r, i);
 313             }
 314         }
 315 
 316         int index = fi.apply(a.length);
 317         boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length);
 318         try {
 319             fromArray(a, index);
 320             if (shouldFail) {
 321                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 322             }
 323         } catch (IndexOutOfBoundsException e) {
 324             if (!shouldFail) {
 325                 Assert.fail("Unexpected IndexOutOfBoundsException");
 326             }
 327         }
 328     }
 329 
 330     @Test(dataProvider = "byteProviderForIOOBE")
 331     static void storeArrayIOOBE(IntFunction<byte[]> fa, IntFunction<Integer> fi) {
 332         byte[] a = fa.apply(SPECIES.length());
 333         byte[] r = new byte[a.length];
 334 
 335         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 336             for (int i = 0; i < a.length; i += SPECIES.length()) {
 337                 ByteVector av = ByteVector.fromArray(SPECIES, a, i);
 338                 intoArray(av, r, i);
 339             }
 340         }
 341 
 342         int index = fi.apply(a.length);
 343         boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length);
 344         try {
 345             ByteVector av = ByteVector.fromArray(SPECIES, a, 0);
 346             intoArray(av, r, index);
 347             if (shouldFail) {
 348                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 349             }
 350         } catch (IndexOutOfBoundsException e) {
 351             if (!shouldFail) {
 352                 Assert.fail("Unexpected IndexOutOfBoundsException");
 353             }
 354         }
 355     }
 356 
 357 
 358     @Test(dataProvider = "byteMaskProvider")
 359     static void loadStoreMaskArray(IntFunction<byte[]> fa,
 360                                    IntFunction<boolean[]> fm) {
 361         byte[] a = fa.apply(SPECIES.length());
 362         byte[] r = new byte[a.length];
 363         boolean[] mask = fm.apply(SPECIES.length());
 364         VectorMask<Byte> vmask = VectorMask.fromValues(SPECIES, mask);
 365 
 366         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 367             for (int i = 0; i < a.length; i += SPECIES.length()) {
 368                 ByteVector av = ByteVector.fromArray(SPECIES, a, i, vmask);
 369                 av.intoArray(r, i);
 370             }
 371         }
 372         assertArraysEquals(r, a, mask);
 373 
 374 
 375         r = new byte[a.length];
 376 
 377         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 378             for (int i = 0; i < a.length; i += SPECIES.length()) {
 379                 ByteVector av = ByteVector.fromArray(SPECIES, a, i);
 380                 av.intoArray(r, i, vmask);
 381             }
 382         }
 383         assertArraysEquals(r, a, mask);
 384     }
 385 
 386     @Test(dataProvider = "byteMaskProviderForIOOBE")
 387     static void loadArrayMaskIOOBE(IntFunction<byte[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
 388         byte[] a = fa.apply(SPECIES.length());
 389         byte[] r = new byte[a.length];
 390         boolean[] mask = fm.apply(SPECIES.length());
 391         VectorMask<Byte> vmask = VectorMask.fromValues(SPECIES, mask);
 392 
 393         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 394             for (int i = 0; i < a.length; i += SPECIES.length()) {
 395                 ByteVector av = fromArray(a, i, vmask);
 396                 av.intoArray(r, i);
 397             }
 398         }
 399 
 400         int index = fi.apply(a.length);
 401         boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length);
 402         try {
 403             fromArray(a, index, vmask);
 404             if (shouldFail) {
 405                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 406             }
 407         } catch (IndexOutOfBoundsException e) {
 408             if (!shouldFail) {
 409                 Assert.fail("Unexpected IndexOutOfBoundsException");
 410             }
 411         }
 412     }
 413 
 414     @Test(dataProvider = "byteMaskProviderForIOOBE")
 415     static void storeArrayMaskIOOBE(IntFunction<byte[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
 416         byte[] a = fa.apply(SPECIES.length());
 417         byte[] r = new byte[a.length];
 418         boolean[] mask = fm.apply(SPECIES.length());
 419         VectorMask<Byte> vmask = VectorMask.fromValues(SPECIES, mask);
 420 
 421         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 422             for (int i = 0; i < a.length; i += SPECIES.length()) {
 423                 ByteVector av = ByteVector.fromArray(SPECIES, a, i);
 424                 intoArray(av, r, i, vmask);
 425             }
 426         }
 427 
 428         int index = fi.apply(a.length);
 429         boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length);
 430         try {
 431             ByteVector av = ByteVector.fromArray(SPECIES, a, 0);
 432             intoArray(av, a, index, vmask);
 433             if (shouldFail) {
 434                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 435             }
 436         } catch (IndexOutOfBoundsException e) {
 437             if (!shouldFail) {
 438                 Assert.fail("Unexpected IndexOutOfBoundsException");
 439             }
 440         }
 441     }
 442 
 443 
 444     @Test(dataProvider = "byteMaskProvider")
 445     static void loadStoreMask(IntFunction<byte[]> fa,
 446                               IntFunction<boolean[]> fm) {
 447         boolean[] mask = fm.apply(SPECIES.length());
 448         boolean[] r = new boolean[mask.length];
 449 
 450         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 451             for (int i = 0; i < mask.length; i += SPECIES.length()) {
 452                 VectorMask<Byte> vmask = VectorMask.fromArray(SPECIES, mask, i);
 453                 vmask.intoArray(r, i);
 454             }
 455         }
 456         Assert.assertEquals(r, mask);
 457     }
 458 
 459 
 460     @Test(dataProvider = "byteMemorySegmentProvider")
 461     static void loadStoreMemorySegment(IntFunction<byte[]> fa,
 462                                        IntFunction<MemorySegment> fb,
 463                                        ByteOrder bo) {
 464         MemorySegment a = toSegment(fa.apply(SPECIES.length()), fb);
 465         MemorySegment r = fb.apply((int) a.byteSize());
 466 
 467         int l = (int) a.byteSize();
 468         int s = SPECIES.vectorByteSize();
 469 
 470         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 471             for (int i = 0; i < l; i += s) {
 472                 ByteVector av = ByteVector.fromMemorySegment(SPECIES, a, i, bo);
 473                 av.intoMemorySegment(r, i, bo);
 474             }
 475         }
 476         long m = r.mismatch(a);
 477         Assert.assertEquals(m, -1, "Segments not equal");
 478     }
 479 
 480     @Test(dataProvider = "byteByteProviderForIOOBE")
 481     static void loadMemorySegmentIOOBE(IntFunction<byte[]> fa, IntFunction<Integer> fi) {
 482         MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Byte.SIZE));
 483         MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Byte.SIZE);
 484 
 485         int l = (int) a.byteSize();
 486         int s = SPECIES.vectorByteSize();
 487 
 488         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 489             for (int i = 0; i < l; i += s) {
 490                 ByteVector av = fromMemorySegment(a, i, ByteOrder.nativeOrder());
 491                 av.intoMemorySegment(r, i, ByteOrder.nativeOrder());
 492             }
 493         }
 494 
 495         int index = fi.apply((int) a.byteSize());
 496         boolean shouldFail = isIndexOutOfBounds(SPECIES.vectorByteSize(), index, (int) a.byteSize());
 497         try {
 498             fromMemorySegment(a, index, ByteOrder.nativeOrder());
 499             if (shouldFail) {
 500                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 501             }
 502         } catch (IndexOutOfBoundsException e) {
 503             if (!shouldFail) {
 504                 Assert.fail("Unexpected IndexOutOfBoundsException");
 505             }
 506         }
 507     }
 508 
 509     @Test(dataProvider = "byteByteProviderForIOOBE")
 510     static void storeMemorySegmentIOOBE(IntFunction<byte[]> fa, IntFunction<Integer> fi) {
 511         MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Byte.SIZE));
 512         MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Byte.SIZE);
 513 
 514         int l = (int) a.byteSize();
 515         int s = SPECIES.vectorByteSize();
 516 
 517         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 518             for (int i = 0; i < l; i += s) {
 519                 ByteVector av = ByteVector.fromMemorySegment(SPECIES, a, i, ByteOrder.nativeOrder());
 520                 intoMemorySegment(av, r, i, ByteOrder.nativeOrder());
 521             }
 522         }
 523 
 524         int index = fi.apply((int) a.byteSize());
 525         boolean shouldFail = isIndexOutOfBounds(SPECIES.vectorByteSize(), index, (int) a.byteSize());
 526         try {
 527             ByteVector av = ByteVector.fromMemorySegment(SPECIES, a, 0, ByteOrder.nativeOrder());
 528             intoMemorySegment(av, r, index, ByteOrder.nativeOrder());
 529             if (shouldFail) {
 530                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 531             }
 532         } catch (IndexOutOfBoundsException e) {
 533             if (!shouldFail) {
 534                 Assert.fail("Unexpected IndexOutOfBoundsException");
 535             }
 536         }
 537     }
 538 
 539     @Test(dataProvider = "byteMemorySegmentMaskProvider")
 540     static void loadStoreMemorySegmentMask(IntFunction<byte[]> fa,
 541                                            IntFunction<MemorySegment> fb,
 542                                            IntFunction<boolean[]> fm,
 543                                            ByteOrder bo) {
 544         byte[] _a = fa.apply(SPECIES.length());
 545         MemorySegment a = toSegment(_a, fb);
 546         MemorySegment r = fb.apply((int) a.byteSize());
 547         boolean[] mask = fm.apply(SPECIES.length());
 548         VectorMask<Byte> vmask = VectorMask.fromValues(SPECIES, mask);
 549 
 550         int l = (int) a.byteSize();
 551         int s = SPECIES.vectorByteSize();
 552 
 553         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 554             for (int i = 0; i < l; i += s) {
 555                 ByteVector av = ByteVector.fromMemorySegment(SPECIES, a, i, bo, vmask);
 556                 av.intoMemorySegment(r, i, bo);
 557             }
 558         }
 559         assertArraysEquals(segmentToArray(r), _a, mask);
 560 
 561 
 562         r = fb.apply((int) a.byteSize());
 563 
 564         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 565             for (int i = 0; i < l; i += s) {
 566                 ByteVector av = ByteVector.fromMemorySegment(SPECIES, a, i, bo);
 567                 av.intoMemorySegment(r, i, bo, vmask);
 568             }
 569         }
 570         assertArraysEquals(segmentToArray(r), _a, mask);
 571     }
 572 
 573     @Test(dataProvider = "byteByteMaskProviderForIOOBE")
 574     static void loadMemorySegmentMaskIOOBE(IntFunction<byte[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
 575         MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Byte.SIZE));
 576         MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Byte.SIZE);
 577         boolean[] mask = fm.apply(SPECIES.length());
 578         VectorMask<Byte> vmask = VectorMask.fromValues(SPECIES, mask);
 579 
 580         int l = (int) a.byteSize();
 581         int s = SPECIES.vectorByteSize();
 582 
 583         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 584             for (int i = 0; i < l; i += s) {
 585                 ByteVector av = fromMemorySegment(a, i, ByteOrder.nativeOrder(), vmask);
 586                 av.intoMemorySegment(r, i, ByteOrder.nativeOrder());
 587             }
 588         }
 589 
 590         int index = fi.apply((int) a.byteSize());
 591         boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, (int) a.byteSize(), SPECIES.elementSize() / 8);
 592         try {
 593             fromMemorySegment(a, index, ByteOrder.nativeOrder(), vmask);
 594             if (shouldFail) {
 595                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 596             }
 597         } catch (IndexOutOfBoundsException e) {
 598             if (!shouldFail) {
 599                 Assert.fail("Unexpected IndexOutOfBoundsException");
 600             }
 601         }
 602     }
 603 
 604     @Test(dataProvider = "byteByteMaskProviderForIOOBE")
 605     static void storeMemorySegmentMaskIOOBE(IntFunction<byte[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
 606         MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Byte.SIZE));
 607         MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Byte.SIZE);
 608         boolean[] mask = fm.apply(SPECIES.length());
 609         VectorMask<Byte> vmask = VectorMask.fromValues(SPECIES, mask);
 610 
 611         int l = (int) a.byteSize();
 612         int s = SPECIES.vectorByteSize();
 613 
 614         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 615             for (int i = 0; i < l; i += s) {
 616                 ByteVector av = ByteVector.fromMemorySegment(SPECIES, a, i, ByteOrder.nativeOrder());
 617                 intoMemorySegment(av, r, i, ByteOrder.nativeOrder(), vmask);
 618             }
 619         }
 620 
 621         int index = fi.apply((int) a.byteSize());
 622         boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, (int) a.byteSize(), SPECIES.elementSize() / 8);
 623         try {
 624             ByteVector av = ByteVector.fromMemorySegment(SPECIES, a, 0, ByteOrder.nativeOrder());
 625             intoMemorySegment(av, a, index, ByteOrder.nativeOrder(), vmask);
 626             if (shouldFail) {
 627                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 628             }
 629         } catch (IndexOutOfBoundsException e) {
 630             if (!shouldFail) {
 631                 Assert.fail("Unexpected IndexOutOfBoundsException");
 632             }
 633         }
 634     }
 635 
 636     @Test(dataProvider = "byteMemorySegmentProvider")
 637     static void loadStoreReadonlyMemorySegment(IntFunction<byte[]> fa,
 638                                                IntFunction<MemorySegment> fb,
 639                                                ByteOrder bo) {
 640         MemorySegment a = toSegment(fa.apply(SPECIES.length()), fb).asReadOnly();
 641 
 642         Assert.assertThrows(
 643                 UnsupportedOperationException.class,
 644                 () -> SPECIES.zero().intoMemorySegment(a, 0, bo)
 645         );
 646 
 647         Assert.assertThrows(
 648                 UnsupportedOperationException.class,
 649                 () -> SPECIES.zero().intoMemorySegment(a, 0, bo, SPECIES.maskAll(true))
 650         );
 651 
 652         Assert.assertThrows(
 653                 UnsupportedOperationException.class,
 654                 () -> SPECIES.zero().intoMemorySegment(a, 0, bo, SPECIES.maskAll(false))
 655         );
 656 
 657         VectorMask<Byte> m = SPECIES.shuffleFromOp(i -> i % 2 == 0 ? 1 : -1)
 658                 .laneIsValid();
 659         Assert.assertThrows(
 660                 UnsupportedOperationException.class,
 661                 () -> SPECIES.zero().intoMemorySegment(a, 0, bo, m)
 662         );
 663     }
 664 
 665 
 666     @Test(dataProvider = "maskProvider")
 667     static void loadStoreMask(IntFunction<boolean[]> fm) {
 668         boolean[] a = fm.apply(SPECIES.length());
 669         boolean[] r = new boolean[a.length];
 670 
 671         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 672             for (int i = 0; i < a.length; i += SPECIES.length()) {
 673                 VectorMask<Byte> vmask = SPECIES.loadMask(a, i);
 674                 vmask.intoArray(r, i);
 675             }
 676         }
 677         Assert.assertEquals(r, a);
 678     }
 679 
 680 
 681     @Test
 682     static void loadStoreShuffle() {
 683         IntUnaryOperator fn = a -> a + 5;
 684         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 685             var shuffle = VectorShuffle.fromOp(SPECIES, fn);
 686             int [] r = shuffle.toArray();
 687 
 688             int [] a = expectedShuffle(SPECIES.length(), fn);
 689             Assert.assertEquals(r, a);
 690        }
 691     }
 692 
 693 
 694 
 695     static void assertArraysEquals(boolean[] r, byte[] a) {
 696         int i = 0;
 697         try {
 698             for (; i < a.length; i++) {
 699                 Assert.assertEquals(r[i], (a[i] & 1) == 1);
 700             }
 701         } catch (AssertionError e) {
 702             Assert.assertEquals(r[i], (a[i] & 1) == 1, "at index #" + i);
 703         }
 704     }
 705 
 706     static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] mask) {
 707         int i = 0;
 708         try {
 709             for (; i < a.length; i++) {
 710                 Assert.assertEquals(r[i], mask[i % SPECIES.length()] && a[i]);
 711             }
 712         } catch (AssertionError e) {
 713             Assert.assertEquals(r[i], mask[i % SPECIES.length()] && a[i], "at index #" + i);
 714         }
 715     }
 716 
 717     static boolean[] convertToBooleanArray(byte[] a) {
 718         boolean[] r = new boolean[a.length];
 719 
 720         for (int i = 0; i < a.length; i++) {
 721             r[i] = (a[i] & 1) == 1;
 722         }
 723 
 724         return r;
 725     }
 726 
 727     @Test(dataProvider = "byteProvider")
 728     static void loadByteStoreBooleanArray(IntFunction<byte[]> fa) {
 729         byte[] a = fa.apply(SPECIES.length());
 730         boolean[] r = new boolean[a.length];
 731 
 732         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 733             for (int i = 0; i < a.length; i += SPECIES.length()) {
 734                 ByteVector av = ByteVector.fromArray(SPECIES, a, i);
 735                 av.intoBooleanArray(r, i);
 736             }
 737         }
 738         assertArraysEquals(r, a);
 739     }
 740 
 741     @Test(dataProvider = "byteProvider")
 742     static void loadStoreBooleanArray(IntFunction<byte[]> fa) {
 743         boolean[] a = convertToBooleanArray(fa.apply(SPECIES.length()));
 744         boolean[] r = new boolean[a.length];
 745 
 746         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 747             for (int i = 0; i < a.length; i += SPECIES.length()) {
 748                 ByteVector av = ByteVector.fromBooleanArray(SPECIES, a, i);
 749                 av.intoBooleanArray(r, i);
 750             }
 751         }
 752         Assert.assertEquals(r, a);
 753     }
 754 
 755     @Test(dataProvider = "byteMaskProvider")
 756     static void loadStoreMaskBooleanArray(IntFunction<byte[]> fa,
 757                                           IntFunction<boolean[]> fm) {
 758         boolean[] a = convertToBooleanArray(fa.apply(SPECIES.length()));
 759         boolean[] r = new boolean[a.length];
 760         boolean[] mask = fm.apply(SPECIES.length());
 761         VectorMask<Byte> vmask = VectorMask.fromValues(SPECIES, mask);
 762 
 763         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 764             for (int i = 0; i < a.length; i += SPECIES.length()) {
 765                 ByteVector av = ByteVector.fromBooleanArray(SPECIES, a, i, vmask);
 766                 av.intoBooleanArray(r, i);
 767             }
 768         }
 769         assertArraysEquals(r, a, mask);
 770 
 771 
 772         r = new boolean[a.length];
 773 
 774         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 775             for (int i = 0; i < a.length; i += SPECIES.length()) {
 776                 ByteVector av = ByteVector.fromBooleanArray(SPECIES, a, i);
 777                 av.intoBooleanArray(r, i, vmask);
 778             }
 779         }
 780         assertArraysEquals(r, a, mask);
 781     }
 782 
 783 
 784     // Gather/Scatter load/store tests
 785 
 786     static void assertGatherArraysEquals(byte[] r, byte[] a, int[] indexMap) {
 787         int i = 0;
 788         int j = 0;
 789         try {
 790             for (; i < a.length; i += SPECIES.length()) {
 791                 j = i;
 792                 for (; j < i + SPECIES.length(); j++) {
 793                     Assert.assertEquals(r[j], a[i + indexMap[j]]);
 794                 }
 795             }
 796         } catch (AssertionError e) {
 797             Assert.assertEquals(r[j], a[i + indexMap[j]], "at index #" + j);
 798         }
 799     }
 800 
 801     static void assertGatherArraysEquals(byte[] r, byte[] a, int[] indexMap, boolean[] mask) {
 802         int i = 0;
 803         int j = 0;
 804         try {
 805             for (; i < a.length; i += SPECIES.length()) {
 806                 j = i;
 807                 for (; j < i + SPECIES.length(); j++) {
 808                     Assert.assertEquals(r[j], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (byte) 0);
 809                 }
 810             }
 811         } catch (AssertionError e) {
 812             Assert.assertEquals(r[i], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (byte) 0, "at index #" + j);
 813         }
 814     }
 815 
 816     static void assertScatterArraysEquals(byte[] r, byte[] a, int[] indexMap, boolean[] mask) {
 817         byte[] expected = new byte[r.length];
 818 
 819         // Store before checking, since the same location may be stored to more than once
 820         for (int i = 0; i < a.length; i += SPECIES.length()) {
 821             for (int j = i; j < i + SPECIES.length(); j++) {
 822                 if (mask[j % SPECIES.length()]) {
 823                     expected[i + indexMap[j]] = a[j];
 824                 }
 825             }
 826         }
 827 
 828         Assert.assertEquals(r, expected);
 829     }
 830 
 831     static void assertScatterArraysEquals(byte[] r, byte[] a, int[] indexMap) {
 832         byte[] expected = new byte[r.length];
 833 
 834         // Store before checking, since the same location may be stored to more than once
 835         for (int i = 0; i < a.length; i += SPECIES.length()) {
 836             for (int j = i; j < i + SPECIES.length(); j++) {
 837                 expected[i + indexMap[j]] = a[j];
 838             }
 839         }
 840 
 841         Assert.assertEquals(r, expected);
 842     }
 843 
 844     @DataProvider
 845     public Object[][] gatherScatterProvider() {
 846         return INT_INDEX_GENERATORS.stream().
 847                 flatMap(fs -> BYTE_GENERATORS.stream().map(fa -> {
 848                     return new Object[] {fa, fs};
 849                 })).
 850                 toArray(Object[][]::new);
 851     }
 852 
 853     @DataProvider
 854     public Object[][] gatherScatterMaskProvider() {
 855         return BOOLEAN_MASK_GENERATORS.stream().
 856           flatMap(fs -> INT_INDEX_GENERATORS.stream().flatMap(fm ->
 857             BYTE_GENERATORS.stream().map(fa -> {
 858                     return new Object[] {fa, fm, fs};
 859             }))).
 860             toArray(Object[][]::new);
 861     }
 862 
 863 
 864     @Test(dataProvider = "gatherScatterProvider")
 865     static void gather(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs) {
 866         byte[] a = fa.apply(SPECIES.length());
 867         int[] b = fs.apply(a.length, SPECIES.length());
 868         byte[] r = new byte[a.length];
 869 
 870         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 871             for (int i = 0; i < a.length; i += SPECIES.length()) {
 872                 ByteVector av = ByteVector.fromArray(SPECIES, a, i, b, i);
 873                 av.intoArray(r, i);
 874             }
 875         }
 876 
 877         assertGatherArraysEquals(r, a, b);
 878     }
 879 
 880     @Test(dataProvider = "gatherScatterMaskProvider")
 881     static void gatherMask(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
 882         byte[] a = fa.apply(SPECIES.length());
 883         int[] b = fs.apply(a.length, SPECIES.length());
 884         byte[] r = new byte[a.length];
 885         boolean[] mask = fm.apply(SPECIES.length());
 886         VectorMask<Byte> vmask = VectorMask.fromArray(SPECIES, mask, 0);
 887 
 888         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 889             for (int i = 0; i < a.length; i += SPECIES.length()) {
 890                 ByteVector av = ByteVector.fromArray(SPECIES, a, i, b, i, vmask);
 891                 av.intoArray(r, i);
 892             }
 893         }
 894 
 895         assertGatherArraysEquals(r, a, b, mask);
 896     }
 897 
 898     @Test(dataProvider = "gatherScatterProvider")
 899     static void scatter(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs) {
 900         byte[] a = fa.apply(SPECIES.length());
 901         int[] b = fs.apply(a.length, SPECIES.length());
 902         byte[] r = new byte[a.length];
 903 
 904         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 905             for (int i = 0; i < a.length; i += SPECIES.length()) {
 906                 ByteVector av = ByteVector.fromArray(SPECIES, a, i);
 907                 av.intoArray(r, i, b, i);
 908             }
 909         }
 910 
 911         assertScatterArraysEquals(r, a, b);
 912     }
 913 
 914     @Test(dataProvider = "gatherScatterMaskProvider")
 915     static void scatterMask(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
 916         byte[] a = fa.apply(SPECIES.length());
 917         int[] b = fs.apply(a.length, SPECIES.length());
 918         byte[] r = new byte[a.length];
 919         boolean[] mask = fm.apply(SPECIES.length());
 920         VectorMask<Byte> vmask = VectorMask.fromArray(SPECIES, mask, 0);
 921 
 922         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 923             for (int i = 0; i < a.length; i += SPECIES.length()) {
 924                 ByteVector av = ByteVector.fromArray(SPECIES, a, i);
 925                 av.intoArray(r, i, b, i, vmask);
 926             }
 927         }
 928 
 929         assertScatterArraysEquals(r, a, b, mask);
 930     }
 931 
 932 
 933     static void assertGatherArraysEquals(boolean[] r, boolean[] a, int[] indexMap) {
 934         int i = 0;
 935         int j = 0;
 936         try {
 937             for (; i < a.length; i += SPECIES.length()) {
 938                 j = i;
 939                 for (; j < i + SPECIES.length(); j++) {
 940                     Assert.assertEquals(r[j], a[i + indexMap[j]]);
 941                 }
 942             }
 943         } catch (AssertionError e) {
 944             Assert.assertEquals(r[j], a[i + indexMap[j]], "at index #" + j);
 945         }
 946     }
 947 
 948     static void assertGatherArraysEquals(boolean[] r, boolean[] a, int[] indexMap, boolean[] mask) {
 949         int i = 0;
 950         int j = 0;
 951         try {
 952             for (; i < a.length; i += SPECIES.length()) {
 953                 j = i;
 954                 for (; j < i + SPECIES.length(); j++) {
 955                     Assert.assertEquals(r[j], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: false);
 956                 }
 957             }
 958         } catch (AssertionError e) {
 959             Assert.assertEquals(r[i], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: false, "at index #" + j);
 960         }
 961     }
 962 
 963     static void assertScatterArraysEquals(boolean[] r, boolean[] a, int[] indexMap, boolean[] mask) {
 964         boolean[] expected = new boolean[r.length];
 965 
 966         // Store before checking, since the same location may be stored to more than once
 967         for (int i = 0; i < a.length; i += SPECIES.length()) {
 968             for (int j = i; j < i + SPECIES.length(); j++) {
 969                 if (mask[j % SPECIES.length()]) {
 970                     expected[i + indexMap[j]] = a[j];
 971                 }
 972             }
 973         }
 974 
 975         Assert.assertEquals(r, expected);
 976     }
 977 
 978     static void assertScatterArraysEquals(boolean[] r, boolean[] a, int[] indexMap) {
 979         boolean[] expected = new boolean[r.length];
 980 
 981         // Store before checking, since the same location may be stored to more than once
 982         for (int i = 0; i < a.length; i += SPECIES.length()) {
 983             for (int j = i; j < i + SPECIES.length(); j++) {
 984                 expected[i + indexMap[j]] = a[j];
 985             }
 986         }
 987 
 988         Assert.assertEquals(r, expected);
 989     }
 990 
 991     @Test(dataProvider = "gatherScatterProvider")
 992     static void booleanGather(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs) {
 993         boolean[] a = convertToBooleanArray(fa.apply(SPECIES.length()));
 994         int[] b = fs.apply(a.length, SPECIES.length());
 995         boolean[] r = new boolean[a.length];
 996 
 997         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 998             for (int i = 0; i < a.length; i += SPECIES.length()) {
 999                 ByteVector av = ByteVector.fromBooleanArray(SPECIES, a, i, b, i);
1000                 av.intoBooleanArray(r, i);
1001             }
1002         }
1003 
1004         assertGatherArraysEquals(r, a, b);
1005     }
1006 
1007     @Test(dataProvider = "gatherScatterMaskProvider")
1008     static void booleanGatherMask(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
1009         boolean[] a = convertToBooleanArray(fa.apply(SPECIES.length()));
1010         int[] b = fs.apply(a.length, SPECIES.length());
1011         boolean[] r = new boolean[a.length];
1012         boolean[] mask = fm.apply(SPECIES.length());
1013         VectorMask<Byte> vmask = VectorMask.fromArray(SPECIES, mask, 0);
1014 
1015         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1016             for (int i = 0; i < a.length; i += SPECIES.length()) {
1017                 ByteVector av = ByteVector.fromBooleanArray(SPECIES, a, i, b, i, vmask);
1018                 av.intoBooleanArray(r, i);
1019             }
1020         }
1021 
1022         assertGatherArraysEquals(r, a, b, mask);
1023     }
1024 
1025     @Test(dataProvider = "gatherScatterProvider")
1026     static void booleanScatter(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs) {
1027         boolean[] a = convertToBooleanArray(fa.apply(SPECIES.length()));
1028         int[] b = fs.apply(a.length, SPECIES.length());
1029         boolean[] r = new boolean[a.length];
1030 
1031         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1032             for (int i = 0; i < a.length; i += SPECIES.length()) {
1033                 ByteVector av = ByteVector.fromBooleanArray(SPECIES, a, i);
1034                 av.intoBooleanArray(r, i, b, i);
1035             }
1036         }
1037 
1038         assertScatterArraysEquals(r, a, b);
1039     }
1040 
1041     @Test(dataProvider = "gatherScatterMaskProvider")
1042     static void booleanScatterMask(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
1043         boolean[] a = convertToBooleanArray(fa.apply(SPECIES.length()));
1044         int[] b = fs.apply(a.length, SPECIES.length());
1045         boolean[] r = new boolean[a.length];
1046         boolean[] mask = fm.apply(SPECIES.length());
1047         VectorMask<Byte> vmask = VectorMask.fromArray(SPECIES, mask, 0);
1048 
1049         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1050             for (int i = 0; i < a.length; i += SPECIES.length()) {
1051                 ByteVector av = ByteVector.fromBooleanArray(SPECIES, a, i);
1052                 av.intoBooleanArray(r, i, b, i, vmask);
1053             }
1054         }
1055 
1056         assertScatterArraysEquals(r, a, b, mask);
1057     }
1058 
1059 }