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 Short128VectorLoadStoreTests
  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.ShortVector;
  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 Short128VectorLoadStoreTests extends AbstractVectorLoadStoreTest {
  52     static final VectorSpecies<Short> SPECIES =
  53                 ShortVector.SPECIES_128;
  54 
  55     static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 100);
  56 
  57     static final ValueLayout.OfShort ELEMENT_LAYOUT = ValueLayout.JAVA_SHORT.withByteAlignment(1);
  58 
  59 
  60     static final int BUFFER_REPS = Integer.getInteger("jdk.incubator.vector.test.buffer-vectors", 25000 / 128);
  61 
  62     static void assertArraysEquals(short[] r, short[] 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] : (short) 0);
  67             }
  68         } catch (AssertionError e) {
  69             Assert.assertEquals(r[i], mask[i % SPECIES.length()] ? a[i] : (short) 0, "at index #" + i);
  70         }
  71     }
  72 
  73     static final List<IntFunction<short[]>> SHORT_GENERATORS = List.of(
  74             withToString("short[i * 5]", (int s) -> {
  75                 return fill(s * BUFFER_REPS,
  76                             i -> (short)(i * 5));
  77             }),
  78             withToString("short[i + 1]", (int s) -> {
  79                 return fill(s * BUFFER_REPS,
  80                             i -> (((short)(i + 1) == 0) ? 1 : (short)(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[][] shortProvider() {
 142         return SHORT_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[][] shortProviderForIOOBE() {
 156         var f = SHORT_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[][] shortMaskProvider() {
 165         return BOOLEAN_MASK_GENERATORS.stream().
 166                 flatMap(fm -> SHORT_GENERATORS.stream().map(fa -> {
 167                     return new Object[] {fa, fm};
 168                 })).
 169                 toArray(Object[][]::new);
 170     }
 171 
 172     @DataProvider
 173     public Object[][] shortMaskProviderForIOOBE() {
 174         var f = SHORT_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[][] shortMemorySegmentProvider() {
 184         return SHORT_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[][] shortMemorySegmentMaskProvider() {
 194         return BOOLEAN_MASK_GENERATORS.stream().
 195                 flatMap(fm -> SHORT_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[][] shortByteProviderForIOOBE() {
 205         var f = SHORT_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[][] shortByteMaskProviderForIOOBE() {
 214         var f = SHORT_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(short[] 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 short[] segmentToArray(MemorySegment ms) {
 231         return ms.toArray(ELEMENT_LAYOUT);
 232     }
 233 
 234 
 235     interface ToShortF {
 236         short apply(int i);
 237     }
 238 
 239     static short[] fill(int s , ToShortF f) {
 240         return fill(new short[s], f);
 241     }
 242 
 243     static short[] fill(short[] a, ToShortF 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 ShortVector fromArray(short[] a, int i) {
 252         return ShortVector.fromArray(SPECIES, a, i);
 253     }
 254 
 255     @DontInline
 256     static ShortVector fromArray(short[] a, int i, VectorMask<Short> m) {
 257         return ShortVector.fromArray(SPECIES, a, i, m);
 258     }
 259 
 260     @DontInline
 261     static void intoArray(ShortVector v, short[] a, int i) {
 262         v.intoArray(a, i);
 263     }
 264 
 265     @DontInline
 266     static void intoArray(ShortVector v, short[] a, int i, VectorMask<Short> m) {
 267         v.intoArray(a, i, m);
 268     }
 269 
 270     @DontInline
 271     static ShortVector fromMemorySegment(MemorySegment a, int i, ByteOrder bo) {
 272         return ShortVector.fromMemorySegment(SPECIES, a, i, bo);
 273     }
 274 
 275     @DontInline
 276     static ShortVector fromMemorySegment(MemorySegment a, int i, ByteOrder bo, VectorMask<Short> m) {
 277         return ShortVector.fromMemorySegment(SPECIES, a, i, bo, m);
 278     }
 279 
 280     @DontInline
 281     static void intoMemorySegment(ShortVector v, MemorySegment a, int i, ByteOrder bo) {
 282         v.intoMemorySegment(a, i, bo);
 283     }
 284 
 285     @DontInline
 286     static void intoMemorySegment(ShortVector v, MemorySegment a, int i, ByteOrder bo, VectorMask<Short> m) {
 287         v.intoMemorySegment(a, i, bo, m);
 288     }
 289 
 290     @Test(dataProvider = "shortProvider")
 291     static void loadStoreArray(IntFunction<short[]> fa) {
 292         short[] a = fa.apply(SPECIES.length());
 293         short[] r = new short[a.length];
 294 
 295         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 296             for (int i = 0; i < a.length; i += SPECIES.length()) {
 297                 ShortVector av = ShortVector.fromArray(SPECIES, a, i);
 298                 av.intoArray(r, i);
 299             }
 300         }
 301         Assert.assertEquals(r, a);
 302     }
 303 
 304     @Test(dataProvider = "shortProviderForIOOBE")
 305     static void loadArrayIOOBE(IntFunction<short[]> fa, IntFunction<Integer> fi) {
 306         short[] a = fa.apply(SPECIES.length());
 307         short[] r = new short[a.length];
 308 
 309         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 310             for (int i = 0; i < a.length; i += SPECIES.length()) {
 311                 ShortVector 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 = "shortProviderForIOOBE")
 331     static void storeArrayIOOBE(IntFunction<short[]> fa, IntFunction<Integer> fi) {
 332         short[] a = fa.apply(SPECIES.length());
 333         short[] r = new short[a.length];
 334 
 335         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 336             for (int i = 0; i < a.length; i += SPECIES.length()) {
 337                 ShortVector av = ShortVector.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             ShortVector av = ShortVector.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 = "shortMaskProvider")
 359     static void loadStoreMaskArray(IntFunction<short[]> fa,
 360                                    IntFunction<boolean[]> fm) {
 361         short[] a = fa.apply(SPECIES.length());
 362         short[] r = new short[a.length];
 363         boolean[] mask = fm.apply(SPECIES.length());
 364         VectorMask<Short> 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                 ShortVector av = ShortVector.fromArray(SPECIES, a, i, vmask);
 369                 av.intoArray(r, i);
 370             }
 371         }
 372         assertArraysEquals(r, a, mask);
 373 
 374 
 375         r = new short[a.length];
 376 
 377         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 378             for (int i = 0; i < a.length; i += SPECIES.length()) {
 379                 ShortVector av = ShortVector.fromArray(SPECIES, a, i);
 380                 av.intoArray(r, i, vmask);
 381             }
 382         }
 383         assertArraysEquals(r, a, mask);
 384     }
 385 
 386     @Test(dataProvider = "shortMaskProviderForIOOBE")
 387     static void loadArrayMaskIOOBE(IntFunction<short[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
 388         short[] a = fa.apply(SPECIES.length());
 389         short[] r = new short[a.length];
 390         boolean[] mask = fm.apply(SPECIES.length());
 391         VectorMask<Short> 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                 ShortVector 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 = "shortMaskProviderForIOOBE")
 415     static void storeArrayMaskIOOBE(IntFunction<short[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
 416         short[] a = fa.apply(SPECIES.length());
 417         short[] r = new short[a.length];
 418         boolean[] mask = fm.apply(SPECIES.length());
 419         VectorMask<Short> 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                 ShortVector av = ShortVector.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             ShortVector av = ShortVector.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 = "shortMaskProvider")
 445     static void loadStoreMask(IntFunction<short[]> 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<Short> vmask = VectorMask.fromArray(SPECIES, mask, i);
 453                 vmask.intoArray(r, i);
 454             }
 455         }
 456         Assert.assertEquals(r, mask);
 457     }
 458 
 459 
 460     @Test(dataProvider = "shortMemorySegmentProvider")
 461     static void loadStoreMemorySegment(IntFunction<short[]> 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                 ShortVector av = ShortVector.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 = "shortByteProviderForIOOBE")
 481     static void loadMemorySegmentIOOBE(IntFunction<short[]> fa, IntFunction<Integer> fi) {
 482         MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Short.SIZE));
 483         MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Short.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                 ShortVector 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 = "shortByteProviderForIOOBE")
 510     static void storeMemorySegmentIOOBE(IntFunction<short[]> fa, IntFunction<Integer> fi) {
 511         MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Short.SIZE));
 512         MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Short.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                 ShortVector av = ShortVector.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             ShortVector av = ShortVector.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 = "shortMemorySegmentMaskProvider")
 540     static void loadStoreMemorySegmentMask(IntFunction<short[]> fa,
 541                                            IntFunction<MemorySegment> fb,
 542                                            IntFunction<boolean[]> fm,
 543                                            ByteOrder bo) {
 544         short[] _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<Short> 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                 ShortVector av = ShortVector.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                 ShortVector av = ShortVector.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 = "shortByteMaskProviderForIOOBE")
 574     static void loadMemorySegmentMaskIOOBE(IntFunction<short[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
 575         MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Short.SIZE));
 576         MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Short.SIZE);
 577         boolean[] mask = fm.apply(SPECIES.length());
 578         VectorMask<Short> 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                 ShortVector 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 = "shortByteMaskProviderForIOOBE")
 605     static void storeMemorySegmentMaskIOOBE(IntFunction<short[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
 606         MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Short.SIZE));
 607         MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Short.SIZE);
 608         boolean[] mask = fm.apply(SPECIES.length());
 609         VectorMask<Short> 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                 ShortVector av = ShortVector.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             ShortVector av = ShortVector.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 = "shortMemorySegmentProvider")
 637     static void loadStoreReadonlyMemorySegment(IntFunction<short[]> 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<Short> 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<Short> 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     static void assertArraysEquals(char[] a, char[] r, boolean[] mask) {
 695         int i = 0;
 696         try {
 697             for (; i < a.length; i++) {
 698                 Assert.assertEquals(mask[i % SPECIES.length()] ? a[i] : (char) 0, r[i]);
 699             }
 700         } catch (AssertionError e) {
 701             Assert.assertEquals(mask[i % SPECIES.length()] ? a[i] : (char) 0, r[i], "at index #" + i);
 702         }
 703     }
 704 
 705     static final List<IntFunction<char[]>> CHAR_GENERATORS = List.of(
 706             withToString("char[i * 5]", (int s) -> {
 707                 return fillChar(s * BUFFER_REPS,
 708                             i -> (char)(i * 5));
 709             }),
 710             withToString("char[i + 1]", (int s) -> {
 711                 return fillChar(s * BUFFER_REPS,
 712                             i -> (((char)(i + 1) == 0) ? 1 : (char)(i + 1)));
 713             })
 714     );
 715 
 716     @DataProvider
 717     public Object[][] charProvider() {
 718         return CHAR_GENERATORS.stream().
 719                 map(f -> new Object[]{f}).
 720                 toArray(Object[][]::new);
 721     }
 722 
 723     @DataProvider
 724     public Object[][] charProviderForIOOBE() {
 725         var f = CHAR_GENERATORS.get(0);
 726         return INDEX_GENERATORS.stream().map(fi -> {
 727                     return new Object[] {f, fi};
 728                 }).
 729                 toArray(Object[][]::new);
 730     }
 731 
 732     @DataProvider
 733     public Object[][] charMaskProvider() {
 734         return BOOLEAN_MASK_GENERATORS.stream().
 735                 flatMap(fm -> CHAR_GENERATORS.stream().map(fa -> {
 736                     return new Object[] {fa, fm};
 737                 })).
 738                 toArray(Object[][]::new);
 739     }
 740 
 741     @DataProvider
 742     public Object[][] charMaskProviderForIOOBE() {
 743         var f = CHAR_GENERATORS.get(0);
 744         return BOOLEAN_MASK_GENERATORS.stream().
 745                 flatMap(fm -> INDEX_GENERATORS.stream().map(fi -> {
 746                     return new Object[] {f, fi, fm};
 747                 })).
 748                 toArray(Object[][]::new);
 749     }
 750 
 751     interface ToCharF {
 752         char apply(int i);
 753     }
 754 
 755     static char[] fillChar(int s , ToCharF f) {
 756         return fillChar(new char[s], f);
 757     }
 758 
 759     static char[] fillChar(char[] a, ToCharF f) {
 760         for (int i = 0; i < a.length; i++) {
 761             a[i] = f.apply(i);
 762         }
 763         return a;
 764     }
 765 
 766     @DontInline
 767     static ShortVector fromCharArray(char[] a, int i) {
 768         return ShortVector.fromCharArray(SPECIES, a, i);
 769     }
 770 
 771     @DontInline
 772     static ShortVector fromCharArray(char[] a, int i, VectorMask<Short> m) {
 773         return ShortVector.fromCharArray(SPECIES, a, i, m);
 774     }
 775 
 776     @DontInline
 777     static void intoCharArray(ShortVector v, char[] a, int i) {
 778         v.intoCharArray(a, i);
 779     }
 780 
 781     @DontInline
 782     static void intoCharArray(ShortVector v, char[] a, int i, VectorMask<Short> m) {
 783         v.intoCharArray(a, i, m);
 784     }
 785 
 786     @Test(dataProvider = "charProvider")
 787     static void loadStoreCharArray(IntFunction<char[]> fa) {
 788         char[] a = fa.apply(SPECIES.length());
 789         char[] r = new char[a.length];
 790 
 791         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 792             for (int i = 0; i < a.length; i += SPECIES.length()) {
 793                 ShortVector av = ShortVector.fromCharArray(SPECIES, a, i);
 794                 av.intoCharArray(r, i);
 795             }
 796         }
 797         Assert.assertEquals(a, r);
 798     }
 799 
 800     @Test(dataProvider = "charProviderForIOOBE")
 801     static void loadCharArrayIOOBE(IntFunction<char[]> fa, IntFunction<Integer> fi) {
 802         char[] a = fa.apply(SPECIES.length());
 803         char[] r = new char[a.length];
 804 
 805         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 806             for (int i = 0; i < a.length; i += SPECIES.length()) {
 807                 ShortVector av = fromCharArray(a, i);
 808                 av.intoCharArray(r, i);
 809             }
 810         }
 811 
 812         int index = fi.apply(a.length);
 813         boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length);
 814         try {
 815             fromCharArray(a, index);
 816             if (shouldFail) {
 817                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 818             }
 819         } catch (IndexOutOfBoundsException e) {
 820             if (!shouldFail) {
 821                 Assert.fail("Unexpected IndexOutOfBoundsException");
 822             }
 823         }
 824     }
 825 
 826     @Test(dataProvider = "charProviderForIOOBE")
 827     static void storeCharArrayIOOBE(IntFunction<char[]> fa, IntFunction<Integer> fi) {
 828         char[] a = fa.apply(SPECIES.length());
 829         char[] r = new char[a.length];
 830 
 831         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 832             for (int i = 0; i < a.length; i += SPECIES.length()) {
 833                 ShortVector av = ShortVector.fromCharArray(SPECIES, a, i);
 834                 intoCharArray(av, r, i);
 835             }
 836         }
 837 
 838         int index = fi.apply(a.length);
 839         boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length);
 840         try {
 841             ShortVector av = ShortVector.fromCharArray(SPECIES, a, 0);
 842             intoCharArray(av, r, index);
 843             if (shouldFail) {
 844                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 845             }
 846         } catch (IndexOutOfBoundsException e) {
 847             if (!shouldFail) {
 848                 Assert.fail("Unexpected IndexOutOfBoundsException");
 849             }
 850         }
 851     }
 852 
 853     @Test(dataProvider = "charMaskProvider")
 854     static void loadStoreMaskCharArray(IntFunction<char[]> fa,
 855                                        IntFunction<boolean[]> fm) {
 856         char[] a = fa.apply(SPECIES.length());
 857         char[] r = new char[a.length];
 858         boolean[] mask = fm.apply(SPECIES.length());
 859         VectorMask<Short> vmask = VectorMask.fromValues(SPECIES, mask);
 860 
 861         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 862             for (int i = 0; i < a.length; i += SPECIES.length()) {
 863                 ShortVector av = ShortVector.fromCharArray(SPECIES, a, i, vmask);
 864                 av.intoCharArray(r, i);
 865             }
 866         }
 867         assertArraysEquals(a, r, mask);
 868 
 869 
 870         r = new char[a.length];
 871 
 872         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 873             for (int i = 0; i < a.length; i += SPECIES.length()) {
 874                 ShortVector av = ShortVector.fromCharArray(SPECIES, a, i);
 875                 av.intoCharArray(r, i, vmask);
 876             }
 877         }
 878         assertArraysEquals(a, r, mask);
 879     }
 880 
 881     @Test(dataProvider = "charMaskProviderForIOOBE")
 882     static void loadCharArrayMaskIOOBE(IntFunction<char[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
 883         char[] a = fa.apply(SPECIES.length());
 884         char[] r = new char[a.length];
 885         boolean[] mask = fm.apply(SPECIES.length());
 886         VectorMask<Short> vmask = VectorMask.fromValues(SPECIES, mask);
 887 
 888         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 889             for (int i = 0; i < a.length; i += SPECIES.length()) {
 890                 ShortVector av = fromCharArray(a, i, vmask);
 891                 av.intoCharArray(r, i);
 892             }
 893         }
 894 
 895         int index = fi.apply(a.length);
 896         boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length);
 897         try {
 898             fromCharArray(a, index, vmask);
 899             if (shouldFail) {
 900                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 901             }
 902         } catch (IndexOutOfBoundsException e) {
 903             if (!shouldFail) {
 904                 Assert.fail("Unexpected IndexOutOfBoundsException");
 905             }
 906         }
 907     }
 908 
 909     @Test(dataProvider = "charMaskProviderForIOOBE")
 910     static void storeCharArrayMaskIOOBE(IntFunction<char[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
 911         char[] a = fa.apply(SPECIES.length());
 912         char[] r = new char[a.length];
 913         boolean[] mask = fm.apply(SPECIES.length());
 914         VectorMask<Short> vmask = VectorMask.fromValues(SPECIES, mask);
 915 
 916         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 917             for (int i = 0; i < a.length; i += SPECIES.length()) {
 918                 ShortVector av = ShortVector.fromCharArray(SPECIES, a, i);
 919                 intoCharArray(av, r, i, vmask);
 920             }
 921         }
 922 
 923         int index = fi.apply(a.length);
 924         boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length);
 925         try {
 926             ShortVector av = ShortVector.fromCharArray(SPECIES, a, 0);
 927             intoCharArray(av, a, index, vmask);
 928             if (shouldFail) {
 929                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 930             }
 931         } catch (IndexOutOfBoundsException e) {
 932             if (!shouldFail) {
 933                 Assert.fail("Unexpected IndexOutOfBoundsException");
 934             }
 935         }
 936     }
 937 
 938 
 939 
 940 
 941     // Gather/Scatter load/store tests
 942 
 943     static void assertGatherArraysEquals(short[] r, short[] a, int[] indexMap) {
 944         int i = 0;
 945         int j = 0;
 946         try {
 947             for (; i < a.length; i += SPECIES.length()) {
 948                 j = i;
 949                 for (; j < i + SPECIES.length(); j++) {
 950                     Assert.assertEquals(r[j], a[i + indexMap[j]]);
 951                 }
 952             }
 953         } catch (AssertionError e) {
 954             Assert.assertEquals(r[j], a[i + indexMap[j]], "at index #" + j);
 955         }
 956     }
 957 
 958     static void assertGatherArraysEquals(short[] r, short[] a, int[] indexMap, boolean[] mask) {
 959         int i = 0;
 960         int j = 0;
 961         try {
 962             for (; i < a.length; i += SPECIES.length()) {
 963                 j = i;
 964                 for (; j < i + SPECIES.length(); j++) {
 965                     Assert.assertEquals(r[j], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (short) 0);
 966                 }
 967             }
 968         } catch (AssertionError e) {
 969             Assert.assertEquals(r[i], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (short) 0, "at index #" + j);
 970         }
 971     }
 972 
 973     static void assertScatterArraysEquals(short[] r, short[] a, int[] indexMap, boolean[] mask) {
 974         short[] expected = new short[r.length];
 975 
 976         // Store before checking, since the same location may be stored to more than once
 977         for (int i = 0; i < a.length; i += SPECIES.length()) {
 978             for (int j = i; j < i + SPECIES.length(); j++) {
 979                 if (mask[j % SPECIES.length()]) {
 980                     expected[i + indexMap[j]] = a[j];
 981                 }
 982             }
 983         }
 984 
 985         Assert.assertEquals(r, expected);
 986     }
 987 
 988     static void assertScatterArraysEquals(short[] r, short[] a, int[] indexMap) {
 989         short[] expected = new short[r.length];
 990 
 991         // Store before checking, since the same location may be stored to more than once
 992         for (int i = 0; i < a.length; i += SPECIES.length()) {
 993             for (int j = i; j < i + SPECIES.length(); j++) {
 994                 expected[i + indexMap[j]] = a[j];
 995             }
 996         }
 997 
 998         Assert.assertEquals(r, expected);
 999     }
