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 LongMaxVectorLoadStoreTests
 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.LongVector;
 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 LongMaxVectorLoadStoreTests extends AbstractVectorLoadStoreTest {
 53     static final VectorSpecies<Long> SPECIES =
 54                 LongVector.SPECIES_MAX;
 55 
 56     static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 100);
 57 
 58     static final ValueLayout.OfLong ELEMENT_LAYOUT = ValueLayout.JAVA_LONG.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(long[] r, long[] 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] : (long) 0);
 73             }
 74         } catch (AssertionError e) {
 75             Assert.assertEquals(r[i], mask[i % SPECIES.length()] ? a[i] : (long) 0, "at index #" + i);
 76         }
 77     }
 78 
 79     static final List<IntFunction<long[]>> LONG_GENERATORS = List.of(
 80             withToString("long[i * 5]", (int s) -> {
 81                 return fill(s * BUFFER_REPS,
 82                             i -> (long)(i * 5));
 83             }),
 84             withToString("long[i + 1]", (int s) -> {
 85                 return fill(s * BUFFER_REPS,
 86                             i -> (((long)(i + 1) == 0) ? 1 : (long)(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[][] longProvider() {
148         return LONG_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[][] longProviderForIOOBE() {
162         var f = LONG_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[][] longMaskProvider() {
171         return BOOLEAN_MASK_GENERATORS.stream().
172                 flatMap(fm -> LONG_GENERATORS.stream().map(fa -> {
173                     return new Object[] {fa, fm};
174                 })).
175                 toArray(Object[][]::new);
176     }
177 
178     @DataProvider
179     public Object[][] longMaskProviderForIOOBE() {
180         var f = LONG_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[][] longMemorySegmentProvider() {
190         return LONG_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[][] longMemorySegmentMaskProvider() {
200         return BOOLEAN_MASK_GENERATORS.stream().
201                 flatMap(fm -> LONG_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[][] longByteProviderForIOOBE() {
211         var f = LONG_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[][] longByteMaskProviderForIOOBE() {
220         var f = LONG_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(long[] 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 long[] segmentToArray(MemorySegment ms) {
237         return ms.toArray(ELEMENT_LAYOUT);
238     }
239 
240 
241     interface ToLongF {
242         long apply(int i);
243     }
244 
245     static long[] fill(int s , ToLongF f) {
246         return fill(new long[s], f);
247     }
248 
249     static long[] fill(long[] a, ToLongF 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 LongVector fromArray(long[] a, int i) {
258         return LongVector.fromArray(SPECIES, a, i);
259     }
260 
261     @DontInline
262     static LongVector fromArray(long[] a, int i, VectorMask<Long> m) {
263         return LongVector.fromArray(SPECIES, a, i, m);
264     }
265 
266     @DontInline
267     static void intoArray(LongVector v, long[] a, int i) {
268         v.intoArray(a, i);
269     }
270 
271     @DontInline
272     static void intoArray(LongVector v, long[] a, int i, VectorMask<Long> m) {
273         v.intoArray(a, i, m);
274     }
275 
276     @DontInline
277     static LongVector fromMemorySegment(MemorySegment a, int i, ByteOrder bo) {
278         return LongVector.fromMemorySegment(SPECIES, a, i, bo);
279     }
280 
281     @DontInline
282     static LongVector fromMemorySegment(MemorySegment a, int i, ByteOrder bo, VectorMask<Long> m) {
283         return LongVector.fromMemorySegment(SPECIES, a, i, bo, m);
284     }
285 
286     @DontInline
287     static void intoMemorySegment(LongVector v, MemorySegment a, int i, ByteOrder bo) {
288         v.intoMemorySegment(a, i, bo);
289     }
290 
291     @DontInline
292     static void intoMemorySegment(LongVector v, MemorySegment a, int i, ByteOrder bo, VectorMask<Long> m) {
293         v.intoMemorySegment(a, i, bo, m);
294     }
295 
296     @Test(dataProvider = "longProvider")
297     static void loadStoreArray(IntFunction<long[]> fa) {
298         long[] a = fa.apply(SPECIES.length());
299         long[] r = new long[a.length];
300 
301         for (int ic = 0; ic < INVOC_COUNT; ic++) {
302             for (int i = 0; i < a.length; i += SPECIES.length()) {
303                 LongVector av = LongVector.fromArray(SPECIES, a, i);
304                 av.intoArray(r, i);
305             }
306         }
307         Assert.assertEquals(r, a);
308     }
309 
310     @Test(dataProvider = "longProviderForIOOBE")
311     static void loadArrayIOOBE(IntFunction<long[]> fa, IntFunction<Integer> fi) {
312         long[] a = fa.apply(SPECIES.length());
313         long[] r = new long[a.length];
314 
315         for (int ic = 0; ic < INVOC_COUNT; ic++) {
316             for (int i = 0; i < a.length; i += SPECIES.length()) {
317                 LongVector 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 = "longProviderForIOOBE")
337     static void storeArrayIOOBE(IntFunction<long[]> fa, IntFunction<Integer> fi) {
338         long[] a = fa.apply(SPECIES.length());
339         long[] r = new long[a.length];
340 
341         for (int ic = 0; ic < INVOC_COUNT; ic++) {
342             for (int i = 0; i < a.length; i += SPECIES.length()) {
343                 LongVector av = LongVector.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             LongVector av = LongVector.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 = "longMaskProvider")
365     static void loadStoreMaskArray(IntFunction<long[]> fa,
366                                    IntFunction<boolean[]> fm) {
367         long[] a = fa.apply(SPECIES.length());
368         long[] r = new long[a.length];
369         boolean[] mask = fm.apply(SPECIES.length());
370         VectorMask<Long> 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                 LongVector av = LongVector.fromArray(SPECIES, a, i, vmask);
375                 av.intoArray(r, i);
376             }
377         }
378         assertArraysEquals(r, a, mask);
379 
380 
381         r = new long[a.length];
382 
383         for (int ic = 0; ic < INVOC_COUNT; ic++) {
384             for (int i = 0; i < a.length; i += SPECIES.length()) {
385                 LongVector av = LongVector.fromArray(SPECIES, a, i);
386                 av.intoArray(r, i, vmask);
387             }
388         }
389         assertArraysEquals(r, a, mask);
390     }
391 
392     @Test(dataProvider = "longMaskProviderForIOOBE")
393     static void loadArrayMaskIOOBE(IntFunction<long[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
394         long[] a = fa.apply(SPECIES.length());
395         long[] r = new long[a.length];
396         boolean[] mask = fm.apply(SPECIES.length());
397         VectorMask<Long> 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                 LongVector 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 = "longMaskProviderForIOOBE")
421     static void storeArrayMaskIOOBE(IntFunction<long[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
422         long[] a = fa.apply(SPECIES.length());
423         long[] r = new long[a.length];
424         boolean[] mask = fm.apply(SPECIES.length());
425         VectorMask<Long> 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                 LongVector av = LongVector.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             LongVector av = LongVector.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 = "longMaskProvider")
451     static void loadStoreMask(IntFunction<long[]> 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<Long> vmask = VectorMask.fromArray(SPECIES, mask, i);
459                 vmask.intoArray(r, i);
460             }
461         }
462         Assert.assertEquals(r, mask);
463     }
464 
465 
466     @Test(dataProvider = "longMemorySegmentProvider")
467     static void loadStoreMemorySegment(IntFunction<long[]> 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                 LongVector av = LongVector.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 = "longByteProviderForIOOBE")
487     static void loadMemorySegmentIOOBE(IntFunction<long[]> fa, IntFunction<Integer> fi) {
488         MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Long.SIZE));
489         MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Long.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                 LongVector 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 = "longByteProviderForIOOBE")
516     static void storeMemorySegmentIOOBE(IntFunction<long[]> fa, IntFunction<Integer> fi) {
517         MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Long.SIZE));
518         MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Long.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                 LongVector av = LongVector.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             LongVector av = LongVector.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 = "longMemorySegmentMaskProvider")
546     static void loadStoreMemorySegmentMask(IntFunction<long[]> fa,
547                                            IntFunction<MemorySegment> fb,
548                                            IntFunction<boolean[]> fm,
549                                            ByteOrder bo) {
550         long[] _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<Long> 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                 LongVector av = LongVector.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                 LongVector av = LongVector.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 = "longByteMaskProviderForIOOBE")
580     static void loadMemorySegmentMaskIOOBE(IntFunction<long[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
581         MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Long.SIZE));
582         MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Long.SIZE);
583         boolean[] mask = fm.apply(SPECIES.length());
584         VectorMask<Long> 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                 LongVector 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 = "longByteMaskProviderForIOOBE")
611     static void storeMemorySegmentMaskIOOBE(IntFunction<long[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
612         MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Long.SIZE));
613         MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Long.SIZE);
614         boolean[] mask = fm.apply(SPECIES.length());
615         VectorMask<Long> 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                 LongVector av = LongVector.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             LongVector av = LongVector.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 = "longMemorySegmentProvider")
643     static void loadStoreReadonlyMemorySegment(IntFunction<long[]> 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<Long> 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<Long> 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 
702 
703     // Gather/Scatter load/store tests
704 
705     static void assertGatherArraysEquals(long[] r, long[] a, int[] indexMap) {
706         int i = 0;
707         int j = 0;
708         try {
709             for (; i < a.length; i += SPECIES.length()) {
710                 j = i;
711                 for (; j < i + SPECIES.length(); j++) {
712                     Assert.assertEquals(r[j], a[i + indexMap[j]]);
713                 }
714             }
715         } catch (AssertionError e) {
716             Assert.assertEquals(r[j], a[i + indexMap[j]], "at index #" + j);
717         }
718     }
719 
720     static void assertGatherArraysEquals(long[] r, long[] a, int[] indexMap, boolean[] mask) {
721         int i = 0;
722         int j = 0;
723         try {
724             for (; i < a.length; i += SPECIES.length()) {
725                 j = i;
726                 for (; j < i + SPECIES.length(); j++) {
727                     Assert.assertEquals(r[j], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (long) 0);
728                 }
729             }
730         } catch (AssertionError e) {
731             Assert.assertEquals(r[i], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (long) 0, "at index #" + j);
732         }
733     }
734 
735     static void assertScatterArraysEquals(long[] r, long[] a, int[] indexMap, boolean[] mask) {
736         long[] expected = new long[r.length];
737 
738         // Store before checking, since the same location may be stored to more than once
739         for (int i = 0; i < a.length; i += SPECIES.length()) {
740             for (int j = i; j < i + SPECIES.length(); j++) {
741                 if (mask[j % SPECIES.length()]) {
742                     expected[i + indexMap[j]] = a[j];
743                 }
744             }
745         }
746 
747         Assert.assertEquals(r, expected);
748     }
749 
750     static void assertScatterArraysEquals(long[] r, long[] a, int[] indexMap) {
751         long[] expected = new long[r.length];
752 
753         // Store before checking, since the same location may be stored to more than once
754         for (int i = 0; i < a.length; i += SPECIES.length()) {
755             for (int j = i; j < i + SPECIES.length(); j++) {
756                 expected[i + indexMap[j]] = a[j];
757             }
758         }
759 
760         Assert.assertEquals(r, expected);
761     }
762 
763     @DataProvider
764     public Object[][] gatherScatterProvider() {
765         return INT_INDEX_GENERATORS.stream().
766                 flatMap(fs -> LONG_GENERATORS.stream().map(fa -> {
767                     return new Object[] {fa, fs};
768                 })).
769                 toArray(Object[][]::new);
770     }
771 
772     @DataProvider
773     public Object[][] gatherScatterMaskProvider() {
774         return BOOLEAN_MASK_GENERATORS.stream().
775           flatMap(fs -> INT_INDEX_GENERATORS.stream().flatMap(fm ->
776             LONG_GENERATORS.stream().map(fa -> {
777                     return new Object[] {fa, fm, fs};
778             }))).
779             toArray(Object[][]::new);
780     }
781 
782 
783     @Test(dataProvider = "gatherScatterProvider")
784     static void gather(IntFunction<long[]> fa, BiFunction<Integer,Integer,int[]> fs) {
785         long[] a = fa.apply(SPECIES.length());
786         int[] b = fs.apply(a.length, SPECIES.length());
787         long[] r = new long[a.length];
788 
789         for (int ic = 0; ic < INVOC_COUNT; ic++) {
790             for (int i = 0; i < a.length; i += SPECIES.length()) {
791                 LongVector av = LongVector.fromArray(SPECIES, a, i, b, i);
792                 av.intoArray(r, i);
793             }
794         }
795 
796         assertGatherArraysEquals(r, a, b);
797     }
798 
799     @Test(dataProvider = "gatherScatterMaskProvider")
800     static void gatherMask(IntFunction<long[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
801         long[] a = fa.apply(SPECIES.length());
802         int[] b = fs.apply(a.length, SPECIES.length());
803         long[] r = new long[a.length];
804         boolean[] mask = fm.apply(SPECIES.length());
805         VectorMask<Long> vmask = VectorMask.fromArray(SPECIES, mask, 0);
806 
807         for (int ic = 0; ic < INVOC_COUNT; ic++) {
808             for (int i = 0; i < a.length; i += SPECIES.length()) {
809                 LongVector av = LongVector.fromArray(SPECIES, a, i, b, i, vmask);
810                 av.intoArray(r, i);
811             }
812         }
813 
814         assertGatherArraysEquals(r, a, b, mask);
815     }
816 
817     @Test(dataProvider = "gatherScatterProvider")
818     static void scatter(IntFunction<long[]> fa, BiFunction<Integer,Integer,int[]> fs) {
819         long[] a = fa.apply(SPECIES.length());
820         int[] b = fs.apply(a.length, SPECIES.length());
821         long[] r = new long[a.length];
822 
823         for (int ic = 0; ic < INVOC_COUNT; ic++) {
824             for (int i = 0; i < a.length; i += SPECIES.length()) {
825                 LongVector av = LongVector.fromArray(SPECIES, a, i);
826                 av.intoArray(r, i, b, i);
827             }
828         }
829 
830         assertScatterArraysEquals(r, a, b);
831     }
832 
833     @Test(dataProvider = "gatherScatterMaskProvider")
834     static void scatterMask(IntFunction<long[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
835         long[] a = fa.apply(SPECIES.length());
836         int[] b = fs.apply(a.length, SPECIES.length());
837         long[] r = new long[a.length];
838         boolean[] mask = fm.apply(SPECIES.length());
839         VectorMask<Long> vmask = VectorMask.fromArray(SPECIES, mask, 0);
840 
841         for (int ic = 0; ic < INVOC_COUNT; ic++) {
842             for (int i = 0; i < a.length; i += SPECIES.length()) {
843                 LongVector av = LongVector.fromArray(SPECIES, a, i);
844                 av.intoArray(r, i, b, i, vmask);
845             }
846         }
847 
848         assertScatterArraysEquals(r, a, b, mask);
849     }
850 
851 
852 
853 }