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 ByteMaxVectorLoadStoreTests
  29  *
  30  */
  31 
  32 // -- This file was mechanically generated: Do not edit! -- //
  33 
  34 import java.lang.foreign.MemorySegment;
  35 import java.lang.foreign.Arena;
  36 import java.lang.foreign.ValueLayout;
  37 import jdk.incubator.vector.ByteVector;
  38 import jdk.incubator.vector.VectorMask;
  39 import jdk.incubator.vector.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 ByteMaxVectorLoadStoreTests extends AbstractVectorLoadStoreTest {
  53     static final VectorSpecies<Byte> SPECIES =
  54                 ByteVector.SPECIES_MAX;
  55 
  56     static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 100);
  57 
  58     static final ValueLayout.OfByte ELEMENT_LAYOUT = ValueLayout.JAVA_BYTE.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(byte[] r, byte[] 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] : (byte) 0);
  73             }
  74         } catch (AssertionError e) {
  75             Assert.assertEquals(r[i], mask[i % SPECIES.length()] ? a[i] : (byte) 0, "at index #" + i);
  76         }
  77     }
  78 
  79     static final List<IntFunction<byte[]>> BYTE_GENERATORS = List.of(
  80             withToString("byte[i * 5]", (int s) -> {
  81                 return fill(s * BUFFER_REPS,
  82                             i -> (byte)(i * 5));
  83             }),
  84             withToString("byte[i + 1]", (int s) -> {
  85                 return fill(s * BUFFER_REPS,
  86                             i -> (((byte)(i + 1) == 0) ? 1 : (byte)(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[][] byteProvider() {
 148         return BYTE_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[][] byteProviderForIOOBE() {
 162         var f = BYTE_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[][] byteMaskProvider() {
 171         return BOOLEAN_MASK_GENERATORS.stream().
 172                 flatMap(fm -> BYTE_GENERATORS.stream().map(fa -> {
 173                     return new Object[] {fa, fm};
 174                 })).
 175                 toArray(Object[][]::new);
 176     }
 177 
 178     @DataProvider
 179     public Object[][] byteMaskProviderForIOOBE() {
 180         var f = BYTE_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[][] byteMemorySegmentProvider() {
 190         return BYTE_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[][] byteMemorySegmentMaskProvider() {
 200         return BOOLEAN_MASK_GENERATORS.stream().
 201                 flatMap(fm -> BYTE_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[][] byteByteProviderForIOOBE() {
 211         var f = BYTE_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[][] byteByteMaskProviderForIOOBE() {
 220         var f = BYTE_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(byte[] 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 byte[] segmentToArray(MemorySegment ms) {
 237         return ms.toArray(ELEMENT_LAYOUT);
 238     }
 239 
 240 
 241     interface ToByteF {
 242         byte apply(int i);
 243     }
 244 
 245     static byte[] fill(int s , ToByteF f) {
 246         return fill(new byte[s], f);
 247     }
 248 
 249     static byte[] fill(byte[] a, ToByteF 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 ByteVector fromArray(byte[] a, int i) {
 258         return ByteVector.fromArray(SPECIES, a, i);
 259     }
 260 
 261     @DontInline
 262     static ByteVector fromArray(byte[] a, int i, VectorMask<Byte> m) {
 263         return ByteVector.fromArray(SPECIES, a, i, m);
 264     }
 265 
 266     @DontInline
 267     static void intoArray(ByteVector v, byte[] a, int i) {
 268         v.intoArray(a, i);
 269     }
 270 
 271     @DontInline
 272     static void intoArray(ByteVector v, byte[] a, int i, VectorMask<Byte> m) {
 273         v.intoArray(a, i, m);
 274     }
 275 
 276     @DontInline
 277     static ByteVector fromMemorySegment(MemorySegment a, int i, ByteOrder bo) {
 278         return ByteVector.fromMemorySegment(SPECIES, a, i, bo);
 279     }
 280 
 281     @DontInline
 282     static ByteVector fromMemorySegment(MemorySegment a, int i, ByteOrder bo, VectorMask<Byte> m) {
 283         return ByteVector.fromMemorySegment(SPECIES, a, i, bo, m);
 284     }
 285 
 286     @DontInline
 287     static void intoMemorySegment(ByteVector v, MemorySegment a, int i, ByteOrder bo) {
 288         v.intoMemorySegment(a, i, bo);
 289     }
 290 
 291     @DontInline
 292     static void intoMemorySegment(ByteVector v, MemorySegment a, int i, ByteOrder bo, VectorMask<Byte> m) {
 293         v.intoMemorySegment(a, i, bo, m);
 294     }
 295 
 296     @Test(dataProvider = "byteProvider")
 297     static void loadStoreArray(IntFunction<byte[]> fa) {
 298         byte[] a = fa.apply(SPECIES.length());
 299         byte[] r = new byte[a.length];
 300 
 301         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 302             for (int i = 0; i < a.length; i += SPECIES.length()) {
 303                 ByteVector av = ByteVector.fromArray(SPECIES, a, i);
 304                 av.intoArray(r, i);
 305             }
 306         }
 307         Assert.assertEquals(r, a);
 308     }
 309 
 310     @Test(dataProvider = "byteProviderForIOOBE")
 311     static void loadArrayIOOBE(IntFunction<byte[]> fa, IntFunction<Integer> fi) {
 312         byte[] a = fa.apply(SPECIES.length());
 313         byte[] r = new byte[a.length];
 314 
 315         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 316             for (int i = 0; i < a.length; i += SPECIES.length()) {
 317                 ByteVector 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 = "byteProviderForIOOBE")
 337     static void storeArrayIOOBE(IntFunction<byte[]> fa, IntFunction<Integer> fi) {
 338         byte[] a = fa.apply(SPECIES.length());
 339         byte[] r = new byte[a.length];
 340 
 341         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 342             for (int i = 0; i < a.length; i += SPECIES.length()) {
 343                 ByteVector av = ByteVector.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             ByteVector av = ByteVector.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 = "byteMaskProvider")
 365     static void loadStoreMaskArray(IntFunction<byte[]> fa,
 366                                    IntFunction<boolean[]> fm) {
 367         byte[] a = fa.apply(SPECIES.length());
 368         byte[] r = new byte[a.length];
 369         boolean[] mask = fm.apply(SPECIES.length());
 370         VectorMask<Byte> 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                 ByteVector av = ByteVector.fromArray(SPECIES, a, i, vmask);
 375                 av.intoArray(r, i);
 376             }
 377         }
 378         assertArraysEquals(r, a, mask);
 379 
 380 
 381         r = new byte[a.length];
 382 
 383         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 384             for (int i = 0; i < a.length; i += SPECIES.length()) {
 385                 ByteVector av = ByteVector.fromArray(SPECIES, a, i);
 386                 av.intoArray(r, i, vmask);
 387             }
 388         }
 389         assertArraysEquals(r, a, mask);
 390     }
 391 
 392     @Test(dataProvider = "byteMaskProviderForIOOBE")
 393     static void loadArrayMaskIOOBE(IntFunction<byte[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
 394         byte[] a = fa.apply(SPECIES.length());
 395         byte[] r = new byte[a.length];
 396         boolean[] mask = fm.apply(SPECIES.length());
 397         VectorMask<Byte> 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                 ByteVector 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 = "byteMaskProviderForIOOBE")
 421     static void storeArrayMaskIOOBE(IntFunction<byte[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
 422         byte[] a = fa.apply(SPECIES.length());
 423         byte[] r = new byte[a.length];
 424         boolean[] mask = fm.apply(SPECIES.length());
 425         VectorMask<Byte> 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                 ByteVector av = ByteVector.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             ByteVector av = ByteVector.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 = "byteMaskProvider")
 451     static void loadStoreMask(IntFunction<byte[]> 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<Byte> vmask = VectorMask.fromArray(SPECIES, mask, i);
 459                 vmask.intoArray(r, i);
 460             }
 461         }
 462         Assert.assertEquals(r, mask);
 463     }
 464 
 465 
 466     @Test(dataProvider = "byteMemorySegmentProvider")
 467     static void loadStoreMemorySegment(IntFunction<byte[]> 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                 ByteVector av = ByteVector.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 = "byteByteProviderForIOOBE")
 487     static void loadMemorySegmentIOOBE(IntFunction<byte[]> fa, IntFunction<Integer> fi) {
 488         MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Byte.SIZE));
 489         MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Byte.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                 ByteVector 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 = "byteByteProviderForIOOBE")
 516     static void storeMemorySegmentIOOBE(IntFunction<byte[]> fa, IntFunction<Integer> fi) {
 517         MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Byte.SIZE));
 518         MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Byte.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                 ByteVector av = ByteVector.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             ByteVector av = ByteVector.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 = "byteMemorySegmentMaskProvider")
 546     static void loadStoreMemorySegmentMask(IntFunction<byte[]> fa,
 547                                            IntFunction<MemorySegment> fb,
 548                                            IntFunction<boolean[]> fm,
 549                                            ByteOrder bo) {
 550         byte[] _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<Byte> 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                 ByteVector av = ByteVector.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                 ByteVector av = ByteVector.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 = "byteByteMaskProviderForIOOBE")
 580     static void loadMemorySegmentMaskIOOBE(IntFunction<byte[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
 581         MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Byte.SIZE));
 582         MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Byte.SIZE);
 583         boolean[] mask = fm.apply(SPECIES.length());
 584         VectorMask<Byte> 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                 ByteVector 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 = "byteByteMaskProviderForIOOBE")
 611     static void storeMemorySegmentMaskIOOBE(IntFunction<byte[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
 612         MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Byte.SIZE));
 613         MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Byte.SIZE);
 614         boolean[] mask = fm.apply(SPECIES.length());
 615         VectorMask<Byte> 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                 ByteVector av = ByteVector.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             ByteVector av = ByteVector.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 = "byteMemorySegmentProvider")
 643     static void loadStoreReadonlyMemorySegment(IntFunction<byte[]> 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<Byte> 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<Byte> 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 
 701     static void assertArraysEquals(boolean[] r, byte[] a) {
 702         int i = 0;
 703         try {
 704             for (; i < a.length; i++) {
 705                 Assert.assertEquals(r[i], (a[i] & 1) == 1);
 706             }
 707         } catch (AssertionError e) {
 708             Assert.assertEquals(r[i], (a[i] & 1) == 1, "at index #" + i);
 709         }
 710     }
 711 
 712     static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] mask) {
 713         int i = 0;
 714         try {
 715             for (; i < a.length; i++) {
 716                 Assert.assertEquals(r[i], mask[i % SPECIES.length()] && a[i]);
 717             }
 718         } catch (AssertionError e) {
 719             Assert.assertEquals(r[i], mask[i % SPECIES.length()] && a[i], "at index #" + i);
 720         }
 721     }
 722 
 723     static boolean[] convertToBooleanArray(byte[] a) {
 724         boolean[] r = new boolean[a.length];
 725 
 726         for (int i = 0; i < a.length; i++) {
 727             r[i] = (a[i] & 1) == 1;
 728         }
 729 
 730         return r;
 731     }
 732 
 733     @Test(dataProvider = "byteProvider")
 734     static void loadByteStoreBooleanArray(IntFunction<byte[]> fa) {
 735         byte[] a = fa.apply(SPECIES.length());
 736         boolean[] r = new boolean[a.length];
 737 
 738         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 739             for (int i = 0; i < a.length; i += SPECIES.length()) {
 740                 ByteVector av = ByteVector.fromArray(SPECIES, a, i);
 741                 av.intoBooleanArray(r, i);
 742             }
 743         }
 744         assertArraysEquals(r, a);
 745     }
 746 
 747     @Test(dataProvider = "byteProvider")
 748     static void loadStoreBooleanArray(IntFunction<byte[]> fa) {
 749         boolean[] a = convertToBooleanArray(fa.apply(SPECIES.length()));
 750         boolean[] r = new boolean[a.length];
 751 
 752         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 753             for (int i = 0; i < a.length; i += SPECIES.length()) {
 754                 ByteVector av = ByteVector.fromBooleanArray(SPECIES, a, i);
 755                 av.intoBooleanArray(r, i);
 756             }
 757         }
 758         Assert.assertEquals(r, a);
 759     }
 760 
 761     @Test(dataProvider = "byteMaskProvider")
 762     static void loadStoreMaskBooleanArray(IntFunction<byte[]> fa,
 763                                           IntFunction<boolean[]> fm) {
 764         boolean[] a = convertToBooleanArray(fa.apply(SPECIES.length()));
 765         boolean[] r = new boolean[a.length];
 766         boolean[] mask = fm.apply(SPECIES.length());
 767         VectorMask<Byte> vmask = VectorMask.fromValues(SPECIES, mask);
 768 
 769         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 770             for (int i = 0; i < a.length; i += SPECIES.length()) {
 771                 ByteVector av = ByteVector.fromBooleanArray(SPECIES, a, i, vmask);
 772                 av.intoBooleanArray(r, i);
 773             }
 774         }
 775         assertArraysEquals(r, a, mask);
 776 
 777 
 778         r = new boolean[a.length];
 779 
 780         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 781             for (int i = 0; i < a.length; i += SPECIES.length()) {
 782                 ByteVector av = ByteVector.fromBooleanArray(SPECIES, a, i);
 783                 av.intoBooleanArray(r, i, vmask);
 784             }
 785         }
 786         assertArraysEquals(r, a, mask);
 787     }
 788 
 789 
 790     // Gather/Scatter load/store tests
 791 
 792     static void assertGatherArraysEquals(byte[] r, byte[] a, int[] indexMap) {
 793         int i = 0;
 794         int j = 0;
 795         try {
 796             for (; i < a.length; i += SPECIES.length()) {
 797                 j = i;
 798                 for (; j < i + SPECIES.length(); j++) {
 799                     Assert.assertEquals(r[j], a[i + indexMap[j]]);
 800                 }
 801             }
 802         } catch (AssertionError e) {
 803             Assert.assertEquals(r[j], a[i + indexMap[j]], "at index #" + j);
 804         }
 805     }
 806 
 807     static void assertGatherArraysEquals(byte[] r, byte[] a, int[] indexMap, boolean[] mask) {
 808         int i = 0;
 809         int j = 0;
 810         try {
 811             for (; i < a.length; i += SPECIES.length()) {
 812                 j = i;
 813                 for (; j < i + SPECIES.length(); j++) {
 814                     Assert.assertEquals(r[j], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (byte) 0);
 815                 }
 816             }
 817         } catch (AssertionError e) {
 818             Assert.assertEquals(r[i], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (byte) 0, "at index #" + j);
 819         }
 820     }
 821 
 822     static void assertScatterArraysEquals(byte[] r, byte[] a, int[] indexMap, boolean[] mask) {
 823         byte[] expected = new byte[r.length];
 824 
 825         // Store before checking, since the same location may be stored to more than once
 826         for (int i = 0; i < a.length; i += SPECIES.length()) {
 827             for (int j = i; j < i + SPECIES.length(); j++) {
 828                 if (mask[j % SPECIES.length()]) {
 829                     expected[i + indexMap[j]] = a[j];
 830                 }
 831             }
 832         }
 833 
 834         Assert.assertEquals(r, expected);
 835     }
 836 
 837     static void assertScatterArraysEquals(byte[] r, byte[] a, int[] indexMap) {
 838         byte[] expected = new byte[r.length];
 839 
 840         // Store before checking, since the same location may be stored to more than once
 841         for (int i = 0; i < a.length; i += SPECIES.length()) {
 842             for (int j = i; j < i + SPECIES.length(); j++) {
 843                 expected[i + indexMap[j]] = a[j];
 844             }
 845         }
 846 
 847         Assert.assertEquals(r, expected);
 848     }
 849 
 850     @DataProvider
 851     public Object[][] gatherScatterProvider() {
 852         return INT_INDEX_GENERATORS.stream().
 853                 flatMap(fs -> BYTE_GENERATORS.stream().map(fa -> {
 854                     return new Object[] {fa, fs};
 855                 })).
 856                 toArray(Object[][]::new);
 857     }
 858 
 859     @DataProvider
 860     public Object[][] gatherScatterMaskProvider() {
 861         return BOOLEAN_MASK_GENERATORS.stream().
 862           flatMap(fs -> INT_INDEX_GENERATORS.stream().flatMap(fm ->
 863             BYTE_GENERATORS.stream().map(fa -> {
 864                     return new Object[] {fa, fm, fs};
 865             }))).
 866             toArray(Object[][]::new);
 867     }
 868 
 869 
 870     @Test(dataProvider = "gatherScatterProvider")
 871     static void gather(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs) {
 872         byte[] a = fa.apply(SPECIES.length());
 873         int[] b = fs.apply(a.length, SPECIES.length());
 874         byte[] r = new byte[a.length];
 875 
 876         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 877             for (int i = 0; i < a.length; i += SPECIES.length()) {
 878                 ByteVector av = ByteVector.fromArray(SPECIES, a, i, b, i);
 879                 av.intoArray(r, i);
 880             }
 881         }
 882 
 883         assertGatherArraysEquals(r, a, b);
 884     }
 885 
 886     @Test(dataProvider = "gatherScatterMaskProvider")
 887     static void gatherMask(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
 888         byte[] a = fa.apply(SPECIES.length());
 889         int[] b = fs.apply(a.length, SPECIES.length());
 890         byte[] r = new byte[a.length];
 891         boolean[] mask = fm.apply(SPECIES.length());
 892         VectorMask<Byte> vmask = VectorMask.fromArray(SPECIES, mask, 0);
 893 
 894         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 895             for (int i = 0; i < a.length; i += SPECIES.length()) {
 896                 ByteVector av = ByteVector.fromArray(SPECIES, a, i, b, i, vmask);
 897                 av.intoArray(r, i);
 898             }
 899         }
 900 
 901         assertGatherArraysEquals(r, a, b, mask);
 902     }
 903 
 904     @Test(dataProvider = "gatherScatterProvider")
 905     static void scatter(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs) {
 906         byte[] a = fa.apply(SPECIES.length());
 907         int[] b = fs.apply(a.length, SPECIES.length());
 908         byte[] r = new byte[a.length];
 909 
 910         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 911             for (int i = 0; i < a.length; i += SPECIES.length()) {
 912                 ByteVector av = ByteVector.fromArray(SPECIES, a, i);
 913                 av.intoArray(r, i, b, i);
 914             }
 915         }
 916 
 917         assertScatterArraysEquals(r, a, b);
 918     }
 919 
 920     @Test(dataProvider = "gatherScatterMaskProvider")
 921     static void scatterMask(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
 922         byte[] a = fa.apply(SPECIES.length());
 923         int[] b = fs.apply(a.length, SPECIES.length());
 924         byte[] r = new byte[a.length];
 925         boolean[] mask = fm.apply(SPECIES.length());
 926         VectorMask<Byte> vmask = VectorMask.fromArray(SPECIES, mask, 0);
 927 
 928         for (int ic = 0; ic < INVOC_COUNT; ic++) {
 929             for (int i = 0; i < a.length; i += SPECIES.length()) {
 930                 ByteVector av = ByteVector.fromArray(SPECIES, a, i);
 931                 av.intoArray(r, i, b, i, vmask);
 932             }
 933         }
 934 
 935         assertScatterArraysEquals(r, a, b, mask);
 936     }
 937 
 938 
 939     static void assertGatherArraysEquals(boolean[] r, boolean[] a, int[] indexMap) {
 940         int i = 0;
 941         int j = 0;
 942         try {
 943             for (; i < a.length; i += SPECIES.length()) {
 944                 j = i;
 945                 for (; j < i + SPECIES.length(); j++) {
 946                     Assert.assertEquals(r[j], a[i + indexMap[j]]);
 947                 }
 948             }
 949         } catch (AssertionError e) {
 950             Assert.assertEquals(r[j], a[i + indexMap[j]], "at index #" + j);
 951         }
 952     }
 953 
 954     static void assertGatherArraysEquals(boolean[] r, boolean[] a, int[] indexMap, boolean[] mask) {
 955         int i = 0;
 956         int j = 0;
 957         try {
 958             for (; i < a.length; i += SPECIES.length()) {
 959                 j = i;
 960                 for (; j < i + SPECIES.length(); j++) {
 961                     Assert.assertEquals(r[j], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: false);
 962                 }
 963             }
 964         } catch (AssertionError e) {
 965             Assert.assertEquals(r[i], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: false, "at index #" + j);
 966         }
 967     }
 968 
 969     static void assertScatterArraysEquals(boolean[] r, boolean[] a, int[] indexMap, boolean[] mask) {
 970         boolean[] expected = new boolean[r.length];
 971 
 972         // Store before checking, since the same location may be stored to more than once
 973         for (int i = 0; i < a.length; i += SPECIES.length()) {
 974             for (int j = i; j < i + SPECIES.length(); j++) {
 975                 if (mask[j % SPECIES.length()]) {
 976                     expected[i + indexMap[j]] = a[j];
 977                 }
 978             }
 979         }
 980 
 981         Assert.assertEquals(r, expected);
 982     }
 983 
 984     static void assertScatterArraysEquals(boolean[] r, boolean[] a, int[] indexMap) {
 985         boolean[] expected = new boolean[r.length];
 986 
 987         // Store before checking, since the same location may be stored to more than once
 988         for (int i = 0; i < a.length; i += SPECIES.length()) {
 989             for (int j = i; j < i + SPECIES.length(); j++) {
 990                 expected[i + indexMap[j]] = a[j];
 991             }
 992         }
 993 
 994         Assert.assertEquals(r, expected);
 995     }
 996 
 997     @Test(dataProvider = "gatherScatterProvider")
 998     static void booleanGather(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs) {
 999         boolean[] a = convertToBooleanArray(fa.apply(SPECIES.length()));
1000         int[] b = fs.apply(a.length, SPECIES.length());
1001         boolean[] r = new boolean[a.length];
1002 
1003         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1004             for (int i = 0; i < a.length; i += SPECIES.length()) {
1005                 ByteVector av = ByteVector.fromBooleanArray(SPECIES, a, i, b, i);
1006                 av.intoBooleanArray(r, i);
1007             }
1008         }
1009 
1010         assertGatherArraysEquals(r, a, b);
1011     }
1012 
1013     @Test(dataProvider = "gatherScatterMaskProvider")
1014     static void booleanGatherMask(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
1015         boolean[] a = convertToBooleanArray(fa.apply(SPECIES.length()));
1016         int[] b = fs.apply(a.length, SPECIES.length());
1017         boolean[] r = new boolean[a.length];
1018         boolean[] mask = fm.apply(SPECIES.length());
1019         VectorMask<Byte> vmask = VectorMask.fromArray(SPECIES, mask, 0);
1020 
1021         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1022             for (int i = 0; i < a.length; i += SPECIES.length()) {
1023                 ByteVector av = ByteVector.fromBooleanArray(SPECIES, a, i, b, i, vmask);
1024                 av.intoBooleanArray(r, i);
1025             }
1026         }
1027 
1028         assertGatherArraysEquals(r, a, b, mask);
1029     }
1030 
1031     @Test(dataProvider = "gatherScatterProvider")
1032     static void booleanScatter(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs) {
1033         boolean[] a = convertToBooleanArray(fa.apply(SPECIES.length()));
1034         int[] b = fs.apply(a.length, SPECIES.length());
1035         boolean[] r = new boolean[a.length];
1036 
1037         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1038             for (int i = 0; i < a.length; i += SPECIES.length()) {
1039                 ByteVector av = ByteVector.fromBooleanArray(SPECIES, a, i);
1040                 av.intoBooleanArray(r, i, b, i);
1041             }
1042         }
1043 
1044         assertScatterArraysEquals(r, a, b);
1045     }
1046 
1047     @Test(dataProvider = "gatherScatterMaskProvider")
1048     static void booleanScatterMask(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
1049         boolean[] a = convertToBooleanArray(fa.apply(SPECIES.length()));
1050         int[] b = fs.apply(a.length, SPECIES.length());
1051         boolean[] r = new boolean[a.length];
1052         boolean[] mask = fm.apply(SPECIES.length());
1053         VectorMask<Byte> vmask = VectorMask.fromArray(SPECIES, mask, 0);
1054 
1055         for (int ic = 0; ic < INVOC_COUNT; ic++) {
1056             for (int i = 0; i < a.length; i += SPECIES.length()) {
1057                 ByteVector av = ByteVector.fromBooleanArray(SPECIES, a, i);
1058                 av.intoBooleanArray(r, i, b, i, vmask);
1059             }
1060         }
1061 
1062         assertScatterArraysEquals(r, a, b, mask);
1063     }
1064 
1065 }