1000 
1001     @DataProvider
1002     public Object[][] gatherScatterProvider() {
1003         return INT_INDEX_GENERATORS.stream().
1004                 flatMap(fs -> SHORT_GENERATORS.stream().map(fa -> {
1005                     return new Object[] {fa, fs};
1006                 })).
1007                 toArray(Object[][]::new);
1008     }
1009 
1010     @DataProvider
1011     public Object[][] gatherScatterMaskProvider() {
1012         return BOOLEAN_MASK_GENERATORS.stream().
1013           flatMap(fs -> INT_INDEX_GENERATORS.stream().flatMap(fm ->
1014             SHORT_GENERATORS.stream().map(fa -> {
1015                     return new Object[] {fa, fm, fs};
1016             }))).
1017             toArray(Object[][]::new);
1018     }
1019 
1020 
1021     @Test(dataProvider = "gatherScatterProvider")
1022     static void gather(IntFunction<short[]> fa, BiFunction<Integer,Integer,int[]> fs) {
1023         short[] a = fa.apply(SPECIES.length());
1024         int[] b = fs.apply(a.length, SPECIES.length());
1025         short[] r = new short[a.length];
1026 
1027         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1028             for (int i = 0; i < a.length; i += SPECIES.length()) {
1029                 ShortVector av = ShortVector.fromArray(SPECIES, a, i, b, i);
1030                 av.intoArray(r, i);
1031             }
1032         }
1033 
1034         assertGatherArraysEquals(r, a, b);
1035     }
1036 
1037     @Test(dataProvider = "gatherScatterMaskProvider")
1038     static void gatherMask(IntFunction<short[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
1039         short[] a = fa.apply(SPECIES.length());
1040         int[] b = fs.apply(a.length, SPECIES.length());
1041         short[] r = new short[a.length];
1042         boolean[] mask = fm.apply(SPECIES.length());
1043         VectorMask<Short> vmask = VectorMask.fromArray(SPECIES, mask, 0);
1044 
1045         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1046             for (int i = 0; i < a.length; i += SPECIES.length()) {
1047                 ShortVector av = ShortVector.fromArray(SPECIES, a, i, b, i, vmask);
1048                 av.intoArray(r, i);
1049             }
1050         }
1051 
1052         assertGatherArraysEquals(r, a, b, mask);
1053     }
1054 
1055     @Test(dataProvider = "gatherScatterProvider")
1056     static void scatter(IntFunction<short[]> fa, BiFunction<Integer,Integer,int[]> fs) {
1057         short[] a = fa.apply(SPECIES.length());
1058         int[] b = fs.apply(a.length, SPECIES.length());
1059         short[] r = new short[a.length];
1060 
1061         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1062             for (int i = 0; i < a.length; i += SPECIES.length()) {
1063                 ShortVector av = ShortVector.fromArray(SPECIES, a, i);
1064                 av.intoArray(r, i, b, i);
1065             }
1066         }
1067 
1068         assertScatterArraysEquals(r, a, b);
1069     }
1070 
1071     @Test(dataProvider = "gatherScatterMaskProvider")
1072     static void scatterMask(IntFunction<short[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
1073         short[] a = fa.apply(SPECIES.length());
1074         int[] b = fs.apply(a.length, SPECIES.length());
1075         short[] r = new short[a.length];
1076         boolean[] mask = fm.apply(SPECIES.length());
1077         VectorMask<Short> vmask = VectorMask.fromArray(SPECIES, mask, 0);
1078 
1079         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1080             for (int i = 0; i < a.length; i += SPECIES.length()) {
1081                 ShortVector av = ShortVector.fromArray(SPECIES, a, i);
1082                 av.intoArray(r, i, b, i, vmask);
1083             }
1084         }
1085 
1086         assertScatterArraysEquals(r, a, b, mask);
1087     }
1088 
1089     static void assertGatherArraysEquals(char[] r, char[] a, int[] indexMap) {
1090         int i = 0;
1091         int j = 0;
1092         try {
1093             for (; i < a.length; i += SPECIES.length()) {
1094                 j = i;
1095                 for (; j < i + SPECIES.length(); j++) {
1096                     Assert.assertEquals(r[j], a[i + indexMap[j]]);
1097                 }
1098             }
1099         } catch (AssertionError e) {
1100             Assert.assertEquals(r[j], a[i + indexMap[j]], "at index #" + j);
1101         }
1102     }
1103 
1104     static void assertGatherArraysEquals(char[] r, char[] a, int[] indexMap, boolean[] mask) {
1105         int i = 0;
1106         int j = 0;
1107         try {
1108             for (; i < a.length; i += SPECIES.length()) {
1109                 j = i;
1110                 for (; j < i + SPECIES.length(); j++) {
1111                     Assert.assertEquals(r[j], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (char) 0);
1112                 }
1113             }
1114         } catch (AssertionError e) {
1115             Assert.assertEquals(r[i], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (char) 0, "at index #" + j);
1116         }
1117     }
1118 
1119     static void assertScatterArraysEquals(char[] r, char[] a, int[] indexMap, boolean[] mask) {
1120         char[] expected = new char[r.length];
1121 
1122         // Store before checking, since the same location may be stored to more than once
1123         for (int i = 0; i < a.length; i += SPECIES.length()) {
1124             for (int j = i; j < i + SPECIES.length(); j++) {
1125                 if (mask[j % SPECIES.length()]) {
1126                     expected[i + indexMap[j]] = a[j];
1127                 }
1128             }
1129         }
1130 
1131         Assert.assertEquals(r, expected);
1132     }
1133 
1134     static void assertScatterArraysEquals(char[] r, char[] a, int[] indexMap) {
1135         char[] expected = new char[r.length];
1136 
1137         // Store before checking, since the same location may be stored to more than once
1138         for (int i = 0; i < a.length; i += SPECIES.length()) {
1139             for (int j = i; j < i + SPECIES.length(); j++) {
1140                 expected[i + indexMap[j]] = a[j];
1141             }
1142         }
1143 
1144         Assert.assertEquals(r, expected);
1145     }
1146 
1147     @DataProvider
1148     public Object[][] charGatherScatterProvider() {
1149         return INT_INDEX_GENERATORS.stream().
1150                 flatMap(fs -> CHAR_GENERATORS.stream().map(fa -> {
1151                     return new Object[] {fa, fs};
1152                 })).
1153                 toArray(Object[][]::new);
1154     }
1155 
1156     @DataProvider
1157     public Object[][] charGatherScatterMaskProvider() {
1158         return BOOLEAN_MASK_GENERATORS.stream().
1159           flatMap(fs -> INT_INDEX_GENERATORS.stream().flatMap(fm ->
1160             CHAR_GENERATORS.stream().map(fa -> {
1161                     return new Object[] {fa, fm, fs};
1162             }))).
1163             toArray(Object[][]::new);
1164     }
1165 
1166 
1167     @Test(dataProvider = "charGatherScatterProvider")
1168     static void charGather(IntFunction<char[]> fa, BiFunction<Integer,Integer,int[]> fs) {
1169         char[] a = fa.apply(SPECIES.length());
1170         int[] b = fs.apply(a.length, SPECIES.length());
1171         char[] r = new char[a.length];
1172 
1173         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1174             for (int i = 0; i < a.length; i += SPECIES.length()) {
1175                 ShortVector av = ShortVector.fromCharArray(SPECIES, a, i, b, i);
1176                 av.intoCharArray(r, i);
1177             }
1178         }
1179 
1180         assertGatherArraysEquals(r, a, b);
1181     }
1182 
1183     @Test(dataProvider = "charGatherScatterMaskProvider")
1184     static void charGatherMask(IntFunction<char[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
1185         char[] a = fa.apply(SPECIES.length());
1186         int[] b = fs.apply(a.length, SPECIES.length());
1187         char[] r = new char[a.length];
1188         boolean[] mask = fm.apply(SPECIES.length());
1189         VectorMask<Short> vmask = VectorMask.fromArray(SPECIES, mask, 0);
1190 
1191         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1192             for (int i = 0; i < a.length; i += SPECIES.length()) {
1193                 ShortVector av = ShortVector.fromCharArray(SPECIES, a, i, b, i, vmask);
1194                 av.intoCharArray(r, i);
1195             }
1196         }
1197 
1198         assertGatherArraysEquals(r, a, b, mask);
1199     }
1200 
1201     @Test(dataProvider = "charGatherScatterProvider")
1202     static void charScatter(IntFunction<char[]> fa, BiFunction<Integer,Integer,int[]> fs) {
1203         char[] a = fa.apply(SPECIES.length());
1204         int[] b = fs.apply(a.length, SPECIES.length());
1205         char[] r = new char[a.length];
1206 
1207         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1208             for (int i = 0; i < a.length; i += SPECIES.length()) {
1209                 ShortVector av = ShortVector.fromCharArray(SPECIES, a, i);
1210                 av.intoCharArray(r, i, b, i);
1211             }
1212         }
1213 
1214         assertScatterArraysEquals(r, a, b);
1215     }
1216 
1217     @Test(dataProvider = "charGatherScatterMaskProvider")
1218     static void charScatterMask(IntFunction<char[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
1219         char[] a = fa.apply(SPECIES.length());
1220         int[] b = fs.apply(a.length, SPECIES.length());
1221         char[] r = new char[a.length];
1222         boolean[] mask = fm.apply(SPECIES.length());
1223         VectorMask<Short> vmask = VectorMask.fromArray(SPECIES, mask, 0);
1224 
1225         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1226             for (int i = 0; i < a.length; i += SPECIES.length()) {
1227                 ShortVector av = ShortVector.fromCharArray(SPECIES, a, i);
1228                 av.intoCharArray(r, i, b, i, vmask);
1229             }
1230         }
1231 
1232         assertScatterArraysEquals(r, a, b, mask);
1233     }
1234 
1235 
1236 }