1 /*
   2  * Copyright (c) 2018, 2020, 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
  27  * @run testng/othervm -ea -esa -Xbatch $vectorteststype$
  28  */
  29 
  30 #warn This file is preprocessed before being compiled
  31 
  32 import jdk.incubator.vector.VectorShape;
  33 import jdk.incubator.vector.VectorSpecies;
  34 import jdk.incubator.vector.VectorShuffle;
  35 import jdk.incubator.vector.VectorMask;
  36 import jdk.incubator.vector.VectorOperators;
  37 import jdk.incubator.vector.Vector;
  38 
  39 #if[Byte]
  40 import jdk.incubator.vector.ByteVector;
  41 #end[Byte]
  42 #if[Float]
  43 import jdk.incubator.vector.FloatVector;
  44 #end[Float]
  45 #if[Int]
  46 import jdk.incubator.vector.IntVector;
  47 #end[Int]
  48 #if[Double]
  49 import jdk.incubator.vector.DoubleVector;
  50 #end[Double]
  51 #if[Short]
  52 import jdk.incubator.vector.ShortVector;
  53 #end[Short]
  54 #if[Long]
  55 import jdk.incubator.vector.LongVector;
  56 #end[Long]
  57 
  58 import org.testng.Assert;
  59 import org.testng.annotations.DataProvider;
  60 import org.testng.annotations.Test;
  61 
  62 import java.lang.Integer;
  63 import java.util.List;
  64 import java.util.Arrays;
  65 import java.util.function.BiFunction;
  66 import java.util.function.IntFunction;
  67 import java.util.stream.Collectors;
  68 import java.util.stream.Stream;
  69 
  70 @Test
  71 public class $vectorteststype$ extends AbstractVectorTest {
  72 
  73 #if[MaxBit]
  74     static final VectorSpecies<$Wideboxtype$> SPECIES =
  75                 $Type$Vector.SPECIES_MAX;
  76 #else[MaxBit]
  77     static final VectorSpecies<$Wideboxtype$> SPECIES =
  78                 $Type$Vector.SPECIES_$bits$;
  79 #end[MaxBit]
  80 
  81     static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 100);
  82 
  83 #if[MaxBit]
  84     static VectorShape getMaxBit() {
  85         return VectorShape.S_Max_BIT;
  86     }
  87 
  88     private static final int Max = 256;  // juts so we can do N/$bits$
  89 #end[MaxBit]
  90 
  91     static final int BUFFER_REPS = Integer.getInteger("jdk.incubator.vector.test.buffer-vectors", 25000 / $bits$);
  92 
  93     static final int BUFFER_SIZE = Integer.getInteger("jdk.incubator.vector.test.buffer-size", BUFFER_REPS * ($bits$ / 8));
  94 
  95     interface FUnOp {
  96         $type$ apply($type$ a);
  97     }
  98 
  99     static void assertArraysEquals($type$[] a, $type$[] r, FUnOp f) {
 100         int i = 0;
 101         try {
 102             for (; i < a.length; i++) {
 103                 Assert.assertEquals(r[i], f.apply(a[i]));
 104             }
 105         } catch (AssertionError e) {
 106             Assert.assertEquals(r[i], f.apply(a[i]), "at index #" + i + ", input = " + a[i]);
 107         }
 108     }
 109 
 110     interface FUnArrayOp {
 111         $type$[] apply($type$ a);
 112     }
 113 
 114     static void assertArraysEquals($type$[] a, $type$[] r, FUnArrayOp f) {
 115         int i = 0;
 116         try {
 117             for (; i < a.length; i += SPECIES.length()) {
 118                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
 119                   f.apply(a[i]));
 120             }
 121         } catch (AssertionError e) {
 122             $type$[] ref = f.apply(a[i]);
 123             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
 124             Assert.assertEquals(ref, res, "(ref: " + Arrays.toString(ref)
 125               + ", res: " + Arrays.toString(res)
 126               + "), at index #" + i);
 127         }
 128     }
 129 
 130     static void assertArraysEquals($type$[] a, $type$[] r, boolean[] mask, FUnOp f) {
 131         int i = 0;
 132         try {
 133             for (; i < a.length; i++) {
 134                 Assert.assertEquals(r[i], mask[i % SPECIES.length()] ? f.apply(a[i]) : a[i]);
 135             }
 136         } catch (AssertionError e) {
 137             Assert.assertEquals(r[i], mask[i % SPECIES.length()] ? f.apply(a[i]) : a[i], "at index #" + i + ", input = " + a[i] + ", mask = " + mask[i % SPECIES.length()]);
 138         }
 139     }
 140 
 141     interface FReductionOp {
 142         $type$ apply($type$[] a, int idx);
 143     }
 144 
 145     interface FReductionAllOp {
 146         $type$ apply($type$[] a);
 147     }
 148 
 149     static void assertReductionArraysEquals($type$[] a, $type$[] b, $type$ c,
 150                                             FReductionOp f, FReductionAllOp fa) {
 151         int i = 0;
 152         try {
 153             Assert.assertEquals(c, fa.apply(a));
 154             for (; i < a.length; i += SPECIES.length()) {
 155                 Assert.assertEquals(b[i], f.apply(a, i));
 156             }
 157         } catch (AssertionError e) {
 158             Assert.assertEquals(c, fa.apply(a), "Final result is incorrect!");
 159             Assert.assertEquals(b[i], f.apply(a, i), "at index #" + i);
 160         }
 161     }
 162 
 163     interface FReductionMaskedOp {
 164         $type$ apply($type$[] a, int idx, boolean[] mask);
 165     }
 166 
 167     interface FReductionAllMaskedOp {
 168         $type$ apply($type$[] a, boolean[] mask);
 169     }
 170 
 171     static void assertReductionArraysEqualsMasked($type$[] a, $type$[] b, $type$ c, boolean[] mask,
 172                                             FReductionMaskedOp f, FReductionAllMaskedOp fa) {
 173         int i = 0;
 174         try {
 175             Assert.assertEquals(c, fa.apply(a, mask));
 176             for (; i < a.length; i += SPECIES.length()) {
 177                 Assert.assertEquals(b[i], f.apply(a, i, mask));
 178             }
 179         } catch (AssertionError e) {
 180             Assert.assertEquals(c, fa.apply(a, mask), "Final result is incorrect!");
 181             Assert.assertEquals(b[i], f.apply(a, i, mask), "at index #" + i);
 182         }
 183     }
 184 
 185     interface FBoolReductionOp {
 186         boolean apply(boolean[] a, int idx);
 187     }
 188 
 189     static void assertReductionBoolArraysEquals(boolean[] a, boolean[] b, FBoolReductionOp f) {
 190         int i = 0;
 191         try {
 192             for (; i < a.length; i += SPECIES.length()) {
 193                 Assert.assertEquals(b[i], f.apply(a, i));
 194             }
 195         } catch (AssertionError e) {
 196             Assert.assertEquals(b[i], f.apply(a, i), "at index #" + i);
 197         }
 198     }
 199 
 200     static void assertInsertArraysEquals($type$[] a, $type$[] b, $type$ element, int index) {
 201         int i = 0;
 202         try {
 203             for (; i < a.length; i += 1) {
 204                 if(i%SPECIES.length() == index) {
 205                     Assert.assertEquals(b[i], element);
 206                 } else {
 207                     Assert.assertEquals(b[i], a[i]);
 208                 }
 209             }
 210         } catch (AssertionError e) {
 211             if (i%SPECIES.length() == index) {
 212                 Assert.assertEquals(b[i], element, "at index #" + i);
 213             } else {
 214                 Assert.assertEquals(b[i], a[i], "at index #" + i);
 215             }
 216         }
 217     }
 218 
 219     static void assertRearrangeArraysEquals($type$[] a, $type$[] r, int[] order, int vector_len) {
 220         int i = 0, j = 0;
 221         try {
 222             for (; i < a.length; i += vector_len) {
 223                 for (j = 0; j < vector_len; j++) {
 224                     Assert.assertEquals(r[i+j], a[i+order[i+j]]);
 225                 }
 226             }
 227         } catch (AssertionError e) {
 228             int idx = i + j;
 229             Assert.assertEquals(r[i+j], a[i+order[i+j]], "at index #" + idx + ", input = " + a[i+order[i+j]]);
 230         }
 231     }
 232 
 233     static void assertBroadcastArraysEquals($type$[]a, $type$[]r) {
 234         int i = 0;
 235         for (; i < a.length; i += SPECIES.length()) {
 236             int idx = i;
 237             for (int j = idx; j < (idx + SPECIES.length()); j++)
 238                 a[j]=a[idx];
 239         }
 240 
 241         try {
 242             for (i = 0; i < a.length; i++) {
 243                 Assert.assertEquals(r[i], a[i]);
 244             }
 245         } catch (AssertionError e) {
 246             Assert.assertEquals(r[i], a[i], "at index #" + i + ", input = " + a[i]);
 247         }
 248     }
 249 
 250     interface FBinOp {
 251         $type$ apply($type$ a, $type$ b);
 252     }
 253 
 254     interface FBinMaskOp {
 255         $type$ apply($type$ a, $type$ b, boolean m);
 256 
 257         static FBinMaskOp lift(FBinOp f) {
 258             return (a, b, m) -> m ? f.apply(a, b) : a;
 259         }
 260     }
 261 
 262     static void assertArraysEquals($type$[] a, $type$[] b, $type$[] r, FBinOp f) {
 263         int i = 0;
 264         try {
 265             for (; i < a.length; i++) {
 266                 Assert.assertEquals(r[i], f.apply(a[i], b[i]));
 267             }
 268         } catch (AssertionError e) {
 269             Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i);
 270         }
 271     }
 272 
 273     static void assertBroadcastArraysEquals($type$[] a, $type$[] b, $type$[] r, FBinOp f) {
 274         int i = 0;
 275         try {
 276             for (; i < a.length; i++) {
 277                 Assert.assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]));
 278             }
 279         } catch (AssertionError e) {
 280             Assert.assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]),
 281                                 "(" + a[i] + ", " + b[(i / SPECIES.length()) * SPECIES.length()] + ") at index #" + i);
 282         }
 283     }
 284 
 285     static void assertArraysEquals($type$[] a, $type$[] b, $type$[] r, boolean[] mask, FBinOp f) {
 286         assertArraysEquals(a, b, r, mask, FBinMaskOp.lift(f));
 287     }
 288 
 289     static void assertArraysEquals($type$[] a, $type$[] b, $type$[] r, boolean[] mask, FBinMaskOp f) {
 290         int i = 0;
 291         try {
 292             for (; i < a.length; i++) {
 293                 Assert.assertEquals(r[i], f.apply(a[i], b[i], mask[i % SPECIES.length()]));
 294             }
 295         } catch (AssertionError err) {
 296             Assert.assertEquals(r[i], f.apply(a[i], b[i], mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", mask = " + mask[i % SPECIES.length()]);
 297         }
 298     }
 299 
 300     static void assertBroadcastArraysEquals($type$[] a, $type$[] b, $type$[] r, boolean[] mask, FBinOp f) {
 301         assertBroadcastArraysEquals(a, b, r, mask, FBinMaskOp.lift(f));
 302     }
 303 
 304     static void assertBroadcastArraysEquals($type$[] a, $type$[] b, $type$[] r, boolean[] mask, FBinMaskOp f) {
 305         int i = 0;
 306         try {
 307             for (; i < a.length; i++) {
 308                 Assert.assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], mask[i % SPECIES.length()]));
 309             }
 310         } catch (AssertionError err) {
 311             Assert.assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], 
 312                                 mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + 
 313                                 ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " +
 314                                 mask[i % SPECIES.length()]);
 315         }
 316     }
 317 
 318     static void assertShiftArraysEquals($type$[] a, $type$[] b, $type$[] r, FBinOp f) {
 319         int i = 0;
 320         int j = 0;
 321         try {
 322             for (; j < a.length; j += SPECIES.length()) {
 323                 for (i = 0; i < SPECIES.length(); i++) {
 324                     Assert.assertEquals(r[i+j], f.apply(a[i+j], b[j]));
 325                 }
 326             }
 327         } catch (AssertionError e) {
 328             Assert.assertEquals(r[i+j], f.apply(a[i+j], b[j]), "at index #" + i + ", " + j);
 329         }
 330     }
 331 
 332     static void assertShiftArraysEquals($type$[] a, $type$[] b, $type$[] r, boolean[] mask, FBinOp f) {
 333         assertShiftArraysEquals(a, b, r, mask, FBinMaskOp.lift(f));
 334     }
 335 
 336     static void assertShiftArraysEquals($type$[] a, $type$[] b, $type$[] r, boolean[] mask, FBinMaskOp f) {
 337         int i = 0;
 338         int j = 0;
 339         try {
 340             for (; j < a.length; j += SPECIES.length()) {
 341                 for (i = 0; i < SPECIES.length(); i++) {
 342                     Assert.assertEquals(r[i+j], f.apply(a[i+j], b[j], mask[i]));
 343                 }
 344             }
 345         } catch (AssertionError err) {
 346             Assert.assertEquals(r[i+j], f.apply(a[i+j], b[j], mask[i]), "at index #" + i + ", input1 = " + a[i+j] + ", input2 = " + b[j] + ", mask = " + mask[i]);
 347         }
 348     }
 349 
 350     interface FTernOp {
 351         $type$ apply($type$ a, $type$ b, $type$ c);
 352     }
 353 
 354     interface FTernMaskOp {
 355         $type$ apply($type$ a, $type$ b, $type$ c, boolean m);
 356 
 357         static FTernMaskOp lift(FTernOp f) {
 358             return (a, b, c, m) -> m ? f.apply(a, b, c) : a;
 359         }
 360     }
 361 
 362     static void assertArraysEquals($type$[] a, $type$[] b, $type$[] c, $type$[] r, FTernOp f) {
 363         int i = 0;
 364         try {
 365             for (; i < a.length; i++) {
 366                 Assert.assertEquals(r[i], f.apply(a[i], b[i], c[i]));
 367             }
 368         } catch (AssertionError e) {
 369             Assert.assertEquals(r[i], f.apply(a[i], b[i], c[i]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]);
 370         }
 371     }
 372 
 373     static void assertArraysEquals($type$[] a, $type$[] b, $type$[] c, $type$[] r, boolean[] mask, FTernOp f) {
 374         assertArraysEquals(a, b, c, r, mask, FTernMaskOp.lift(f));
 375     }
 376 
 377     static void assertArraysEquals($type$[] a, $type$[] b, $type$[] c, $type$[] r, boolean[] mask, FTernMaskOp f) {
 378         int i = 0;
 379         try {
 380             for (; i < a.length; i++) {
 381                 Assert.assertEquals(r[i], f.apply(a[i], b[i], c[i], mask[i % SPECIES.length()]));
 382             }
 383         } catch (AssertionError err) {
 384             Assert.assertEquals(r[i], f.apply(a[i], b[i], c[i], mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = "
 385               + b[i] + ", input3 = " + c[i] + ", mask = " + mask[i % SPECIES.length()]);
 386         }
 387     }
 388 
 389 #if[FP]
 390     static boolean isWithin1Ulp($type$ actual, $type$ expected) {
 391         if ($Type$.isNaN(expected) && !$Type$.isNaN(actual)) {
 392             return false;
 393         } else if (!$Type$.isNaN(expected) && $Type$.isNaN(actual)) {
 394             return false;
 395         }
 396 
 397         $type$ low = Math.nextDown(expected);
 398         $type$ high = Math.nextUp(expected);
 399 
 400         if ($Type$.compare(low, expected) > 0) {
 401             return false;
 402         }
 403 
 404         if ($Type$.compare(high, expected) < 0) {
 405             return false;
 406         }
 407 
 408         return true;
 409     }
 410 
 411     static void assertArraysEqualsWithinOneUlp($type$[] a, $type$[] r, FUnOp mathf, FUnOp strictmathf) {
 412         int i = 0;
 413         try {
 414             // Check that result is within 1 ulp of strict math or equivalent to math implementation.
 415             for (; i < a.length; i++) {
 416                 Assert.assertTrue($Type$.compare(r[i], mathf.apply(a[i])) == 0 ||
 417                                     isWithin1Ulp(r[i], strictmathf.apply(a[i])));
 418             }
 419         } catch (AssertionError e) {
 420             Assert.assertTrue($Type$.compare(r[i], mathf.apply(a[i])) == 0, "at index #" + i + ", input = " + a[i] + ", actual = " + r[i] + ", expected = " + mathf.apply(a[i]));
 421             Assert.assertTrue(isWithin1Ulp(r[i], strictmathf.apply(a[i])), "at index #" + i + ", input = " + a[i] + ", actual = " + r[i] + ", expected (within 1 ulp) = " + strictmathf.apply(a[i]));
 422         }
 423     }
 424 
 425     static void assertArraysEqualsWithinOneUlp($type$[] a, $type$[] b, $type$[] r, FBinOp mathf, FBinOp strictmathf) {
 426         int i = 0;
 427         try {
 428             // Check that result is within 1 ulp of strict math or equivalent to math implementation.
 429             for (; i < a.length; i++) {
 430                 Assert.assertTrue($Type$.compare(r[i], mathf.apply(a[i], b[i])) == 0 ||
 431                                     isWithin1Ulp(r[i], strictmathf.apply(a[i], b[i])));
 432             }
 433         } catch (AssertionError e) {
 434             Assert.assertTrue($Type$.compare(r[i], mathf.apply(a[i], b[i])) == 0, "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", actual = " + r[i] + ", expected = " + mathf.apply(a[i], b[i]));
 435             Assert.assertTrue(isWithin1Ulp(r[i], strictmathf.apply(a[i], b[i])), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", actual = " + r[i] + ", expected (within 1 ulp) = " + strictmathf.apply(a[i], b[i]));
 436         }
 437     }
 438 #end[FP]
 439 
 440     interface FBinArrayOp {
 441         $type$ apply($type$[] a, int b);
 442     }
 443 
 444     static void assertArraysEquals($type$[] a, $type$[] r, FBinArrayOp f) {
 445         int i = 0;
 446         try {
 447             for (; i < a.length; i++) {
 448                 Assert.assertEquals(r[i], f.apply(a, i));
 449             }
 450         } catch (AssertionError e) {
 451             Assert.assertEquals(r[i], f.apply(a,i), "at index #" + i);
 452         }
 453     }
 454 
 455     interface FGatherScatterOp {
 456         $type$[] apply($type$[] a, int ix, int[] b, int iy);
 457     }
 458 
 459     static void assertArraysEquals($type$[] a, int[] b, $type$[] r, FGatherScatterOp f) {
 460         int i = 0;
 461         try {
 462             for (; i < a.length; i += SPECIES.length()) {
 463                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
 464                   f.apply(a, i, b, i));
 465             }
 466         } catch (AssertionError e) {
 467             $type$[] ref = f.apply(a, i, b, i);
 468             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
 469             Assert.assertEquals(res, ref,
 470               "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: "
 471               + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length()))
 472               + ", b: "
 473               + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length()))
 474               + " at index #" + i);
 475         }
 476     }
 477 
 478     interface FGatherMaskedOp {
 479         $type$[] apply($type$[] a, int ix, boolean[] mask, int[] b, int iy);
 480     }
 481 
 482     interface FScatterMaskedOp {
 483         $type$[] apply($type$[] r, $type$[] a, int ix, boolean[] mask, int[] b, int iy);
 484     }
 485 
 486     static void assertArraysEquals($type$[] a, int[] b, $type$[] r, boolean[] mask, FGatherMaskedOp f) {
 487         int i = 0;
 488         try {
 489             for (; i < a.length; i += SPECIES.length()) {
 490                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
 491                   f.apply(a, i, mask, b, i));
 492             }
 493         } catch (AssertionError e) {
 494             $type$[] ref = f.apply(a, i, mask, b, i);
 495             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
 496             Assert.assertEquals(ref, res,
 497               "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: "
 498               + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length()))
 499               + ", b: "
 500               + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length()))
 501               + ", mask: "
 502               + Arrays.toString(mask)
 503               + " at index #" + i);
 504         }
 505     }
 506 
 507     static void assertArraysEquals($type$[] a, int[] b, $type$[] r, boolean[] mask, FScatterMaskedOp f) {
 508         int i = 0;
 509         try {
 510             for (; i < a.length; i += SPECIES.length()) {
 511                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
 512                   f.apply(r, a, i, mask, b, i));
 513             }
 514         } catch (AssertionError e) {
 515             $type$[] ref = f.apply(r, a, i, mask, b, i);
 516             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
 517             Assert.assertEquals(ref, res,
 518               "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: "
 519               + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length()))
 520               + ", b: "
 521               + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length()))
 522               + ", r: "
 523               + Arrays.toString(Arrays.copyOfRange(r, i, i+SPECIES.length()))
 524               + ", mask: "
 525               + Arrays.toString(mask)
 526               + " at index #" + i);
 527         }
 528     }
 529 
 530     interface FLaneOp {
 531         $type$[] apply($type$[] a, int origin, int idx);
 532     }
 533 
 534     static void assertArraysEquals($type$[] a, $type$[] r, int origin, FLaneOp f) {
 535         int i = 0;
 536         try {
 537             for (; i < a.length; i += SPECIES.length()) {
 538                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
 539                   f.apply(a, origin, i));
 540             }
 541         } catch (AssertionError e) {
 542             $type$[] ref = f.apply(a, origin, i);
 543             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
 544             Assert.assertEquals(ref, res, "(ref: " + Arrays.toString(ref)
 545               + ", res: " + Arrays.toString(res)
 546               + "), at index #" + i);
 547         }
 548     }
 549 
 550     interface FLaneBop {
 551         $type$[] apply($type$[] a, $type$[] b, int origin, int idx);
 552     }
 553 
 554     static void assertArraysEquals($type$[] a, $type$[] b, $type$[] r, int origin, FLaneBop f) {
 555         int i = 0;
 556         try {
 557             for (; i < a.length; i += SPECIES.length()) {
 558                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
 559                   f.apply(a, b, origin, i));
 560             }
 561         } catch (AssertionError e) {
 562             $type$[] ref = f.apply(a, b, origin, i);
 563             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
 564             Assert.assertEquals(ref, res, "(ref: " + Arrays.toString(ref)
 565               + ", res: " + Arrays.toString(res)
 566               + "), at index #" + i
 567               + ", at origin #" + origin);
 568         }
 569     }
 570 
 571     interface FLaneMaskedBop {
 572         $type$[] apply($type$[] a, $type$[] b, int origin, boolean[] mask, int idx);
 573     }
 574 
 575     static void assertArraysEquals($type$[] a, $type$[] b, $type$[] r, int origin, boolean[] mask, FLaneMaskedBop f) {
 576         int i = 0;
 577         try {
 578             for (; i < a.length; i += SPECIES.length()) {
 579                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
 580                   f.apply(a, b, origin, mask, i));
 581             }
 582         } catch (AssertionError e) {
 583             $type$[] ref = f.apply(a, b, origin, mask, i);
 584             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
 585             Assert.assertEquals(ref, res, "(ref: " + Arrays.toString(ref)
 586               + ", res: " + Arrays.toString(res)
 587               + "), at index #" + i
 588               + ", at origin #" + origin);
 589         }
 590     }
 591 
 592     interface FLanePartBop {
 593         $type$[] apply($type$[] a, $type$[] b, int origin, int part, int idx);
 594     }
 595 
 596     static void assertArraysEquals($type$[] a, $type$[] b, $type$[] r, int origin, int part, FLanePartBop f) {
 597         int i = 0;
 598         try {
 599             for (; i < a.length; i += SPECIES.length()) {
 600                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
 601                   f.apply(a, b, origin, part, i));
 602             }
 603         } catch (AssertionError e) {
 604             $type$[] ref = f.apply(a, b, origin, part, i);
 605             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
 606             Assert.assertEquals(ref, res, "(ref: " + Arrays.toString(ref)
 607               + ", res: " + Arrays.toString(res)
 608               + "), at index #" + i
 609               + ", at origin #" + origin
 610               + ", with part #" + part);
 611         }
 612     }
 613 
 614     interface FLanePartMaskedBop {
 615         $type$[] apply($type$[] a, $type$[] b, int origin, int part, boolean[] mask, int idx);
 616     }
 617 
 618     static void assertArraysEquals($type$[] a, $type$[] b, $type$[] r, int origin, int part, boolean[] mask, FLanePartMaskedBop f) {
 619         int i = 0;
 620         try {
 621             for (; i < a.length; i += SPECIES.length()) {
 622                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
 623                   f.apply(a, b, origin, part, mask, i));
 624             }
 625         } catch (AssertionError e) {
 626             $type$[] ref = f.apply(a, b, origin, part, mask, i);
 627             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
 628             Assert.assertEquals(ref, res, "(ref: " + Arrays.toString(ref)
 629               + ", res: " + Arrays.toString(res)
 630               + "), at index #" + i
 631               + ", at origin #" + origin
 632               + ", with part #" + part);
 633         }
 634     }
 635 
 636     static $bitstype$ bits($type$ e) {
 637         return {#if[FP]? $Type$.$type$To$Bitstype$Bits(e): e};
 638     }
 639 
 640     static final List<IntFunction<$type$[]>> $TYPE$_GENERATORS = List.of(
 641             withToString("$type$[-i * 5]", (int s) -> {
 642                 return fill(s * BUFFER_REPS,
 643                             i -> ($type$)(-i * 5));
 644             }),
 645             withToString("$type$[i * 5]", (int s) -> {
 646                 return fill(s * BUFFER_REPS,
 647                             i -> ($type$)(i * 5));
 648             }),
 649             withToString("$type$[i + 1]", (int s) -> {
 650                 return fill(s * BUFFER_REPS,
 651                             i -> ((($type$)(i + 1) == 0) ? 1 : ($type$)(i + 1)));
 652             }),
 653             withToString("$type$[cornerCaseValue(i)]", (int s) -> {
 654                 return fill(s * BUFFER_REPS,
 655                             i -> cornerCaseValue(i));
 656             })
 657     );
 658 
 659     // Create combinations of pairs
 660     // @@@ Might be sensitive to order e.g. div by 0
 661     static final List<List<IntFunction<$type$[]>>> $TYPE$_GENERATOR_PAIRS =
 662         Stream.of($TYPE$_GENERATORS.get(0)).
 663                 flatMap(fa -> $TYPE$_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))).
 664                 collect(Collectors.toList());
 665 
 666     @DataProvider
 667     public Object[][] boolUnaryOpProvider() {
 668         return BOOL_ARRAY_GENERATORS.stream().
 669                 map(f -> new Object[]{f}).
 670                 toArray(Object[][]::new);
 671     }
 672 
 673     static final List<List<IntFunction<$type$[]>>> $TYPE$_GENERATOR_TRIPLES =
 674         $TYPE$_GENERATOR_PAIRS.stream().
 675                 flatMap(pair -> $TYPE$_GENERATORS.stream().map(f -> List.of(pair.get(0), pair.get(1), f))).
 676                 collect(Collectors.toList());
 677 
 678     @DataProvider
 679     public Object[][] $type$BinaryOpProvider() {
 680         return $TYPE$_GENERATOR_PAIRS.stream().map(List::toArray).
 681                 toArray(Object[][]::new);
 682     }
 683 
 684     @DataProvider
 685     public Object[][] $type$IndexedOpProvider() {
 686         return $TYPE$_GENERATOR_PAIRS.stream().map(List::toArray).
 687                 toArray(Object[][]::new);
 688     }
 689 
 690     @DataProvider
 691     public Object[][] $type$BinaryOpMaskProvider() {
 692         return BOOLEAN_MASK_GENERATORS.stream().
 693                 flatMap(fm -> $TYPE$_GENERATOR_PAIRS.stream().map(lfa -> {
 694                     return Stream.concat(lfa.stream(), Stream.of(fm)).toArray();
 695                 })).
 696                 toArray(Object[][]::new);
 697     }
 698 
 699     @DataProvider
 700     public Object[][] $type$TernaryOpProvider() {
 701         return $TYPE$_GENERATOR_TRIPLES.stream().map(List::toArray).
 702                 toArray(Object[][]::new);
 703     }
 704 
 705     @DataProvider
 706     public Object[][] $type$TernaryOpMaskProvider() {
 707         return BOOLEAN_MASK_GENERATORS.stream().
 708                 flatMap(fm -> $TYPE$_GENERATOR_TRIPLES.stream().map(lfa -> {
 709                     return Stream.concat(lfa.stream(), Stream.of(fm)).toArray();
 710                 })).
 711                 toArray(Object[][]::new);
 712     }
 713 
 714     @DataProvider
 715     public Object[][] $type$UnaryOpProvider() {
 716         return $TYPE$_GENERATORS.stream().
 717                 map(f -> new Object[]{f}).
 718                 toArray(Object[][]::new);
 719     }
 720 
 721     @DataProvider
 722     public Object[][] $type$UnaryOpMaskProvider() {
 723         return BOOLEAN_MASK_GENERATORS.stream().
 724                 flatMap(fm -> $TYPE$_GENERATORS.stream().map(fa -> {
 725                     return new Object[] {fa, fm};
 726                 })).
 727                 toArray(Object[][]::new);
 728     }
 729 
 730     @DataProvider
 731     public Object[][] $type$UnaryOpShuffleProvider() {
 732         return INT_SHUFFLE_GENERATORS.stream().
 733                 flatMap(fs -> $TYPE$_GENERATORS.stream().map(fa -> {
 734                     return new Object[] {fa, fs};
 735                 })).
 736                 toArray(Object[][]::new);
 737     }
 738 
 739     @DataProvider
 740     public Object[][] $type$UnaryOpIndexProvider() {
 741         return INT_INDEX_GENERATORS.stream().
 742                 flatMap(fs -> $TYPE$_GENERATORS.stream().map(fa -> {
 743                     return new Object[] {fa, fs};
 744                 })).
 745                 toArray(Object[][]::new);
 746     }
 747 
 748     @DataProvider
 749     public Object[][] $type$UnaryMaskedOpIndexProvider() {
 750         return BOOLEAN_MASK_GENERATORS.stream().
 751           flatMap(fs -> INT_INDEX_GENERATORS.stream().flatMap(fm ->
 752             $TYPE$_GENERATORS.stream().map(fa -> {
 753                     return new Object[] {fa, fm, fs};
 754             }))).
 755             toArray(Object[][]::new);
 756     }
 757 
 758     @DataProvider
 759     public Object[][] scatterMaskedOpIndexProvider() {
 760         return BOOLEAN_MASK_GENERATORS.stream().
 761           flatMap(fs -> INT_INDEX_GENERATORS.stream().flatMap(fm ->
 762             $TYPE$_GENERATORS.stream().flatMap(fn ->
 763               $TYPE$_GENERATORS.stream().map(fa -> {
 764                     return new Object[] {fa, fn, fm, fs};
 765             })))).
 766             toArray(Object[][]::new);
 767     }
 768 
 769     static final List<IntFunction<$type$[]>> $TYPE$_COMPARE_GENERATORS = List.of(
 770             withToString("$type$[i]", (int s) -> {
 771                 return fill(s * BUFFER_REPS,
 772                             i -> ($type$)i);
 773             }),
 774             withToString("$type$[i + 1]", (int s) -> {
 775                 return fill(s * BUFFER_REPS,
 776                             i -> ($type$)(i + 1));
 777             }),
 778             withToString("$type$[i - 2]", (int s) -> {
 779                 return fill(s * BUFFER_REPS,
 780                             i -> ($type$)(i - 2));
 781             }),
 782             withToString("$type$[zigZag(i)]", (int s) -> {
 783                 return fill(s * BUFFER_REPS,
 784                             i -> i%3 == 0 ? ($type$)i : (i%3 == 1 ? ($type$)(i + 1) : ($type$)(i - 2)));
 785             }),
 786             withToString("$type$[cornerCaseValue(i)]", (int s) -> {
 787                 return fill(s * BUFFER_REPS,
 788                             i -> cornerCaseValue(i));
 789             })
 790     );
 791 
 792     static final List<List<IntFunction<$type$[]>>> $TYPE$_TEST_GENERATOR_ARGS =
 793         $TYPE$_COMPARE_GENERATORS.stream().
 794                 map(fa -> List.of(fa)).
 795                 collect(Collectors.toList());
 796 
 797     @DataProvider
 798     public Object[][] $type$TestOpProvider() {
 799         return $TYPE$_TEST_GENERATOR_ARGS.stream().map(List::toArray).
 800                 toArray(Object[][]::new);
 801     }
 802 
 803     static final List<List<IntFunction<$type$[]>>> $TYPE$_COMPARE_GENERATOR_PAIRS =
 804         $TYPE$_COMPARE_GENERATORS.stream().
 805                 flatMap(fa -> $TYPE$_COMPARE_GENERATORS.stream().map(fb -> List.of(fa, fb))).
 806                 collect(Collectors.toList());
 807 
 808     @DataProvider
 809     public Object[][] $type$CompareOpProvider() {
 810         return $TYPE$_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray).
 811                 toArray(Object[][]::new);
 812     }
 813 
 814     interface To$Type$F {
 815         $type$ apply(int i);
 816     }
 817 
 818     static $type$[] fill(int s , To$Type$F f) {
 819         return fill(new $type$[s], f);
 820     }
 821 
 822     static $type$[] fill($type$[] a, To$Type$F f) {
 823         for (int i = 0; i < a.length; i++) {
 824             a[i] = f.apply(i);
 825         }
 826         return a;
 827     }
 828 
 829     static $type$ cornerCaseValue(int i) {
 830 #if[FP]
 831         switch(i % 7) {
 832             case 0:
 833                 return $Wideboxtype$.MAX_VALUE;
 834             case 1:
 835                 return $Wideboxtype$.MIN_VALUE;
 836             case 2:
 837                 return $Wideboxtype$.NEGATIVE_INFINITY;
 838             case 3:
 839                 return $Wideboxtype$.POSITIVE_INFINITY;
 840             case 4:
 841                 return $Wideboxtype$.NaN;
 842             case 5:
 843                 return ($type$)0.0;
 844             default:
 845                 return ($type$)-0.0;
 846         }
 847 #else[FP]
 848         switch(i % 5) {
 849             case 0:
 850                 return $Wideboxtype$.MAX_VALUE;
 851             case 1:
 852                 return $Wideboxtype$.MIN_VALUE;
 853             case 2:
 854                 return $Wideboxtype$.MIN_VALUE;
 855             case 3:
 856                 return $Wideboxtype$.MAX_VALUE;
 857             default:
 858                 return ($type$)0;
 859         }
 860 #end[FP]
 861     }
 862    static $type$ get($type$[] a, int i) {
 863        return ($type$) a[i];
 864    }
 865 
 866    static final IntFunction<$type$[]> fr = (vl) -> {
 867         int length = BUFFER_REPS * vl;
 868         return new $type$[length];
 869     };
 870 
 871     static final IntFunction<boolean[]> fmr = (vl) -> {
 872         int length = BUFFER_REPS * vl;
 873         return new boolean[length];
 874     };
 875 
 876 #if[BITWISE]
 877     static void replaceZero($type$[] a, $type$ v) {
 878         for (int i = 0; i < a.length; i++) {
 879             if (a[i] == 0) {
 880                 a[i] = v;
 881             }
 882         }
 883     }
 884 
 885     static void replaceZero($type$[] a, boolean[] mask, $type$ v) {
 886         for (int i = 0; i < a.length; i++) {
 887             if (mask[i % mask.length] && a[i] == 0) {
 888                 a[i] = v;
 889             }
 890         }
 891     }
 892 #end[BITWISE]
 893 
 894     @Test
 895     static void smokeTest1() {
 896         $abstractvectortype$ three = $abstractvectortype$.broadcast(SPECIES, (byte)-3);
 897         $abstractvectortype$ three2 = ($abstractvectortype$) SPECIES.broadcast(-3);
 898         assert(three.eq(three2).allTrue());
 899         $abstractvectortype$ three3 = three2.broadcast(1).broadcast(-3);
 900         assert(three.eq(three3).allTrue());
 901         int scale = 2;
 902         Class<?> ETYPE = $type$.class;
 903         if (ETYPE == double.class || ETYPE == long.class)
 904             scale = 1000000;
 905         else if (ETYPE == byte.class && SPECIES.length() >= 64)
 906             scale = 1;
 907         $abstractvectortype$ higher = three.addIndex(scale);
 908         VectorMask<$Boxtype$> m = three.compare(VectorOperators.LE, higher);
 909         assert(m.allTrue());
 910         m = higher.min(($type$)-1).test(VectorOperators.IS_NEGATIVE);
 911         assert(m.allTrue());
 912 #if[FP]
 913         m = higher.test(VectorOperators.IS_FINITE);
 914         assert(m.allTrue());
 915 #end[FP]
 916         $type$ max = higher.reduceLanes(VectorOperators.MAX);
 917         assert(max == -3 + scale * (SPECIES.length()-1));
 918     }
 919 
 920     private static $type$[]
 921     bothToArray($abstractvectortype$ a, $abstractvectortype$ b) {
 922         $type$[] r = new $type$[a.length() + b.length()];
 923         a.intoArray(r, 0);
 924         b.intoArray(r, a.length());
 925         return r;
 926     }
 927 
 928     @Test
 929     static void smokeTest2() {
 930         // Do some zipping and shuffling.
 931         $abstractvectortype$ io = ($abstractvectortype$) SPECIES.broadcast(0).addIndex(1);
 932         $abstractvectortype$ io2 = ($abstractvectortype$) VectorShuffle.iota(SPECIES,0,1,false).toVector();
 933         Assert.assertEquals(io, io2);
 934         $abstractvectortype$ a = io.add(($type$)1); //[1,2]
 935         $abstractvectortype$ b = a.neg();  //[-1,-2]
 936         $type$[] abValues = bothToArray(a,b); //[1,2,-1,-2]
 937         VectorShuffle<$Boxtype$> zip0 = VectorShuffle.makeZip(SPECIES, 0);
 938         VectorShuffle<$Boxtype$> zip1 = VectorShuffle.makeZip(SPECIES, 1);
 939         $abstractvectortype$ zab0 = a.rearrange(zip0,b); //[1,-1]
 940         $abstractvectortype$ zab1 = a.rearrange(zip1,b); //[2,-2]
 941         $type$[] zabValues = bothToArray(zab0, zab1); //[1,-1,2,-2]
 942         // manually zip
 943         $type$[] manual = new $type$[zabValues.length];
 944         for (int i = 0; i < manual.length; i += 2) {
 945             manual[i+0] = abValues[i/2];
 946             manual[i+1] = abValues[a.length() + i/2];
 947         }
 948         Assert.assertEquals(Arrays.toString(zabValues), Arrays.toString(manual));
 949         VectorShuffle<$Boxtype$> unz0 = VectorShuffle.makeUnzip(SPECIES, 0);
 950         VectorShuffle<$Boxtype$> unz1 = VectorShuffle.makeUnzip(SPECIES, 1);
 951         $abstractvectortype$ uab0 = zab0.rearrange(unz0,zab1);
 952         $abstractvectortype$ uab1 = zab0.rearrange(unz1,zab1);
 953         $type$[] abValues1 = bothToArray(uab0, uab1);
 954         Assert.assertEquals(Arrays.toString(abValues), Arrays.toString(abValues1));
 955     }
 956 
 957     static void iotaShuffle() {
 958         $abstractvectortype$ io = ($abstractvectortype$) SPECIES.broadcast(0).addIndex(1);
 959         $abstractvectortype$ io2 = ($abstractvectortype$) VectorShuffle.iota(SPECIES, 0 , 1, false).toVector();
 960         Assert.assertEquals(io, io2);
 961     }
 962 
 963     @Test
 964     // Test all shuffle related operations.
 965     static void shuffleTest() {
 966         // To test backend instructions, make sure that C2 is used.
 967         for (int loop = 0; loop < INVOC_COUNT * INVOC_COUNT; loop++) {
 968             iotaShuffle();
 969         }
 970     }
 971 
 972     @Test
 973     void viewAsIntegeralLanesTest() {
 974 #if[FP]
 975         Vector<?> asIntegral = SPECIES.zero().viewAsIntegralLanes();
 976         VectorSpecies<?> asIntegralSpecies = asIntegral.species();
 977         Assert.assertNotEquals(asIntegralSpecies.elementType(), SPECIES.elementType());
 978         Assert.assertEquals(asIntegralSpecies.vectorShape(), SPECIES.vectorShape());
 979         Assert.assertEquals(asIntegralSpecies.length(), SPECIES.length());
 980         Assert.assertEquals(asIntegral.viewAsFloatingLanes().species(), SPECIES);
 981 #else[FP]
 982         Vector<?> asIntegral = SPECIES.zero().viewAsIntegralLanes();
 983         Assert.assertEquals(asIntegral.species(), SPECIES);
 984 #end[FP]
 985     }
 986 
 987 #if[FP]
 988     @Test
 989     void viewAsFloatingLanesTest() {
 990         Vector<?> asFloating = SPECIES.zero().viewAsFloatingLanes();
 991         Assert.assertEquals(asFloating.species(), SPECIES);
 992     }
 993 #else[FP]
 994 #if[byteOrShort]
 995     @Test(expectedExceptions = UnsupportedOperationException.class)
 996     void viewAsFloatingLanesTest() {
 997         SPECIES.zero().viewAsFloatingLanes();
 998     }
 999 #else[byteOrShort]
