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