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