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