1 /*
  2  * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 /*
 25  * @test
 26  * @enablePreview
 27  * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation
 28  * @run testng/othervm -XX:-TieredCompilation Double256VectorLoadStoreTests
 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.DoubleVector;
 38 import jdk.incubator.vector.VectorMask;
 39 import jdk.incubator.vector.VectorSpecies;
 40 import jdk.incubator.vector.VectorShuffle;
 41 import jdk.internal.vm.annotation.DontInline;
 42 import org.testng.Assert;
 43 import org.testng.annotations.DataProvider;
 44 import org.testng.annotations.Test;
 45 
 46 import java.nio.ByteOrder;
 47 import java.util.List;
 48 import java.util.function.*;
 49 
 50 @Test
 51 public class Double256VectorLoadStoreTests extends AbstractVectorLoadStoreTest {
 52     static final VectorSpecies<Double> SPECIES =
 53                 DoubleVector.SPECIES_256;
 54 
 55     static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 100);
 56 
 57     static final ValueLayout.OfDouble ELEMENT_LAYOUT = ValueLayout.JAVA_DOUBLE.withByteAlignment(1);
 58 
 59 
 60     static final int BUFFER_REPS = Integer.getInteger("jdk.incubator.vector.test.buffer-vectors", 25000 / 256);
 61 
 62     static void assertArraysEquals(double[] r, double[] a, boolean[] mask) {
 63         int i = 0;
 64         try {
 65             for (; i < a.length; i++) {
 66                 Assert.assertEquals(r[i], mask[i % SPECIES.length()] ? a[i] : (double) 0);
 67             }
 68         } catch (AssertionError e) {
 69             Assert.assertEquals(r[i], mask[i % SPECIES.length()] ? a[i] : (double) 0, "at index #" + i);
 70         }
 71     }
 72 
 73     static final List<IntFunction<double[]>> DOUBLE_GENERATORS = List.of(
 74             withToString("double[i * 5]", (int s) -> {
 75                 return fill(s * BUFFER_REPS,
 76                             i -> (double)(i * 5));
 77             }),
 78             withToString("double[i + 1]", (int s) -> {
 79                 return fill(s * BUFFER_REPS,
 80                             i -> (((double)(i + 1) == 0) ? 1 : (double)(i + 1)));
 81             })
 82     );
 83 
 84     // Relative to array.length
 85     static final List<IntFunction<Integer>> INDEX_GENERATORS = List.of(
 86             withToString("-1", (int l) -> {
 87                 return -1;
 88             }),
 89             withToString("l", (int l) -> {
 90                 return l;
 91             }),
 92             withToString("l - 1", (int l) -> {
 93                 return l - 1;
 94             }),
 95             withToString("l + 1", (int l) -> {
 96                 return l + 1;
 97             }),
 98             withToString("l - speciesl + 1", (int l) -> {
 99                 return l - SPECIES.length() + 1;
100             }),
101             withToString("l + speciesl - 1", (int l) -> {
102                 return l + SPECIES.length() - 1;
103             }),
104             withToString("l + speciesl", (int l) -> {
105                 return l + SPECIES.length();
106             }),
107             withToString("l + speciesl + 1", (int l) -> {
108                 return l + SPECIES.length() + 1;
109             })
110     );
111 
112     // Relative to byte[] array.length or MemorySegment.byteSize()
113     static final List<IntFunction<Integer>> BYTE_INDEX_GENERATORS = List.of(
114             withToString("-1", (int l) -> {
115                 return -1;
116             }),
117             withToString("l", (int l) -> {
118                 return l;
119             }),
120             withToString("l - 1", (int l) -> {
121                 return l - 1;
122             }),
123             withToString("l + 1", (int l) -> {
124                 return l + 1;
125             }),
126             withToString("l - speciesl*ebsize + 1", (int l) -> {
127                 return l - SPECIES.vectorByteSize() + 1;
128             }),
129             withToString("l + speciesl*ebsize - 1", (int l) -> {
130                 return l + SPECIES.vectorByteSize() - 1;
131             }),
132             withToString("l + speciesl*ebsize", (int l) -> {
133                 return l + SPECIES.vectorByteSize();
134             }),
135             withToString("l + speciesl*ebsize + 1", (int l) -> {
136                 return l + SPECIES.vectorByteSize() + 1;
137             })
138     );
139 
140     @DataProvider
141     public Object[][] doubleProvider() {
142         return DOUBLE_GENERATORS.stream().
143                 map(f -> new Object[]{f}).
144                 toArray(Object[][]::new);
145     }
146 
147     @DataProvider
148     public Object[][] maskProvider() {
149         return BOOLEAN_MASK_GENERATORS.stream().
150                 map(f -> new Object[]{f}).
151                 toArray(Object[][]::new);
152     }
153 
154     @DataProvider
155     public Object[][] doubleProviderForIOOBE() {
156         var f = DOUBLE_GENERATORS.get(0);
157         return INDEX_GENERATORS.stream().map(fi -> {
158                     return new Object[] {f, fi};
159                 }).
160                 toArray(Object[][]::new);
161     }
162 
163     @DataProvider
164     public Object[][] doubleMaskProvider() {
165         return BOOLEAN_MASK_GENERATORS.stream().
166                 flatMap(fm -> DOUBLE_GENERATORS.stream().map(fa -> {
167                     return new Object[] {fa, fm};
168                 })).
169                 toArray(Object[][]::new);
170     }
171 
172     @DataProvider
173     public Object[][] doubleMaskProviderForIOOBE() {
174         var f = DOUBLE_GENERATORS.get(0);
175         return BOOLEAN_MASK_GENERATORS.stream().
176                 flatMap(fm -> INDEX_GENERATORS.stream().map(fi -> {
177                     return new Object[] {f, fi, fm};
178                 })).
179                 toArray(Object[][]::new);
180     }
181 
182     @DataProvider
183     public Object[][] doubleMemorySegmentProvider() {
184         return DOUBLE_GENERATORS.stream().
185                 flatMap(fa -> MEMORY_SEGMENT_GENERATORS.stream().
186                         flatMap(fb -> BYTE_ORDER_VALUES.stream().map(bo -> {
187                             return new Object[]{fa, fb, bo};
188                         }))).
189                 toArray(Object[][]::new);
190     }
191 
192     @DataProvider
193     public Object[][] doubleMemorySegmentMaskProvider() {
194         return BOOLEAN_MASK_GENERATORS.stream().
195                 flatMap(fm -> DOUBLE_GENERATORS.stream().
196                         flatMap(fa -> MEMORY_SEGMENT_GENERATORS.stream().
197                                 flatMap(fb -> BYTE_ORDER_VALUES.stream().map(bo -> {
198                             return new Object[]{fa, fb, fm, bo};
199                         })))).
200                 toArray(Object[][]::new);
201     }
202 
203     @DataProvider
204     public Object[][] doubleByteProviderForIOOBE() {
205         var f = DOUBLE_GENERATORS.get(0);
206         return BYTE_INDEX_GENERATORS.stream().map(fi -> {
207                     return new Object[] {f, fi};
208                 }).
209                 toArray(Object[][]::new);
210     }
211 
212     @DataProvider
213     public Object[][] doubleByteMaskProviderForIOOBE() {
214         var f = DOUBLE_GENERATORS.get(0);
215         return BOOLEAN_MASK_GENERATORS.stream().
216                 flatMap(fm -> BYTE_INDEX_GENERATORS.stream().map(fi -> {
217                     return new Object[] {f, fi, fm};
218                 })).
219                 toArray(Object[][]::new);
220     }
221 
222     static MemorySegment toSegment(double[] a, IntFunction<MemorySegment> fb) {
223         MemorySegment ms = fb.apply(a.length * SPECIES.elementSize() / 8);
224         for (int i = 0; i < a.length; i++) {
225             ms.set(ELEMENT_LAYOUT, i * SPECIES.elementSize() / 8 , a[i]);
226         }
227         return ms;
228     }
229 
230     static double[] segmentToArray(MemorySegment ms) {
231         return ms.toArray(ELEMENT_LAYOUT);
232     }
233 
234 
235     interface ToDoubleF {
236         double apply(int i);
237     }
238 
239     static double[] fill(int s , ToDoubleF f) {
240         return fill(new double[s], f);
241     }
242 
243     static double[] fill(double[] a, ToDoubleF f) {
244         for (int i = 0; i < a.length; i++) {
245             a[i] = f.apply(i);
246         }
247         return a;
248     }
249 
250     @DontInline
251     static DoubleVector fromArray(double[] a, int i) {
252         return DoubleVector.fromArray(SPECIES, a, i);
253     }
254 
255     @DontInline
256     static DoubleVector fromArray(double[] a, int i, VectorMask<Double> m) {
257         return DoubleVector.fromArray(SPECIES, a, i, m);
258     }
259 
260     @DontInline
261     static void intoArray(DoubleVector v, double[] a, int i) {
262         v.intoArray(a, i);
263     }
264 
265     @DontInline
266     static void intoArray(DoubleVector v, double[] a, int i, VectorMask<Double> m) {
267         v.intoArray(a, i, m);
268     }
269 
270     @DontInline
271     static DoubleVector fromMemorySegment(MemorySegment a, int i, ByteOrder bo) {
272         return DoubleVector.fromMemorySegment(SPECIES, a, i, bo);
273     }
274 
275     @DontInline
276     static DoubleVector fromMemorySegment(MemorySegment a, int i, ByteOrder bo, VectorMask<Double> m) {
277         return DoubleVector.fromMemorySegment(SPECIES, a, i, bo, m);
278     }
279 
280     @DontInline
281     static void intoMemorySegment(DoubleVector v, MemorySegment a, int i, ByteOrder bo) {
282         v.intoMemorySegment(a, i, bo);
283     }
284 
285     @DontInline
286     static void intoMemorySegment(DoubleVector v, MemorySegment a, int i, ByteOrder bo, VectorMask<Double> m) {
287         v.intoMemorySegment(a, i, bo, m);
288     }
289 
290     @Test(dataProvider = "doubleProvider")
291     static void loadStoreArray(IntFunction<double[]> fa) {
292         double[] a = fa.apply(SPECIES.length());
293         double[] r = new double[a.length];
294 
295         for (int ic = 0; ic < INVOC_COUNT; ic++) {
296             for (int i = 0; i < a.length; i += SPECIES.length()) {
297                 DoubleVector av = DoubleVector.fromArray(SPECIES, a, i);
298                 av.intoArray(r, i);
299             }
300         }
301         Assert.assertEquals(r, a);
302     }
303 
304     @Test(dataProvider = "doubleProviderForIOOBE")
305     static void loadArrayIOOBE(IntFunction<double[]> fa, IntFunction<Integer> fi) {
306         double[] a = fa.apply(SPECIES.length());
307         double[] r = new double[a.length];
308 
309         for (int ic = 0; ic < INVOC_COUNT; ic++) {
310             for (int i = 0; i < a.length; i += SPECIES.length()) {
311                 DoubleVector av = fromArray(a, i);
312                 av.intoArray(r, i);
313             }
314         }
315 
316         int index = fi.apply(a.length);
317         boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length);
318         try {
319             fromArray(a, index);
320             if (shouldFail) {
321                 Assert.fail("Failed to throw IndexOutOfBoundsException");
322             }
323         } catch (IndexOutOfBoundsException e) {
324             if (!shouldFail) {
325                 Assert.fail("Unexpected IndexOutOfBoundsException");
326             }
327         }
328     }
329 
330     @Test(dataProvider = "doubleProviderForIOOBE")
331     static void storeArrayIOOBE(IntFunction<double[]> fa, IntFunction<Integer> fi) {
332         double[] a = fa.apply(SPECIES.length());
333         double[] r = new double[a.length];
334 
335         for (int ic = 0; ic < INVOC_COUNT; ic++) {
336             for (int i = 0; i < a.length; i += SPECIES.length()) {
337                 DoubleVector av = DoubleVector.fromArray(SPECIES, a, i);
338                 intoArray(av, r, i);
339             }
340         }
341 
342         int index = fi.apply(a.length);
343         boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length);
344         try {
345             DoubleVector av = DoubleVector.fromArray(SPECIES, a, 0);
346             intoArray(av, r, index);
347             if (shouldFail) {
348                 Assert.fail("Failed to throw IndexOutOfBoundsException");
349             }
350         } catch (IndexOutOfBoundsException e) {
351             if (!shouldFail) {
352                 Assert.fail("Unexpected IndexOutOfBoundsException");
353             }
354         }
355     }
356 
357 
358     @Test(dataProvider = "doubleMaskProvider")
359     static void loadStoreMaskArray(IntFunction<double[]> fa,
360                                    IntFunction<boolean[]> fm) {
361         double[] a = fa.apply(SPECIES.length());
362         double[] r = new double[a.length];
363         boolean[] mask = fm.apply(SPECIES.length());
364         VectorMask<Double> vmask = VectorMask.fromValues(SPECIES, mask);
365 
366         for (int ic = 0; ic < INVOC_COUNT; ic++) {
367             for (int i = 0; i < a.length; i += SPECIES.length()) {
368                 DoubleVector av = DoubleVector.fromArray(SPECIES, a, i, vmask);
369                 av.intoArray(r, i);
370             }
371         }
372         assertArraysEquals(r, a, mask);
373 
374 
375         r = new double[a.length];
376 
377         for (int ic = 0; ic < INVOC_COUNT; ic++) {
378             for (int i = 0; i < a.length; i += SPECIES.length()) {
379                 DoubleVector av = DoubleVector.fromArray(SPECIES, a, i);
380                 av.intoArray(r, i, vmask);
381             }
382         }
383         assertArraysEquals(r, a, mask);
384     }
385 
386     @Test(dataProvider = "doubleMaskProviderForIOOBE")
387     static void loadArrayMaskIOOBE(IntFunction<double[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
388         double[] a = fa.apply(SPECIES.length());
389         double[] r = new double[a.length];
390         boolean[] mask = fm.apply(SPECIES.length());
391         VectorMask<Double> vmask = VectorMask.fromValues(SPECIES, mask);
392 
393         for (int ic = 0; ic < INVOC_COUNT; ic++) {
394             for (int i = 0; i < a.length; i += SPECIES.length()) {
395                 DoubleVector av = fromArray(a, i, vmask);
396                 av.intoArray(r, i);
397             }
398         }
399 
400         int index = fi.apply(a.length);
401         boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length);
402         try {
403             fromArray(a, index, vmask);
404             if (shouldFail) {
405                 Assert.fail("Failed to throw IndexOutOfBoundsException");
406             }
407         } catch (IndexOutOfBoundsException e) {
408             if (!shouldFail) {
409                 Assert.fail("Unexpected IndexOutOfBoundsException");
410             }
411         }
412     }
413 
414     @Test(dataProvider = "doubleMaskProviderForIOOBE")
415     static void storeArrayMaskIOOBE(IntFunction<double[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
416         double[] a = fa.apply(SPECIES.length());
417         double[] r = new double[a.length];
418         boolean[] mask = fm.apply(SPECIES.length());
419         VectorMask<Double> vmask = VectorMask.fromValues(SPECIES, mask);
420 
421         for (int ic = 0; ic < INVOC_COUNT; ic++) {
422             for (int i = 0; i < a.length; i += SPECIES.length()) {
423                 DoubleVector av = DoubleVector.fromArray(SPECIES, a, i);
424                 intoArray(av, r, i, vmask);
425             }
426         }
427 
428         int index = fi.apply(a.length);
429         boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length);
430         try {
431             DoubleVector av = DoubleVector.fromArray(SPECIES, a, 0);
432             intoArray(av, a, index, vmask);
433             if (shouldFail) {
434                 Assert.fail("Failed to throw IndexOutOfBoundsException");
435             }
436         } catch (IndexOutOfBoundsException e) {
437             if (!shouldFail) {
438                 Assert.fail("Unexpected IndexOutOfBoundsException");
439             }
440         }
441     }
442 
443 
444     @Test(dataProvider = "doubleMaskProvider")
445     static void loadStoreMask(IntFunction<double[]> fa,
446                               IntFunction<boolean[]> fm) {
447         boolean[] mask = fm.apply(SPECIES.length());
448         boolean[] r = new boolean[mask.length];
449 
450         for (int ic = 0; ic < INVOC_COUNT; ic++) {
451             for (int i = 0; i < mask.length; i += SPECIES.length()) {
452                 VectorMask<Double> vmask = VectorMask.fromArray(SPECIES, mask, i);
453                 vmask.intoArray(r, i);
454             }
455         }
456         Assert.assertEquals(r, mask);
457     }
458 
459 
460     @Test(dataProvider = "doubleMemorySegmentProvider")
461     static void loadStoreMemorySegment(IntFunction<double[]> fa,
462                                        IntFunction<MemorySegment> fb,
463                                        ByteOrder bo) {
464         MemorySegment a = toSegment(fa.apply(SPECIES.length()), fb);
465         MemorySegment r = fb.apply((int) a.byteSize());
466 
467         int l = (int) a.byteSize();
468         int s = SPECIES.vectorByteSize();
469 
470         for (int ic = 0; ic < INVOC_COUNT; ic++) {
471             for (int i = 0; i < l; i += s) {
472                 DoubleVector av = DoubleVector.fromMemorySegment(SPECIES, a, i, bo);
473                 av.intoMemorySegment(r, i, bo);
474             }
475         }
476         long m = r.mismatch(a);
477         Assert.assertEquals(m, -1, "Segments not equal");
478     }
479 
480     @Test(dataProvider = "doubleByteProviderForIOOBE")
481     static void loadMemorySegmentIOOBE(IntFunction<double[]> fa, IntFunction<Integer> fi) {
482         MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Double.SIZE));
483         MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Double.SIZE);
484 
485         int l = (int) a.byteSize();
486         int s = SPECIES.vectorByteSize();
487 
488         for (int ic = 0; ic < INVOC_COUNT; ic++) {
489             for (int i = 0; i < l; i += s) {
490                 DoubleVector av = fromMemorySegment(a, i, ByteOrder.nativeOrder());
491                 av.intoMemorySegment(r, i, ByteOrder.nativeOrder());
492             }
493         }
494 
495         int index = fi.apply((int) a.byteSize());
496         boolean shouldFail = isIndexOutOfBounds(SPECIES.vectorByteSize(), index, (int) a.byteSize());
497         try {
498             fromMemorySegment(a, index, ByteOrder.nativeOrder());
499             if (shouldFail) {
500                 Assert.fail("Failed to throw IndexOutOfBoundsException");
501             }
502         } catch (IndexOutOfBoundsException e) {
503             if (!shouldFail) {
504                 Assert.fail("Unexpected IndexOutOfBoundsException");
505             }
506         }
507     }
508 
509     @Test(dataProvider = "doubleByteProviderForIOOBE")
510     static void storeMemorySegmentIOOBE(IntFunction<double[]> fa, IntFunction<Integer> fi) {
511         MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Double.SIZE));
512         MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Double.SIZE);
513 
514         int l = (int) a.byteSize();
515         int s = SPECIES.vectorByteSize();
516 
517         for (int ic = 0; ic < INVOC_COUNT; ic++) {
518             for (int i = 0; i < l; i += s) {
519                 DoubleVector av = DoubleVector.fromMemorySegment(SPECIES, a, i, ByteOrder.nativeOrder());
520                 intoMemorySegment(av, r, i, ByteOrder.nativeOrder());
521             }
522         }
523 
524         int index = fi.apply((int) a.byteSize());
525         boolean shouldFail = isIndexOutOfBounds(SPECIES.vectorByteSize(), index, (int) a.byteSize());
526         try {
527             DoubleVector av = DoubleVector.fromMemorySegment(SPECIES, a, 0, ByteOrder.nativeOrder());
528             intoMemorySegment(av, r, index, ByteOrder.nativeOrder());
529             if (shouldFail) {
530                 Assert.fail("Failed to throw IndexOutOfBoundsException");
531             }
532         } catch (IndexOutOfBoundsException e) {
533             if (!shouldFail) {
534                 Assert.fail("Unexpected IndexOutOfBoundsException");
535             }
536         }
537     }
538 
539     @Test(dataProvider = "doubleMemorySegmentMaskProvider")
540     static void loadStoreMemorySegmentMask(IntFunction<double[]> fa,
541                                            IntFunction<MemorySegment> fb,
542                                            IntFunction<boolean[]> fm,
543                                            ByteOrder bo) {
544         double[] _a = fa.apply(SPECIES.length());
545         MemorySegment a = toSegment(_a, fb);
546         MemorySegment r = fb.apply((int) a.byteSize());
547         boolean[] mask = fm.apply(SPECIES.length());
548         VectorMask<Double> vmask = VectorMask.fromValues(SPECIES, mask);
549 
550         int l = (int) a.byteSize();
551         int s = SPECIES.vectorByteSize();
552 
553         for (int ic = 0; ic < INVOC_COUNT; ic++) {
554             for (int i = 0; i < l; i += s) {
555                 DoubleVector av = DoubleVector.fromMemorySegment(SPECIES, a, i, bo, vmask);
556                 av.intoMemorySegment(r, i, bo);
557             }
558         }
559         assertArraysEquals(segmentToArray(r), _a, mask);
560 
561 
562         r = fb.apply((int) a.byteSize());
563 
564         for (int ic = 0; ic < INVOC_COUNT; ic++) {
565             for (int i = 0; i < l; i += s) {
566                 DoubleVector av = DoubleVector.fromMemorySegment(SPECIES, a, i, bo);
567                 av.intoMemorySegment(r, i, bo, vmask);
568             }
569         }
570         assertArraysEquals(segmentToArray(r), _a, mask);
571     }
572 
573     @Test(dataProvider = "doubleByteMaskProviderForIOOBE")
574     static void loadMemorySegmentMaskIOOBE(IntFunction<double[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
575         MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Double.SIZE));
576         MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Double.SIZE);
577         boolean[] mask = fm.apply(SPECIES.length());
578         VectorMask<Double> vmask = VectorMask.fromValues(SPECIES, mask);
579 
580         int l = (int) a.byteSize();
581         int s = SPECIES.vectorByteSize();
582 
583         for (int ic = 0; ic < INVOC_COUNT; ic++) {
584             for (int i = 0; i < l; i += s) {
585                 DoubleVector av = fromMemorySegment(a, i, ByteOrder.nativeOrder(), vmask);
586                 av.intoMemorySegment(r, i, ByteOrder.nativeOrder());
587             }
588         }
589 
590         int index = fi.apply((int) a.byteSize());
591         boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, (int) a.byteSize(), SPECIES.elementSize() / 8);
592         try {
593             fromMemorySegment(a, index, ByteOrder.nativeOrder(), vmask);
594             if (shouldFail) {
595                 Assert.fail("Failed to throw IndexOutOfBoundsException");
596             }
597         } catch (IndexOutOfBoundsException e) {
598             if (!shouldFail) {
599                 Assert.fail("Unexpected IndexOutOfBoundsException");
600             }
601         }
602     }
603 
604     @Test(dataProvider = "doubleByteMaskProviderForIOOBE")
605     static void storeMemorySegmentMaskIOOBE(IntFunction<double[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) {
606         MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> Arena.ofAuto().allocate(i, Double.SIZE));
607         MemorySegment r = Arena.ofAuto().allocate(a.byteSize(), Double.SIZE);
608         boolean[] mask = fm.apply(SPECIES.length());
609         VectorMask<Double> vmask = VectorMask.fromValues(SPECIES, mask);
610 
611         int l = (int) a.byteSize();
612         int s = SPECIES.vectorByteSize();
613 
614         for (int ic = 0; ic < INVOC_COUNT; ic++) {
615             for (int i = 0; i < l; i += s) {
616                 DoubleVector av = DoubleVector.fromMemorySegment(SPECIES, a, i, ByteOrder.nativeOrder());
617                 intoMemorySegment(av, r, i, ByteOrder.nativeOrder(), vmask);
618             }
619         }
620 
621         int index = fi.apply((int) a.byteSize());
622         boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, (int) a.byteSize(), SPECIES.elementSize() / 8);
623         try {
624             DoubleVector av = DoubleVector.fromMemorySegment(SPECIES, a, 0, ByteOrder.nativeOrder());
625             intoMemorySegment(av, a, index, ByteOrder.nativeOrder(), vmask);
626             if (shouldFail) {
627                 Assert.fail("Failed to throw IndexOutOfBoundsException");
628             }
629         } catch (IndexOutOfBoundsException e) {
630             if (!shouldFail) {
631                 Assert.fail("Unexpected IndexOutOfBoundsException");
632             }
633         }
634     }
635 
636     @Test(dataProvider = "doubleMemorySegmentProvider")
637     static void loadStoreReadonlyMemorySegment(IntFunction<double[]> fa,
638                                                IntFunction<MemorySegment> fb,
639                                                ByteOrder bo) {
640         MemorySegment a = toSegment(fa.apply(SPECIES.length()), fb).asReadOnly();
641 
642         Assert.assertThrows(
643                 UnsupportedOperationException.class,
644                 () -> SPECIES.zero().intoMemorySegment(a, 0, bo)
645         );
646 
647         Assert.assertThrows(
648                 UnsupportedOperationException.class,
649                 () -> SPECIES.zero().intoMemorySegment(a, 0, bo, SPECIES.maskAll(true))
650         );
651 
652         Assert.assertThrows(
653                 UnsupportedOperationException.class,
654                 () -> SPECIES.zero().intoMemorySegment(a, 0, bo, SPECIES.maskAll(false))
655         );
656 
657         VectorMask<Double> m = SPECIES.shuffleFromOp(i -> i % 2 == 0 ? 1 : -1)
658                 .laneIsValid();
659         Assert.assertThrows(
660                 UnsupportedOperationException.class,
661                 () -> SPECIES.zero().intoMemorySegment(a, 0, bo, m)
662         );
663     }
664 
665 
666     @Test(dataProvider = "maskProvider")
667     static void loadStoreMask(IntFunction<boolean[]> fm) {
668         boolean[] a = fm.apply(SPECIES.length());
669         boolean[] r = new boolean[a.length];
670 
671         for (int ic = 0; ic < INVOC_COUNT; ic++) {
672             for (int i = 0; i < a.length; i += SPECIES.length()) {
673                 VectorMask<Double> vmask = SPECIES.loadMask(a, i);
674                 vmask.intoArray(r, i);
675             }
676         }
677         Assert.assertEquals(r, a);
678     }
679 
680 
681     @Test
682     static void loadStoreShuffle() {
683         IntUnaryOperator fn = a -> a + 5;
684         for (int ic = 0; ic < INVOC_COUNT; ic++) {
685             var shuffle = VectorShuffle.fromOp(SPECIES, fn);
686             int [] r = shuffle.toArray();
687 
688             int [] a = expectedShuffle(SPECIES.length(), fn);
689             Assert.assertEquals(r, a);
690        }
691     }
692 
693 
694 
695 
696 
697     // Gather/Scatter load/store tests
698 
699     static void assertGatherArraysEquals(double[] r, double[] a, int[] indexMap) {
700         int i = 0;
701         int j = 0;
702         try {
703             for (; i < a.length; i += SPECIES.length()) {
704                 j = i;
705                 for (; j < i + SPECIES.length(); j++) {
706                     Assert.assertEquals(r[j], a[i + indexMap[j]]);
707                 }
708             }
709         } catch (AssertionError e) {
710             Assert.assertEquals(r[j], a[i + indexMap[j]], "at index #" + j);
711         }
712     }
713 
714     static void assertGatherArraysEquals(double[] r, double[] a, int[] indexMap, boolean[] mask) {
715         int i = 0;
716         int j = 0;
717         try {
718             for (; i < a.length; i += SPECIES.length()) {
719                 j = i;
720                 for (; j < i + SPECIES.length(); j++) {
721                     Assert.assertEquals(r[j], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (double) 0);
722                 }
723             }
724         } catch (AssertionError e) {
725             Assert.assertEquals(r[i], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (double) 0, "at index #" + j);
726         }
727     }
728 
729     static void assertScatterArraysEquals(double[] r, double[] a, int[] indexMap, boolean[] mask) {
730         double[] expected = new double[r.length];
731 
732         // Store before checking, since the same location may be stored to more than once
733         for (int i = 0; i < a.length; i += SPECIES.length()) {
734             for (int j = i; j < i + SPECIES.length(); j++) {
735                 if (mask[j % SPECIES.length()]) {
736                     expected[i + indexMap[j]] = a[j];
737                 }
738             }
739         }
740 
741         Assert.assertEquals(r, expected);
742     }
743 
744     static void assertScatterArraysEquals(double[] r, double[] a, int[] indexMap) {
745         double[] expected = new double[r.length];
746 
747         // Store before checking, since the same location may be stored to more than once
748         for (int i = 0; i < a.length; i += SPECIES.length()) {
749             for (int j = i; j < i + SPECIES.length(); j++) {
750                 expected[i + indexMap[j]] = a[j];
751             }
752         }
753 
754         Assert.assertEquals(r, expected);
755     }
756 
757     @DataProvider
758     public Object[][] gatherScatterProvider() {
759         return INT_INDEX_GENERATORS.stream().
760                 flatMap(fs -> DOUBLE_GENERATORS.stream().map(fa -> {
761                     return new Object[] {fa, fs};
762                 })).
763                 toArray(Object[][]::new);
764     }
765 
766     @DataProvider
767     public Object[][] gatherScatterMaskProvider() {
768         return BOOLEAN_MASK_GENERATORS.stream().
769           flatMap(fs -> INT_INDEX_GENERATORS.stream().flatMap(fm ->
770             DOUBLE_GENERATORS.stream().map(fa -> {
771                     return new Object[] {fa, fm, fs};
772             }))).
773             toArray(Object[][]::new);
774     }
775 
776 
777     @Test(dataProvider = "gatherScatterProvider")
778     static void gather(IntFunction<double[]> fa, BiFunction<Integer,Integer,int[]> fs) {
779         double[] a = fa.apply(SPECIES.length());
780         int[] b = fs.apply(a.length, SPECIES.length());
781         double[] r = new double[a.length];
782 
783         for (int ic = 0; ic < INVOC_COUNT; ic++) {
784             for (int i = 0; i < a.length; i += SPECIES.length()) {
785                 DoubleVector av = DoubleVector.fromArray(SPECIES, a, i, b, i);
786                 av.intoArray(r, i);
787             }
788         }
789 
790         assertGatherArraysEquals(r, a, b);
791     }
792 
793     @Test(dataProvider = "gatherScatterMaskProvider")
794     static void gatherMask(IntFunction<double[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
795         double[] a = fa.apply(SPECIES.length());
796         int[] b = fs.apply(a.length, SPECIES.length());
797         double[] r = new double[a.length];
798         boolean[] mask = fm.apply(SPECIES.length());
799         VectorMask<Double> vmask = VectorMask.fromArray(SPECIES, mask, 0);
800 
801         for (int ic = 0; ic < INVOC_COUNT; ic++) {
802             for (int i = 0; i < a.length; i += SPECIES.length()) {
803                 DoubleVector av = DoubleVector.fromArray(SPECIES, a, i, b, i, vmask);
804                 av.intoArray(r, i);
805             }
806         }
807 
808         assertGatherArraysEquals(r, a, b, mask);
809     }
810 
811     @Test(dataProvider = "gatherScatterProvider")
812     static void scatter(IntFunction<double[]> fa, BiFunction<Integer,Integer,int[]> fs) {
813         double[] a = fa.apply(SPECIES.length());
814         int[] b = fs.apply(a.length, SPECIES.length());
815         double[] r = new double[a.length];
816 
817         for (int ic = 0; ic < INVOC_COUNT; ic++) {
818             for (int i = 0; i < a.length; i += SPECIES.length()) {
819                 DoubleVector av = DoubleVector.fromArray(SPECIES, a, i);
820                 av.intoArray(r, i, b, i);
821             }
822         }
823 
824         assertScatterArraysEquals(r, a, b);
825     }
826 
827     @Test(dataProvider = "gatherScatterMaskProvider")
828     static void scatterMask(IntFunction<double[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
829         double[] a = fa.apply(SPECIES.length());
830         int[] b = fs.apply(a.length, SPECIES.length());
831         double[] r = new double[a.length];
832         boolean[] mask = fm.apply(SPECIES.length());
833         VectorMask<Double> vmask = VectorMask.fromArray(SPECIES, mask, 0);
834 
835         for (int ic = 0; ic < INVOC_COUNT; ic++) {
836             for (int i = 0; i < a.length; i += SPECIES.length()) {
837                 DoubleVector av = DoubleVector.fromArray(SPECIES, a, i);
838                 av.intoArray(r, i, b, i, vmask);
839             }
840         }
841 
842         assertScatterArraysEquals(r, a, b, mask);
843     }
844 
845 
846 
847 }