1000     @Test
1001     void viewAsFloatingLanesTest() {
1002         Vector<?> asFloating = SPECIES.zero().viewAsFloatingLanes();
1003         VectorSpecies<?> asFloatingSpecies = asFloating.species();
1004         Assert.assertNotEquals(asFloatingSpecies.elementType(), SPECIES.elementType());
1005         Assert.assertEquals(asFloatingSpecies.vectorShape(), SPECIES.vectorShape());
1006         Assert.assertEquals(asFloatingSpecies.length(), SPECIES.length());
1007         Assert.assertEquals(asFloating.viewAsIntegralLanes().species(), SPECIES);
1008     }
1009 #end[byteOrShort]
1010 #end[FP]
1011 
1012 #if[BITWISE]
1013     @Test
1014     // Test div by 0.
1015     static void bitwiseDivByZeroSmokeTest() {
1016         try {
1017             $abstractvectortype$ a = ($abstractvectortype$) SPECIES.broadcast(0).addIndex(1);
1018             $abstractvectortype$ b = ($abstractvectortype$) SPECIES.broadcast(0);
1019             a.div(b);
1020             Assert.fail();
1021         } catch (ArithmeticException e) {
1022         }
1023 
1024         try {
1025             $abstractvectortype$ a = ($abstractvectortype$) SPECIES.broadcast(0).addIndex(1);
1026             $abstractvectortype$ b = ($abstractvectortype$) SPECIES.broadcast(0);
1027             VectorMask<$Boxtype$> m = a.lt(($type$) 1);
1028             a.div(b, m);
1029             Assert.fail();
1030         } catch (ArithmeticException e) {
1031         }
1032     }
1033 #end[BITWISE]