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