1 /*
   2  * Copyright (c) 2018, 2021, 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.foreign 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 jdk.incubator.vector.ShortVector;
  35 import jdk.incubator.vector.VectorMask;
  36 import jdk.incubator.vector.VectorShape;
  37 import jdk.incubator.vector.VectorSpecies;
  38 import jdk.incubator.vector.VectorShuffle;
  39 import jdk.internal.vm.annotation.DontInline;
  40 import org.testng.Assert;
  41 import org.testng.annotations.DataProvider;
  42 import org.testng.annotations.Test;
  43 
  44 import java.lang.invoke.MethodHandles;
  45 import java.lang.invoke.VarHandle;
  46 import java.nio.ByteBuffer;
  47 import java.nio.ShortBuffer;
  48 import java.nio.ByteOrder;
  49 import java.nio.ReadOnlyBufferException;
  50 import java.util.List;
  51 import java.util.function.*;
  52 
  53 @Test
  54 public class ShortMaxVectorLoadStoreTests extends AbstractVectorLoadStoreTest {
  55     static final VectorSpecies<Short> SPECIES =
  56                 ShortVector.SPECIES_MAX;
  57 
  58     static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 100);
  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 void assertArraysEquals(byte[] r, byte[] a, boolean[] mask) {
  80         int i = 0;
  81         try {
  82             for (; i < a.length; i++) {
  83                 Assert.assertEquals(r[i], mask[(i*8/SPECIES.elementSize()) % SPECIES.length()] ? a[i] : (byte) 0);
  84             }
  85         } catch (AssertionError e) {
  86             Assert.assertEquals(r[i], mask[(i*8/SPECIES.elementSize()) % SPECIES.length()] ? a[i] : (byte) 0, "at index #" + i);
  87         }
  88     }
  89 
  90     static final List<IntFunction<short[]>> SHORT_GENERATORS = List.of(
  91             withToString("short[i * 5]", (int s) -> {
  92                 return fill(s * BUFFER_REPS,
  93                             i -> (short)(i * 5));
  94             }),
  95             withToString("short[i + 1]", (int s) -> {
  96                 return fill(s * BUFFER_REPS,
  97                             i -> (((short)(i + 1) == 0) ? 1 : (short)(i + 1)));
  98             })
  99     );
 100 
 101     // Relative to array.length
 102     static final List<IntFunction<Integer>> INDEX_GENERATORS = List.of(
 103             withToString("-1", (int l) -> {
 104                 return -1;
 105             }),
 106             withToString("l", (int l) -> {
 107                 return l;
 108             }),
 109             withToString("l - 1", (int l) -> {
 110                 return l - 1;
 111             }),
 112             withToString("l + 1", (int l) -> {
 113                 return l + 1;
 114             }),
 115             withToString("l - speciesl + 1", (int l) -> {
 116                 return l - SPECIES.length() + 1;
 117             }),
 118             withToString("l + speciesl - 1", (int l) -> {
 119                 return l + SPECIES.length() - 1;
 120             }),
 121             withToString("l + speciesl", (int l) -> {
 122                 return l + SPECIES.length();
 123             }),
 124             withToString("l + speciesl + 1", (int l) -> {
 125                 return l + SPECIES.length() + 1;
 126             })
 127     );
 128 
 129     // Relative to byte[] array.length or ByteBuffer.limit()
 130     static final List<IntFunction<Integer>> BYTE_INDEX_GENERATORS = List.of(
 131             withToString("-1", (int l) -> {
 132                 return -1;
 133             }),
 134             withToString("l", (int l) -> {
 135                 return l;
 136             }),
 137             withToString("l - 1", (int l) -> {
 138                 return l - 1;
 139             }),
 140             withToString("l + 1", (int l) -> {
 141                 return l + 1;
 142             }),
 143             withToString("l - speciesl*ebsize + 1", (int l) -> {
 144                 return l - SPECIES.vectorByteSize() + 1;
 145             }),
 146             withToString("l + speciesl*ebsize - 1", (int l) -> {
 147                 return l + SPECIES.vectorByteSize() - 1;
 148             }),
 149             withToString("l + speciesl*ebsize", (int l) -> {
 150                 return l + SPECIES.vectorByteSize();
 151             }),
 152             withToString("l + speciesl*ebsize + 1", (int l) -> {
 153                 return l + SPECIES.vectorByteSize() + 1;
 154             })
 155     );
 156 
 157     @DataProvider
 158     public Object[][] shortProvider() {
 159         return SHORT_GENERATORS.stream().
 160                 map(f -> new Object[]{f}).
 161                 toArray(Object[][]::new);
 162     }
 163 
 164     @DataProvider
 165     public Object[][] maskProvider() {
 166         return BOOLEAN_MASK_GENERATORS.stream().
 167                 map(f -> new Object[]{f}).
 168                 toArray(Object[][]::new);
 169     }
 170 
 171     @DataProvider
 172     public Object[][] shortProviderForIOOBE() {
 173         var f = SHORT_GENERATORS.get(0);
 174         return INDEX_GENERATORS.stream().map(fi -> {
 175                     return new Object[] {f, fi};
 176                 }).
 177                 toArray(Object[][]::new);
 178     }
 179 
 180     @DataProvider
 181     public Object[][] shortMaskProvider() {
 182         return BOOLEAN_MASK_GENERATORS.stream().
 183                 flatMap(fm -> SHORT_GENERATORS.stream().map(fa -> {
 184                     return new Object[] {fa, fm};
 185                 })).
 186                 toArray(Object[][]::new);
 187     }
 188 
 189     @DataProvider
 190     public Object[][] shortMaskProviderForIOOBE() {
 191         var f = SHORT_GENERATORS.get(0);
 192         return BOOLEAN_MASK_GENERATORS.stream().
 193                 flatMap(fm -> INDEX_GENERATORS.stream().map(fi -> {
 194                     return new Object[] {f, fi, fm};
 195                 })).
 196                 toArray(Object[][]::new);
 197     }
 198 
 199     @DataProvider
 200     public Object[][] shortByteBufferProvider() {
 201         return SHORT_GENERATORS.stream().
 202                 flatMap(fa -> BYTE_BUFFER_GENERATORS.stream().
 203                         flatMap(fb -> BYTE_ORDER_VALUES.stream().map(bo -> {
 204                             return new Object[]{fa, fb, bo};
 205                         }))).
 206                 toArray(Object[][]::new);
 207     }
 208 
 209     @DataProvider
 210     public Object[][] shortByteBufferMaskProvider() {
 211         return BOOLEAN_MASK_GENERATORS.stream().
 212                 flatMap(fm -> SHORT_GENERATORS.stream().
 213                         flatMap(fa -> BYTE_BUFFER_GENERATORS.stream().
 214                                 flatMap(fb -> BYTE_ORDER_VALUES.stream().map(bo -> {
 215                             return new Object[]{fa, fb, fm, bo};
 216                         })))).
 217                 toArray(Object[][]::new);
 218     }
 219 
 220     @DataProvider
 221     public Object[][] shortByteArrayProvider() {
 222         return SHORT_GENERATORS.stream().
 223                 flatMap(fa -> BYTE_ORDER_VALUES.stream().map(bo -> {
 224                     return new Object[]{fa, bo};
 225                 })).
 226                 toArray(Object[][]::new);
 227     }
 228 
 229     @DataProvider
 230     public Object[][] shortByteArrayMaskProvider() {
 231         return BOOLEAN_MASK_GENERATORS.stream().
 232                 flatMap(fm -> SHORT_GENERATORS.stream().
 233                     flatMap(fa -> BYTE_ORDER_VALUES.stream().map(bo -> {
 234                         return new Object[]{fa, fm, bo};
 235                     }))).
 236                 toArray(Object[][]::new);
 237     }
 238 
 239     @DataProvider
 240     public Object[][] shortByteProviderForIOOBE() {
 241         var f = SHORT_GENERATORS.get(0);
 242         return BYTE_INDEX_GENERATORS.stream().map(fi -> {
 243                     return new Object[] {f, fi};
 244                 }).
 245                 toArray(Object[][]::new);
 246     }
 247 
 248     @DataProvider
 249     public Object[][] shortByteMaskProviderForIOOBE() {
 250         var f = SHORT_GENERATORS.get(0);
 251         return BOOLEAN_MASK_GENERATORS.stream().
 252                 flatMap(fm -> BYTE_INDEX_GENERATORS.stream().map(fi -> {
 253                     return new Object[] {f, fi, fm};
 254                 })).
 255                 toArray(Object[][]::new);
 256     }
 257 
 258     static ByteBuffer toBuffer(short[] a, IntFunction<ByteBuffer> fb) {
 259         ByteBuffer bb = fb.apply(a.length * SPECIES.elementSize() / 8);
 260         for (short v : a) {
 261             bb.putShort(v);
 262         }
 263         return bb.clear();
 264     }
 265 
 266     static short[] bufferToArray(ByteBuffer bb) {
 267         ShortBuffer db = bb.asShortBuffer();
 268         short[] d = new short[db.capacity()];
 269         db.get(0, d);
 270         return d;
 271     }
 272 
 273     static byte[] toByteArray(short[] a, IntFunction<byte[]> fb, ByteOrder bo) {
 274         byte[] b = fb.apply(a.length * SPECIES.elementSize() / 8);
 275         ShortBuffer bb = ByteBuffer.wrap(b, 0, b.length).order(bo).asShortBuffer();
 276         for (short v : a) {
 277             bb.put(v);
 278         }
 279         return b;
 280     }
 281 
 282 
 283     interface ToShortF {
 284         short apply(int i);
 285     }
 286 
 287     static short[] fill(int s , ToShortF f) {
 288         return fill(new short[s], f);
 289     }
 290 
 291     static short[] fill(short[] a, ToShortF f) {
 292         for (int i = 0; i < a.length; i++) {
 293             a[i] = f.apply(i);
 294         }
 295         return a;
 296     }
 297 
 298     @DontInline
 299     static ShortVector fromArray(short[] a, int i) {
 300         return ShortVector.fromArray(SPECIES, a, i);
 301     }
 302 
 303     @DontInline
 304     static ShortVector fromArray(short[] a, int i, VectorMask<Short> m) {
 305         return ShortVector.fromArray(SPECIES, a, i, m);
 306     }
 307 
 308     @DontInline
 309     static void intoArray(ShortVector v, short[] a, int i) {
 310         v.intoArray(a, i);
 311     }
 312 
 313     @DontInline
 314     static void intoArray(ShortVector v, short[] a, int i, VectorMask<Short> m) {
 315         v.intoArray(a, i, m);
 316     }
 317 
 318     @DontInline
 319     static ShortVector fromByteArray(byte[] a, int i, ByteOrder bo) {
 320         return ShortVector.fromByteArray(SPECIES, a, i, bo);
 321     }
 322 
 323     @DontInline
 324     static ShortVector fromByteArray(byte[] a, int i, ByteOrder bo, VectorMask<Short> m) {
 325         return ShortVector.fromByteArray(SPECIES, a, i, bo, m);
 326     }
 327 
 328     @DontInline
 329     static void intoByteArray(ShortVector v, byte[] a, int i, ByteOrder bo) {
 330         v.intoByteArray(a, i, bo);
 331     }
 332 
 333     @DontInline
 334     static void intoByteArray(ShortVector v, byte[] a, int i, ByteOrder bo, VectorMask<Short> m) {
 335         v.intoByteArray(a, i, bo, m);
 336     }
 337 
 338     @DontInline
 339     static ShortVector fromByteBuffer(ByteBuffer a, int i, ByteOrder bo) {
 340         return ShortVector.fromByteBuffer(SPECIES, a, i, bo);
 341     }
 342 
 343     @DontInline
 344     static ShortVector fromByteBuffer(ByteBuffer a, int i, ByteOrder bo, VectorMask<Short> m) {
 345         return ShortVector.fromByteBuffer(SPECIES, a, i, bo, m);
 346     }
 347 
 348     @DontInline
 349     static void intoByteBuffer(ShortVector v, ByteBuffer a, int i, ByteOrder bo) {
 350         v.intoByteBuffer(a, i, bo);
 351     }
 352 
 353     @DontInline
 354     static void intoByteBuffer(ShortVector v, ByteBuffer a, int i, ByteOrder bo, VectorMask<Short> m) {
 355         v.intoByteBuffer(a, i, bo, m);
 356     }
 357 
 358 
 359     @Test(dataProvider = "shortProvider")
 360     static void loadStoreArray(IntFunction<short[]> fa) {
 361         short[] a = fa.apply(SPECIES.length());
 362         short[] r = new short[a.length];
 363 
 364         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 365             for (int i = 0; i < a.length; i += SPECIES.length()) {
 366                 ShortVector av = ShortVector.fromArray(SPECIES, a, i);
 367                 av.intoArray(r, i);
 368             }
 369         }
 370         Assert.assertEquals(r, a);
 371     }
 372 
 373     @Test(dataProvider = "shortProviderForIOOBE")
 374     static void loadArrayIOOBE(IntFunction<short[]> fa, IntFunction<Integer> fi) {
 375         short[] a = fa.apply(SPECIES.length());
 376         short[] r = new short[a.length];
 377 
 378         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 379             for (int i = 0; i < a.length; i += SPECIES.length()) {
 380                 ShortVector av = fromArray(a, i);
 381                 av.intoArray(r, i);
 382             }
 383         }
 384 
 385         int index = fi.apply(a.length);
 386         boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length);
 387         try {
 388             fromArray(a, index);
 389             if (shouldFail) {
 390                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 391             }
 392         } catch (IndexOutOfBoundsException e) {
 393             if (!shouldFail) {
 394                 Assert.fail("Unexpected IndexOutOfBoundsException");
 395             }
 396         }
 397     }
 398 
 399     @Test(dataProvider = "shortProviderForIOOBE")
 400     static void storeArrayIOOBE(IntFunction<short[]> fa, IntFunction<Integer> fi) {
 401         short[] a = fa.apply(SPECIES.length());
 402         short[] r = new short[a.length];
 403 
 404         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 405             for (int i = 0; i < a.length; i += SPECIES.length()) {
 406                 ShortVector av = ShortVector.fromArray(SPECIES, a, i);
 407                 intoArray(av, r, i);
 408             }
 409         }
 410 
 411         int index = fi.apply(a.length);
 412         boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length);
 413         try {
 414             ShortVector av = ShortVector.fromArray(SPECIES, a, 0);
 415             intoArray(av, r, index);
 416             if (shouldFail) {
 417                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 418             }
 419         } catch (IndexOutOfBoundsException e) {
 420             if (!shouldFail) {
 421                 Assert.fail("Unexpected IndexOutOfBoundsException");
 422             }
 423         }
 424     }
 425 
 426 
 427     @Test(dataProvider = "shortMaskProvider")
 428     static void loadStoreMaskArray(IntFunction<short[]> fa,
 429                                    IntFunction<boolean[]> fm) {
 430         short[] a = fa.apply(SPECIES.length());
 431         short[] r = new short[a.length];
 432         boolean[] mask = fm.apply(SPECIES.length());
 433         VectorMask<Short> vmask = VectorMask.fromValues(SPECIES, mask);
 434 
 435         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 436             for (int i = 0; i < a.length; i += SPECIES.length()) {
 437                 ShortVector av = ShortVector.fromArray(SPECIES, a, i, vmask);
 438                 av.intoArray(r, i);
 439             }
 440         }
 441         assertArraysEquals(r, a, mask);
 442 
 443 
 444         r = new short[a.length];
 445 
 446         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 447             for (int i = 0; i < a.length; i += SPECIES.length()) {
 448                 ShortVector av = ShortVector.fromArray(SPECIES, a, i);
 449                 av.intoArray(r, i, vmask);
 450             }
 451         }
 452         assertArraysEquals(r, a, mask);
 453     }
 454 
 455     @Test(dataProvider = "shortMaskProviderForIOOBE")
 456     static void loadArrayMaskIOOBE(IntFunction<short[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
 457         short[] a = fa.apply(SPECIES.length());
 458         short[] r = new short[a.length];
 459         boolean[] mask = fm.apply(SPECIES.length());
 460         VectorMask<Short> vmask = VectorMask.fromValues(SPECIES, mask);
 461 
 462         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 463             for (int i = 0; i < a.length; i += SPECIES.length()) {
 464                 ShortVector av = fromArray(a, i, vmask);
 465                 av.intoArray(r, i);
 466             }
 467         }
 468 
 469         int index = fi.apply(a.length);
 470         boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length);
 471         try {
 472             fromArray(a, index, vmask);
 473             if (shouldFail) {
 474                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 475             }
 476         } catch (IndexOutOfBoundsException e) {
 477             if (!shouldFail) {
 478                 Assert.fail("Unexpected IndexOutOfBoundsException");
 479             }
 480         }
 481     }
 482 
 483     @Test(dataProvider = "shortMaskProviderForIOOBE")
 484     static void storeArrayMaskIOOBE(IntFunction<short[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
 485         short[] a = fa.apply(SPECIES.length());
 486         short[] r = new short[a.length];
 487         boolean[] mask = fm.apply(SPECIES.length());
 488         VectorMask<Short> vmask = VectorMask.fromValues(SPECIES, mask);
 489 
 490         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 491             for (int i = 0; i < a.length; i += SPECIES.length()) {
 492                 ShortVector av = ShortVector.fromArray(SPECIES, a, i);
 493                 intoArray(av, r, i, vmask);
 494             }
 495         }
 496 
 497         int index = fi.apply(a.length);
 498         boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length);
 499         try {
 500             ShortVector av = ShortVector.fromArray(SPECIES, a, 0);
 501             intoArray(av, a, index, vmask);
 502             if (shouldFail) {
 503                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 504             }
 505         } catch (IndexOutOfBoundsException e) {
 506             if (!shouldFail) {
 507                 Assert.fail("Unexpected IndexOutOfBoundsException");
 508             }
 509         }
 510     }
 511 
 512 
 513     @Test(dataProvider = "shortMaskProvider")
 514     static void loadStoreMask(IntFunction<short[]> fa,
 515                               IntFunction<boolean[]> fm) {
 516         boolean[] mask = fm.apply(SPECIES.length());
 517         boolean[] r = new boolean[mask.length];
 518 
 519         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 520             for (int i = 0; i < mask.length; i += SPECIES.length()) {
 521                 VectorMask<Short> vmask = VectorMask.fromArray(SPECIES, mask, i);
 522                 vmask.intoArray(r, i);
 523             }
 524         }
 525         Assert.assertEquals(r, mask);
 526     }
 527 
 528 
 529     @Test(dataProvider = "shortByteBufferProvider")
 530     static void loadStoreByteBuffer(IntFunction<short[]> fa,
 531                                     IntFunction<ByteBuffer> fb,
 532                                     ByteOrder bo) {
 533         ByteBuffer a = toBuffer(fa.apply(SPECIES.length()), fb);
 534         ByteBuffer r = fb.apply(a.limit());
 535 
 536         int l = a.limit();
 537         int s = SPECIES.vectorByteSize();
 538 
 539         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 540             for (int i = 0; i < l; i += s) {
 541                 ShortVector av = ShortVector.fromByteBuffer(SPECIES, a, i, bo);
 542                 av.intoByteBuffer(r, i, bo);
 543             }
 544         }
 545         Assert.assertEquals(a.position(), 0, "Input buffer position changed");
 546         Assert.assertEquals(a.limit(), l, "Input buffer limit changed");
 547         Assert.assertEquals(r.position(), 0, "Result buffer position changed");
 548         Assert.assertEquals(r.limit(), l, "Result buffer limit changed");
 549         Assert.assertEquals(r, a, "Buffers not equal");
 550     }
 551 
 552     @Test(dataProvider = "shortByteProviderForIOOBE")
 553     static void loadByteBufferIOOBE(IntFunction<short[]> fa, IntFunction<Integer> fi) {
 554         ByteBuffer a = toBuffer(fa.apply(SPECIES.length()), ByteBuffer::allocateDirect);
 555         ByteBuffer r = ByteBuffer.allocateDirect(a.limit());
 556 
 557         int l = a.limit();
 558         int s = SPECIES.vectorByteSize();
 559 
 560         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 561             for (int i = 0; i < l; i += s) {
 562                 ShortVector av = fromByteBuffer(a, i, ByteOrder.nativeOrder());
 563                 av.intoByteBuffer(r, i, ByteOrder.nativeOrder());
 564             }
 565         }
 566 
 567         int index = fi.apply(a.limit());
 568         boolean shouldFail = isIndexOutOfBounds(SPECIES.vectorByteSize(), index, a.limit());
 569         try {
 570             fromByteBuffer(a, index, ByteOrder.nativeOrder());
 571             if (shouldFail) {
 572                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 573             }
 574         } catch (IndexOutOfBoundsException e) {
 575             if (!shouldFail) {
 576                 Assert.fail("Unexpected IndexOutOfBoundsException");
 577             }
 578         }
 579     }
 580 
 581     @Test(dataProvider = "shortByteProviderForIOOBE")
 582     static void storeByteBufferIOOBE(IntFunction<short[]> fa, IntFunction<Integer> fi) {
 583         ByteBuffer a = toBuffer(fa.apply(SPECIES.length()), ByteBuffer::allocateDirect);
 584         ByteBuffer r = ByteBuffer.allocateDirect(a.limit());
 585 
 586         int l = a.limit();
 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 = ShortVector.fromByteBuffer(SPECIES, a, i, ByteOrder.nativeOrder());
 592                 intoByteBuffer(av, r, i, ByteOrder.nativeOrder());
 593             }
 594         }
 595 
 596         int index = fi.apply(a.limit());
 597         boolean shouldFail = isIndexOutOfBounds(SPECIES.vectorByteSize(), index, a.limit());
 598         try {
 599             ShortVector av = ShortVector.fromByteBuffer(SPECIES, a, 0, ByteOrder.nativeOrder());
 600             intoByteBuffer(av, r, index, ByteOrder.nativeOrder());
 601             if (shouldFail) {
 602                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 603             }
 604         } catch (IndexOutOfBoundsException e) {
 605             if (!shouldFail) {
 606                 Assert.fail("Unexpected IndexOutOfBoundsException");
 607             }
 608         }
 609     }
 610 
 611 
 612     @Test(dataProvider = "shortByteBufferMaskProvider")
 613     static void loadStoreByteBufferMask(IntFunction<short[]> fa,
 614                                         IntFunction<ByteBuffer> fb,
 615                                         IntFunction<boolean[]> fm,
 616                                         ByteOrder bo) {
 617         short[] _a = fa.apply(SPECIES.length());
 618         ByteBuffer a = toBuffer(_a, fb);
 619         ByteBuffer r = fb.apply(a.limit());
 620         boolean[] mask = fm.apply(SPECIES.length());
 621         VectorMask<Short> vmask = VectorMask.fromValues(SPECIES, mask);
 622 
 623         int l = a.limit();
 624         int s = SPECIES.vectorByteSize();
 625 
 626         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 627             for (int i = 0; i < l; i += s) {
 628                 ShortVector av = ShortVector.fromByteBuffer(SPECIES, a, i, bo, vmask);
 629                 av.intoByteBuffer(r, i, bo);
 630             }
 631         }
 632         Assert.assertEquals(a.position(), 0, "Input buffer position changed");
 633         Assert.assertEquals(a.limit(), l, "Input buffer limit changed");
 634         Assert.assertEquals(r.position(), 0, "Result buffer position changed");
 635         Assert.assertEquals(r.limit(), l, "Result buffer limit changed");
 636         assertArraysEquals(bufferToArray(r), _a, mask);
 637 
 638 
 639         r = fb.apply(a.limit());
 640 
 641         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 642             for (int i = 0; i < l; i += s) {
 643                 ShortVector av = ShortVector.fromByteBuffer(SPECIES, a, i, bo);
 644                 av.intoByteBuffer(r, i, bo, vmask);
 645             }
 646         }
 647         Assert.assertEquals(a.position(), 0, "Input buffer position changed");
 648         Assert.assertEquals(a.limit(), l, "Input buffer limit changed");
 649         Assert.assertEquals(r.position(), 0, "Result buffer position changed");
 650         Assert.assertEquals(r.limit(), l, "Result buffer limit changed");
 651         assertArraysEquals(bufferToArray(r), _a, mask);
 652     }
 653 
 654     @Test(dataProvider = "shortByteMaskProviderForIOOBE")
 655     static void loadByteBufferMaskIOOBE(IntFunction<short[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
 656         ByteBuffer a = toBuffer(fa.apply(SPECIES.length()), ByteBuffer::allocateDirect);
 657         ByteBuffer r = ByteBuffer.allocateDirect(a.limit());
 658         boolean[] mask = fm.apply(SPECIES.length());
 659         VectorMask<Short> vmask = VectorMask.fromValues(SPECIES, mask);
 660 
 661         int l = a.limit();
 662         int s = SPECIES.vectorByteSize();
 663 
 664         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 665             for (int i = 0; i < l; i += s) {
 666                 ShortVector av = fromByteBuffer(a, i, ByteOrder.nativeOrder(), vmask);
 667                 av.intoByteBuffer(r, i, ByteOrder.nativeOrder());
 668             }
 669         }
 670 
 671         int index = fi.apply(a.limit());
 672         boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.limit(), SPECIES.elementSize() / 8);
 673         try {
 674             fromByteBuffer(a, index, ByteOrder.nativeOrder(), vmask);
 675             if (shouldFail) {
 676                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 677             }
 678         } catch (IndexOutOfBoundsException e) {
 679             if (!shouldFail) {
 680                 Assert.fail("Unexpected IndexOutOfBoundsException");
 681             }
 682         }
 683     }
 684 
 685     @Test(dataProvider = "shortByteMaskProviderForIOOBE")
 686     static void storeByteBufferMaskIOOBE(IntFunction<short[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
 687         ByteBuffer a = toBuffer(fa.apply(SPECIES.length()), ByteBuffer::allocateDirect);
 688         ByteBuffer r = ByteBuffer.allocateDirect(a.limit());
 689         boolean[] mask = fm.apply(SPECIES.length());
 690         VectorMask<Short> vmask = VectorMask.fromValues(SPECIES, mask);
 691 
 692         int l = a.limit();
 693         int s = SPECIES.vectorByteSize();
 694 
 695         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 696             for (int i = 0; i < l; i += s) {
 697                 ShortVector av = ShortVector.fromByteBuffer(SPECIES, a, i, ByteOrder.nativeOrder());
 698                 intoByteBuffer(av, r, i, ByteOrder.nativeOrder(), vmask);
 699             }
 700         }
 701 
 702         int index = fi.apply(a.limit());
 703         boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.limit(), SPECIES.elementSize() / 8);
 704         try {
 705             ShortVector av = ShortVector.fromByteBuffer(SPECIES, a, 0, ByteOrder.nativeOrder());
 706             intoByteBuffer(av, a, index, ByteOrder.nativeOrder(), vmask);
 707             if (shouldFail) {
 708                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 709             }
 710         } catch (IndexOutOfBoundsException e) {
 711             if (!shouldFail) {
 712                 Assert.fail("Unexpected IndexOutOfBoundsException");
 713             }
 714         }
 715     }
 716 
 717 
 718     @Test(dataProvider = "shortByteBufferProvider")
 719     static void loadStoreReadonlyByteBuffer(IntFunction<short[]> fa,
 720                                     IntFunction<ByteBuffer> fb,
 721                                     ByteOrder bo) {
 722         ByteBuffer a = toBuffer(fa.apply(SPECIES.length()), fb).asReadOnlyBuffer();
 723 
 724         try {
 725             SPECIES.zero().intoByteBuffer(a, 0, bo);
 726             Assert.fail("ReadOnlyBufferException expected");
 727         } catch (ReadOnlyBufferException e) {
 728         }
 729 
 730         try {
 731             SPECIES.zero().intoByteBuffer(a, 0, bo, SPECIES.maskAll(true));
 732             Assert.fail("ReadOnlyBufferException expected");
 733         } catch (ReadOnlyBufferException e) {
 734         }
 735 
 736         try {
 737             SPECIES.zero().intoByteBuffer(a, 0, bo, SPECIES.maskAll(false));
 738             Assert.fail("ReadOnlyBufferException expected");
 739         } catch (ReadOnlyBufferException e) {
 740         }
 741 
 742         try {
 743             VectorMask<Short> m = SPECIES.shuffleFromOp(i -> i % 2 == 0 ? 1 : -1)
 744                     .laneIsValid();
 745             SPECIES.zero().intoByteBuffer(a, 0, bo, m);
 746             Assert.fail("ReadOnlyBufferException expected");
 747         } catch (ReadOnlyBufferException e) {
 748         }
 749     }
 750 
 751 
 752     @Test(dataProvider = "shortByteArrayProvider")
 753     static void loadStoreByteArray(IntFunction<short[]> fa,
 754                                     ByteOrder bo) {
 755         byte[] a = toByteArray(fa.apply(SPECIES.length()), byte[]::new, bo);
 756         byte[] r = new byte[a.length];
 757 
 758         int s = SPECIES.vectorByteSize();
 759         int l = a.length;
 760 
 761         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 762             for (int i = 0; i < l; i += s) {
 763                 ShortVector av = ShortVector.fromByteArray(SPECIES, a, i, bo);
 764                 av.intoByteArray(r, i, bo);
 765             }
 766         }
 767         Assert.assertEquals(r, a, "Byte arrays not equal");
 768     }
 769 
 770     @Test(dataProvider = "shortByteProviderForIOOBE")
 771     static void loadByteArrayIOOBE(IntFunction<short[]> fa, IntFunction<Integer> fi) {
 772         byte[] a = toByteArray(fa.apply(SPECIES.length()), byte[]::new, ByteOrder.nativeOrder());
 773         byte[] r = new byte[a.length];
 774 
 775         int s = SPECIES.vectorByteSize();
 776         int l = a.length;
 777 
 778         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 779             for (int i = 0; i < l; i += s) {
 780                 ShortVector av = fromByteArray(a, i, ByteOrder.nativeOrder());
 781                 av.intoByteArray(r, i, ByteOrder.nativeOrder());
 782             }
 783         }
 784 
 785         int index = fi.apply(a.length);
 786         boolean shouldFail = isIndexOutOfBounds(SPECIES.vectorByteSize(), index, a.length);
 787         try {
 788             fromByteArray(a, index, ByteOrder.nativeOrder());

 789             if (shouldFail) {
 790                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 791             }
 792         } catch (IndexOutOfBoundsException e) {
 793             if (!shouldFail) {
 794                 Assert.fail("Unexpected IndexOutOfBoundsException");
 795             }
 796         }
 797     }
 798 
 799     @Test(dataProvider = "shortByteProviderForIOOBE")
 800     static void storeByteArrayIOOBE(IntFunction<short[]> fa, IntFunction<Integer> fi) {
 801         byte[] a = toByteArray(fa.apply(SPECIES.length()), byte[]::new, ByteOrder.nativeOrder());
 802         byte[] r = new byte[a.length];
 803 
 804         int s = SPECIES.vectorByteSize();
 805         int l = a.length;
 806 
 807         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 808             for (int i = 0; i < l; i += s) {
 809                 ShortVector av = ShortVector.fromByteArray(SPECIES, a, i, ByteOrder.nativeOrder());
 810                 intoByteArray(av, r, i, ByteOrder.nativeOrder());
 811             }
 812         }
 813 
 814         int index = fi.apply(a.length);
 815         boolean shouldFail = isIndexOutOfBounds(SPECIES.vectorByteSize(), index, a.length);
 816         try {
 817             ShortVector av = ShortVector.fromByteArray(SPECIES, a, 0, ByteOrder.nativeOrder());
 818             intoByteArray(av, r, index, ByteOrder.nativeOrder());
 819             if (shouldFail) {
 820                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 821             }
 822         } catch (IndexOutOfBoundsException e) {
 823             if (!shouldFail) {
 824                 Assert.fail("Unexpected IndexOutOfBoundsException");
 825             }
 826         }
 827     }
 828 
 829 
 830     @Test(dataProvider = "shortByteArrayMaskProvider")
 831     static void loadStoreByteArrayMask(IntFunction<short[]> fa,
 832                                   IntFunction<boolean[]> fm,
 833                                   ByteOrder bo) {
 834         byte[] a = toByteArray(fa.apply(SPECIES.length()), byte[]::new, bo);
 835         byte[] r = new byte[a.length];
 836         boolean[] mask = fm.apply(SPECIES.length());
 837         VectorMask<Short> vmask = VectorMask.fromValues(SPECIES, mask);
 838 
 839         int s = SPECIES.vectorByteSize();
 840         int l = a.length;
 841 
 842         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 843           for (int i = 0; i < l; i += s) {
 844               ShortVector av = ShortVector.fromByteArray(SPECIES, a, i, bo, vmask);
 845               av.intoByteArray(r, i, bo);
 846           }
 847         }
 848         assertArraysEquals(r, a, mask);
 849 
 850 
 851         r = new byte[a.length];
 852 
 853         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 854             for (int i = 0; i < l; i += s) {
 855                 ShortVector av = ShortVector.fromByteArray(SPECIES, a, i, bo);
 856                 av.intoByteArray(r, i, bo, vmask);
 857             }
 858         }
 859         assertArraysEquals(r, a, mask);
 860     }
 861 
 862     @Test(dataProvider = "shortByteMaskProviderForIOOBE")
 863     static void loadByteArrayMaskIOOBE(IntFunction<short[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
 864         byte[] a = toByteArray(fa.apply(SPECIES.length()), byte[]::new, ByteOrder.nativeOrder());
 865         byte[] r = new byte[a.length];
 866         boolean[] mask = fm.apply(SPECIES.length());
 867         VectorMask<Short> vmask = VectorMask.fromValues(SPECIES, mask);
 868 
 869         int s = SPECIES.vectorByteSize();
 870         int l = a.length;


 871 
 872         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 873             for (int i = 0; i < l; i += s) {
 874                 ShortVector av = fromByteArray(a, i, ByteOrder.nativeOrder(), vmask);
 875                 av.intoByteArray(r, i, ByteOrder.nativeOrder());
 876             }
 877         }
 878 
 879         int index = fi.apply(a.length);
 880         boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length, SPECIES.elementSize() / 8);
 881         try {
 882             fromByteArray(a, index, ByteOrder.nativeOrder(), vmask);
 883             if (shouldFail) {
 884                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 885             }
 886         } catch (IndexOutOfBoundsException e) {
 887             if (!shouldFail) {
 888                 Assert.fail("Unexpected IndexOutOfBoundsException");
 889             }
 890         }
 891     }
 892 
 893     @Test(dataProvider = "shortByteMaskProviderForIOOBE")
 894     static void storeByteArrayMaskIOOBE(IntFunction<short[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
 895         byte[] a = toByteArray(fa.apply(SPECIES.length()), byte[]::new, ByteOrder.nativeOrder());
 896         byte[] r = new byte[a.length];
 897         boolean[] mask = fm.apply(SPECIES.length());
 898         VectorMask<Short> vmask = VectorMask.fromValues(SPECIES, mask);
 899 
 900         int s = SPECIES.vectorByteSize();
 901         int l = a.length;
 902 
 903         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 904             for (int i = 0; i < l; i += s) {
 905                 ShortVector av = ShortVector.fromByteArray(SPECIES, a, i, ByteOrder.nativeOrder());
 906                 intoByteArray(av, r, i, ByteOrder.nativeOrder(), vmask);
 907             }
 908         }
 909 
 910         int index = fi.apply(a.length);
 911         boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length, SPECIES.elementSize() / 8);
 912         try {
 913             ShortVector av = ShortVector.fromByteArray(SPECIES, a, 0, ByteOrder.nativeOrder());
 914             intoByteArray(av, a, index, ByteOrder.nativeOrder(), vmask);
 915             if (shouldFail) {
 916                 Assert.fail("Failed to throw IndexOutOfBoundsException");
 917             }
 918         } catch (IndexOutOfBoundsException e) {
 919             if (!shouldFail) {
 920                 Assert.fail("Unexpected IndexOutOfBoundsException");
 921             }
 922         }
 923     }
 924 
 925     @Test(dataProvider = "maskProvider")
 926     static void loadStoreMask(IntFunction<boolean[]> fm) {
 927         boolean[] a = fm.apply(SPECIES.length());
 928         boolean[] r = new boolean[a.length];
 929 
 930         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 931             for (int i = 0; i < a.length; i += SPECIES.length()) {
 932                 VectorMask<Short> vmask = SPECIES.loadMask(a, i);
 933                 vmask.intoArray(r, i);
 934             }
 935         }
 936         Assert.assertEquals(r, a);
 937     }
 938 

 939     @Test
 940     static void loadStoreShuffle() {
 941         IntUnaryOperator fn = a -> a + 5;
 942         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 943             var shuffle = VectorShuffle.fromOp(SPECIES, fn);
 944             int [] r = shuffle.toArray();
 945 
 946             int [] a = expectedShuffle(SPECIES.length(), fn);
 947             Assert.assertEquals(r, a);
 948        }
 949     }
 950 
 951 
 952     static void assertArraysEquals(char[] a, char[] r, boolean[] mask) {
 953         int i = 0;
 954         try {
 955             for (; i < a.length; i++) {
 956                 Assert.assertEquals(mask[i % SPECIES.length()] ? a[i] : (char) 0, r[i]);
 957             }
 958         } catch (AssertionError e) {
 959             Assert.assertEquals(mask[i % SPECIES.length()] ? a[i] : (char) 0, r[i], "at index #" + i);
 960         }
 961     }
 962 
 963     static final List<IntFunction<char[]>> CHAR_GENERATORS = List.of(
 964             withToString("char[i * 5]", (int s) -> {
 965                 return fillChar(s * BUFFER_REPS,
 966                             i -> (char)(i * 5));
 967             }),
 968             withToString("char[i + 1]", (int s) -> {
 969                 return fillChar(s * BUFFER_REPS,
 970                             i -> (((char)(i + 1) == 0) ? 1 : (char)(i + 1)));
 971             })
 972     );
 973 
 974     @DataProvider
 975     public Object[][] charProvider() {
 976         return CHAR_GENERATORS.stream().
 977                 map(f -> new Object[]{f}).
 978                 toArray(Object[][]::new);
 979     }
 980 
 981     @DataProvider
 982     public Object[][] charProviderForIOOBE() {
 983         var f = CHAR_GENERATORS.get(0);
 984         return INDEX_GENERATORS.stream().map(fi -> {
 985                     return new Object[] {f, fi};
 986                 }).
 987                 toArray(Object[][]::new);
 988     }
 989 
 990     @DataProvider
 991     public Object[][] charMaskProvider() {
 992         return BOOLEAN_MASK_GENERATORS.stream().
 993                 flatMap(fm -> CHAR_GENERATORS.stream().map(fa -> {
 994                     return new Object[] {fa, fm};
 995                 })).
 996                 toArray(Object[][]::new);
 997     }
 998 
 999     @DataProvider
1000     public Object[][] charMaskProviderForIOOBE() {
1001         var f = CHAR_GENERATORS.get(0);
1002         return BOOLEAN_MASK_GENERATORS.stream().
1003                 flatMap(fm -> INDEX_GENERATORS.stream().map(fi -> {
1004                     return new Object[] {f, fi, fm};
1005                 })).
1006                 toArray(Object[][]::new);
1007     }
1008 
1009     interface ToCharF {
1010         char apply(int i);
1011     }
1012 
1013     static char[] fillChar(int s , ToCharF f) {
1014         return fillChar(new char[s], f);
1015     }
1016 
1017     static char[] fillChar(char[] a, ToCharF f) {
1018         for (int i = 0; i < a.length; i++) {
1019             a[i] = f.apply(i);
1020         }
1021         return a;
1022     }
1023 
1024     @DontInline
1025     static ShortVector fromCharArray(char[] a, int i) {
1026         return ShortVector.fromCharArray(SPECIES, a, i);
1027     }
1028 
1029     @DontInline
1030     static ShortVector fromCharArray(char[] a, int i, VectorMask<Short> m) {
1031         return ShortVector.fromCharArray(SPECIES, a, i, m);
1032     }
1033 
1034     @DontInline
1035     static void intoCharArray(ShortVector v, char[] a, int i) {
1036         v.intoCharArray(a, i);
1037     }
1038 
1039     @DontInline
1040     static void intoCharArray(ShortVector v, char[] a, int i, VectorMask<Short> m) {
1041         v.intoCharArray(a, i, m);
1042     }
1043 
1044     @Test(dataProvider = "charProvider")
1045     static void loadStoreCharArray(IntFunction<char[]> fa) {
1046         char[] a = fa.apply(SPECIES.length());
1047         char[] r = new char[a.length];
1048 
1049         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1050             for (int i = 0; i < a.length; i += SPECIES.length()) {
1051                 ShortVector av = ShortVector.fromCharArray(SPECIES, a, i);
1052                 av.intoCharArray(r, i);
1053             }
1054         }
1055         Assert.assertEquals(a, r);
1056     }
1057 
1058     @Test(dataProvider = "charProviderForIOOBE")
1059     static void loadCharArrayIOOBE(IntFunction<char[]> fa, IntFunction<Integer> fi) {
1060         char[] a = fa.apply(SPECIES.length());
1061         char[] r = new char[a.length];
1062 
1063         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1064             for (int i = 0; i < a.length; i += SPECIES.length()) {
1065                 ShortVector av = fromCharArray(a, i);
1066                 av.intoCharArray(r, i);
1067             }
1068         }
1069 
1070         int index = fi.apply(a.length);
1071         boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length);
1072         try {
1073             fromCharArray(a, index);
1074             if (shouldFail) {
1075                 Assert.fail("Failed to throw IndexOutOfBoundsException");
1076             }
1077         } catch (IndexOutOfBoundsException e) {
1078             if (!shouldFail) {
1079                 Assert.fail("Unexpected IndexOutOfBoundsException");
1080             }
1081         }
1082     }
1083 
1084     @Test(dataProvider = "charProviderForIOOBE")
1085     static void storeCharArrayIOOBE(IntFunction<char[]> fa, IntFunction<Integer> fi) {
1086         char[] a = fa.apply(SPECIES.length());
1087         char[] r = new char[a.length];
1088 
1089         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1090             for (int i = 0; i < a.length; i += SPECIES.length()) {
1091                 ShortVector av = ShortVector.fromCharArray(SPECIES, a, i);
1092                 intoCharArray(av, r, i);
1093             }
1094         }
1095 
1096         int index = fi.apply(a.length);
1097         boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length);
1098         try {
1099             ShortVector av = ShortVector.fromCharArray(SPECIES, a, 0);
1100             intoCharArray(av, r, index);
1101             if (shouldFail) {
1102                 Assert.fail("Failed to throw IndexOutOfBoundsException");
1103             }
1104         } catch (IndexOutOfBoundsException e) {
1105             if (!shouldFail) {
1106                 Assert.fail("Unexpected IndexOutOfBoundsException");
1107             }
1108         }
1109     }
1110 
1111     @Test(dataProvider = "charMaskProvider")
1112     static void loadStoreMaskCharArray(IntFunction<char[]> fa,
1113                                        IntFunction<boolean[]> fm) {
1114         char[] a = fa.apply(SPECIES.length());
1115         char[] r = new char[a.length];
1116         boolean[] mask = fm.apply(SPECIES.length());
1117         VectorMask<Short> vmask = VectorMask.fromValues(SPECIES, mask);
1118 
1119         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1120             for (int i = 0; i < a.length; i += SPECIES.length()) {
1121                 ShortVector av = ShortVector.fromCharArray(SPECIES, a, i, vmask);
1122                 av.intoCharArray(r, i);
1123             }
1124         }
1125         assertArraysEquals(a, r, mask);
1126 
1127 
1128         r = new char[a.length];
1129 
1130         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1131             for (int i = 0; i < a.length; i += SPECIES.length()) {
1132                 ShortVector av = ShortVector.fromCharArray(SPECIES, a, i);
1133                 av.intoCharArray(r, i, vmask);
1134             }
1135         }
1136         assertArraysEquals(a, r, mask);
1137     }
1138 
1139     @Test(dataProvider = "charMaskProviderForIOOBE")
1140     static void loadCharArrayMaskIOOBE(IntFunction<char[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
1141         char[] a = fa.apply(SPECIES.length());
1142         char[] r = new char[a.length];
1143         boolean[] mask = fm.apply(SPECIES.length());
1144         VectorMask<Short> vmask = VectorMask.fromValues(SPECIES, mask);
1145 
1146         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1147             for (int i = 0; i < a.length; i += SPECIES.length()) {
1148                 ShortVector av = fromCharArray(a, i, vmask);
1149                 av.intoCharArray(r, i);
1150             }
1151         }
1152 
1153         int index = fi.apply(a.length);
1154         boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length);
1155         try {
1156             fromCharArray(a, index, vmask);
1157             if (shouldFail) {
1158                 Assert.fail("Failed to throw IndexOutOfBoundsException");
1159             }
1160         } catch (IndexOutOfBoundsException e) {
1161             if (!shouldFail) {
1162                 Assert.fail("Unexpected IndexOutOfBoundsException");
1163             }
1164         }
1165     }
1166 
1167     @Test(dataProvider = "charMaskProviderForIOOBE")
1168     static void storeCharArrayMaskIOOBE(IntFunction<char[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
1169         char[] a = fa.apply(SPECIES.length());
1170         char[] r = new char[a.length];
1171         boolean[] mask = fm.apply(SPECIES.length());
1172         VectorMask<Short> vmask = VectorMask.fromValues(SPECIES, mask);
1173 
1174         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1175             for (int i = 0; i < a.length; i += SPECIES.length()) {
1176                 ShortVector av = ShortVector.fromCharArray(SPECIES, a, i);
1177                 intoCharArray(av, r, i, vmask);
1178             }
1179         }
1180 
1181         int index = fi.apply(a.length);
1182         boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length);
1183         try {
1184             ShortVector av = ShortVector.fromCharArray(SPECIES, a, 0);
1185             intoCharArray(av, a, index, vmask);
1186             if (shouldFail) {
1187                 Assert.fail("Failed to throw IndexOutOfBoundsException");
1188             }
1189         } catch (IndexOutOfBoundsException e) {
1190             if (!shouldFail) {
1191                 Assert.fail("Unexpected IndexOutOfBoundsException");
1192             }
1193         }
1194     }
1195 
1196 
1197 
1198 
1199     // Gather/Scatter load/store tests
1200 
1201     static void assertGatherArraysEquals(short[] r, short[] a, int[] indexMap) {
1202         int i = 0;
1203         int j = 0;
1204         try {
1205             for (; i < a.length; i += SPECIES.length()) {
1206                 j = i;
1207                 for (; j < i + SPECIES.length(); j++) {
1208                     Assert.assertEquals(r[j], a[i + indexMap[j]]);
1209                 }
1210             }
1211         } catch (AssertionError e) {
1212             Assert.assertEquals(r[j], a[i + indexMap[j]], "at index #" + j);
1213         }
1214     }
1215 
1216     static void assertGatherArraysEquals(short[] r, short[] a, int[] indexMap, boolean[] mask) {
1217         int i = 0;
1218         int j = 0;
1219         try {
1220             for (; i < a.length; i += SPECIES.length()) {
1221                 j = i;
1222                 for (; j < i + SPECIES.length(); j++) {
1223                     Assert.assertEquals(r[j], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (short) 0);
1224                 }
1225             }
1226         } catch (AssertionError e) {
1227             Assert.assertEquals(r[i], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (short) 0, "at index #" + j);
1228         }
1229     }
1230 
1231     static void assertScatterArraysEquals(short[] r, short[] a, int[] indexMap, boolean[] mask) {
1232         short[] expected = new short[r.length];
1233 
1234         // Store before checking, since the same location may be stored to more than once
1235         for (int i = 0; i < a.length; i += SPECIES.length()) {
1236             for (int j = i; j < i + SPECIES.length(); j++) {
1237                 if (mask[j % SPECIES.length()]) {
1238                     expected[i + indexMap[j]] = a[j];
1239                 }
1240             }
1241         }
1242 
1243         Assert.assertEquals(r, expected);
1244     }
1245 
1246     static void assertScatterArraysEquals(short[] r, short[] a, int[] indexMap) {
1247         short[] expected = new short[r.length];
1248 
1249         // Store before checking, since the same location may be stored to more than once
1250         for (int i = 0; i < a.length; i += SPECIES.length()) {
1251             for (int j = i; j < i + SPECIES.length(); j++) {
1252                 expected[i + indexMap[j]] = a[j];
1253             }
1254         }
1255 
1256         Assert.assertEquals(r, expected);
1257     }
1258 
1259     @DataProvider
1260     public Object[][] gatherScatterProvider() {
1261         return INT_INDEX_GENERATORS.stream().
1262                 flatMap(fs -> SHORT_GENERATORS.stream().map(fa -> {
1263                     return new Object[] {fa, fs};
1264                 })).
1265                 toArray(Object[][]::new);
1266     }
1267 
1268     @DataProvider
1269     public Object[][] gatherScatterMaskProvider() {
1270         return BOOLEAN_MASK_GENERATORS.stream().
1271           flatMap(fs -> INT_INDEX_GENERATORS.stream().flatMap(fm ->
1272             SHORT_GENERATORS.stream().map(fa -> {
1273                     return new Object[] {fa, fm, fs};
1274             }))).
1275             toArray(Object[][]::new);
1276     }
1277 
1278 
1279     @Test(dataProvider = "gatherScatterProvider")
1280     static void gather(IntFunction<short[]> fa, BiFunction<Integer,Integer,int[]> fs) {
1281         short[] a = fa.apply(SPECIES.length());
1282         int[] b = fs.apply(a.length, SPECIES.length());
1283         short[] r = new short[a.length];
1284 
1285         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1286             for (int i = 0; i < a.length; i += SPECIES.length()) {
1287                 ShortVector av = ShortVector.fromArray(SPECIES, a, i, b, i);
1288                 av.intoArray(r, i);
1289             }
1290         }
1291 
1292         assertGatherArraysEquals(r, a, b);
1293     }
1294 
1295     @Test(dataProvider = "gatherScatterMaskProvider")
1296     static void gatherMask(IntFunction<short[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
1297         short[] a = fa.apply(SPECIES.length());
1298         int[] b = fs.apply(a.length, SPECIES.length());
1299         short[] r = new short[a.length];
1300         boolean[] mask = fm.apply(SPECIES.length());
1301         VectorMask<Short> vmask = VectorMask.fromArray(SPECIES, mask, 0);
1302 
1303         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1304             for (int i = 0; i < a.length; i += SPECIES.length()) {
1305                 ShortVector av = ShortVector.fromArray(SPECIES, a, i, b, i, vmask);
1306                 av.intoArray(r, i);
1307             }
1308         }
1309 
1310         assertGatherArraysEquals(r, a, b, mask);
1311     }
1312 
1313     @Test(dataProvider = "gatherScatterProvider")
1314     static void scatter(IntFunction<short[]> fa, BiFunction<Integer,Integer,int[]> fs) {
1315         short[] a = fa.apply(SPECIES.length());
1316         int[] b = fs.apply(a.length, SPECIES.length());
1317         short[] r = new short[a.length];
1318 
1319         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1320             for (int i = 0; i < a.length; i += SPECIES.length()) {
1321                 ShortVector av = ShortVector.fromArray(SPECIES, a, i);
1322                 av.intoArray(r, i, b, i);
1323             }
1324         }
1325 
1326         assertScatterArraysEquals(r, a, b);
1327     }
1328 
1329     @Test(dataProvider = "gatherScatterMaskProvider")
1330     static void scatterMask(IntFunction<short[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
1331         short[] a = fa.apply(SPECIES.length());
1332         int[] b = fs.apply(a.length, SPECIES.length());
1333         short[] r = new short[a.length];
1334         boolean[] mask = fm.apply(SPECIES.length());
1335         VectorMask<Short> vmask = VectorMask.fromArray(SPECIES, mask, 0);
1336 
1337         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1338             for (int i = 0; i < a.length; i += SPECIES.length()) {
1339                 ShortVector av = ShortVector.fromArray(SPECIES, a, i);
1340                 av.intoArray(r, i, b, i, vmask);
1341             }
1342         }
1343 
1344         assertScatterArraysEquals(r, a, b, mask);
1345     }
1346 
1347     static void assertGatherArraysEquals(char[] r, char[] a, int[] indexMap) {
1348         int i = 0;
1349         int j = 0;
1350         try {
1351             for (; i < a.length; i += SPECIES.length()) {
1352                 j = i;
1353                 for (; j < i + SPECIES.length(); j++) {
1354                     Assert.assertEquals(r[j], a[i + indexMap[j]]);
1355                 }
1356             }
1357         } catch (AssertionError e) {
1358             Assert.assertEquals(r[j], a[i + indexMap[j]], "at index #" + j);
1359         }
1360     }
1361 
1362     static void assertGatherArraysEquals(char[] r, char[] a, int[] indexMap, boolean[] mask) {
1363         int i = 0;
1364         int j = 0;
1365         try {
1366             for (; i < a.length; i += SPECIES.length()) {
1367                 j = i;
1368                 for (; j < i + SPECIES.length(); j++) {
1369                     Assert.assertEquals(r[j], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (char) 0);
1370                 }
1371             }
1372         } catch (AssertionError e) {
1373             Assert.assertEquals(r[i], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (char) 0, "at index #" + j);
1374         }
1375     }
1376 
1377     static void assertScatterArraysEquals(char[] r, char[] a, int[] indexMap, boolean[] mask) {
1378         char[] expected = new char[r.length];
1379 
1380         // Store before checking, since the same location may be stored to more than once
1381         for (int i = 0; i < a.length; i += SPECIES.length()) {
1382             for (int j = i; j < i + SPECIES.length(); j++) {
1383                 if (mask[j % SPECIES.length()]) {
1384                     expected[i + indexMap[j]] = a[j];
1385                 }
1386             }
1387         }
1388 
1389         Assert.assertEquals(r, expected);
1390     }
1391 
1392     static void assertScatterArraysEquals(char[] r, char[] a, int[] indexMap) {
1393         char[] expected = new char[r.length];
1394 
1395         // Store before checking, since the same location may be stored to more than once
1396         for (int i = 0; i < a.length; i += SPECIES.length()) {
1397             for (int j = i; j < i + SPECIES.length(); j++) {
1398                 expected[i + indexMap[j]] = a[j];
1399             }
1400         }
1401 
1402         Assert.assertEquals(r, expected);
1403     }
1404 
1405     @DataProvider
1406     public Object[][] charGatherScatterProvider() {
1407         return INT_INDEX_GENERATORS.stream().
1408                 flatMap(fs -> CHAR_GENERATORS.stream().map(fa -> {
1409                     return new Object[] {fa, fs};
1410                 })).
1411                 toArray(Object[][]::new);
1412     }
1413 
1414     @DataProvider
1415     public Object[][] charGatherScatterMaskProvider() {
1416         return BOOLEAN_MASK_GENERATORS.stream().
1417           flatMap(fs -> INT_INDEX_GENERATORS.stream().flatMap(fm ->
1418             CHAR_GENERATORS.stream().map(fa -> {
1419                     return new Object[] {fa, fm, fs};
1420             }))).
1421             toArray(Object[][]::new);
1422     }
1423 
1424 
1425     @Test(dataProvider = "charGatherScatterProvider")
1426     static void charGather(IntFunction<char[]> fa, BiFunction<Integer,Integer,int[]> fs) {
1427         char[] a = fa.apply(SPECIES.length());
1428         int[] b = fs.apply(a.length, SPECIES.length());
1429         char[] r = new char[a.length];
1430 
1431         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1432             for (int i = 0; i < a.length; i += SPECIES.length()) {
1433                 ShortVector av = ShortVector.fromCharArray(SPECIES, a, i, b, i);
1434                 av.intoCharArray(r, i);
1435             }
1436         }
1437 
1438         assertGatherArraysEquals(r, a, b);
1439     }
1440 
1441     @Test(dataProvider = "charGatherScatterMaskProvider")
1442     static void charGatherMask(IntFunction<char[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
1443         char[] a = fa.apply(SPECIES.length());
1444         int[] b = fs.apply(a.length, SPECIES.length());
1445         char[] r = new char[a.length];
1446         boolean[] mask = fm.apply(SPECIES.length());
1447         VectorMask<Short> vmask = VectorMask.fromArray(SPECIES, mask, 0);
1448 
1449         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1450             for (int i = 0; i < a.length; i += SPECIES.length()) {
1451                 ShortVector av = ShortVector.fromCharArray(SPECIES, a, i, b, i, vmask);
1452                 av.intoCharArray(r, i);
1453             }
1454         }
1455 
1456         assertGatherArraysEquals(r, a, b, mask);
1457     }
1458 
1459     @Test(dataProvider = "charGatherScatterProvider")
1460     static void charScatter(IntFunction<char[]> fa, BiFunction<Integer,Integer,int[]> fs) {
1461         char[] a = fa.apply(SPECIES.length());
1462         int[] b = fs.apply(a.length, SPECIES.length());
1463         char[] r = new char[a.length];
1464 
1465         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1466             for (int i = 0; i < a.length; i += SPECIES.length()) {
1467                 ShortVector av = ShortVector.fromCharArray(SPECIES, a, i);
1468                 av.intoCharArray(r, i, b, i);
1469             }
1470         }
1471 
1472         assertScatterArraysEquals(r, a, b);
1473     }
1474 
1475     @Test(dataProvider = "charGatherScatterMaskProvider")
1476     static void charScatterMask(IntFunction<char[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
1477         char[] a = fa.apply(SPECIES.length());
1478         int[] b = fs.apply(a.length, SPECIES.length());
1479         char[] r = new char[a.length];
1480         boolean[] mask = fm.apply(SPECIES.length());
1481         VectorMask<Short> vmask = VectorMask.fromArray(SPECIES, mask, 0);
1482 
1483         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1484             for (int i = 0; i < a.length; i += SPECIES.length()) {
1485                 ShortVector av = ShortVector.fromCharArray(SPECIES, a, i);
1486                 av.intoCharArray(r, i, b, i, vmask);
1487             }
1488         }
1489 
1490         assertScatterArraysEquals(r, a, b, mask);
1491     }
1492 
1493 
1494 }
--- EOF ---