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()]), "(" + a[i] + ", " + b[(i / SPECIES.length()) * SPECIES.length()] + ") at index #" + i);
 281         }
 282     }
 283 
 284     static void assertArraysEquals($type$[] a, $type$[] b, $type$[] r, boolean[] mask, FBinOp f) {
 285         assertArraysEquals(a, b, r, mask, FBinMaskOp.lift(f));
 286     }
 287 
 288     static void assertArraysEquals($type$[] a, $type$[] b, $type$[] r, boolean[] mask, FBinMaskOp f) {
 289         int i = 0;
 290         try {
 291             for (; i < a.length; i++) {
 292                 Assert.assertEquals(r[i], f.apply(a[i], b[i], mask[i % SPECIES.length()]));
 293             }
 294         } catch (AssertionError err) {
 295             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()]);
 296         }
 297     }
 298 
 299     static void assertBroadcastArraysEquals($type$[] a, $type$[] b, $type$[] r, boolean[] mask, FBinOp f) {
 300         assertBroadcastArraysEquals(a, b, r, mask, FBinMaskOp.lift(f));
 301     }
 302 
 303     static void assertBroadcastArraysEquals($type$[] a, $type$[] b, $type$[] r, boolean[] mask, FBinMaskOp f) {
 304         int i = 0;
 305         try {
 306             for (; i < a.length; i++) {
 307                 Assert.assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], mask[i % SPECIES.length()]));
 308             }
 309         } catch (AssertionError err) {
 310             Assert.assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " + mask[i % SPECIES.length()]);
 311         }
 312     }
 313 
 314     static void assertShiftArraysEquals($type$[] a, $type$[] b, $type$[] r, FBinOp f) {
 315         int i = 0;
 316         int j = 0;
 317         try {
 318             for (; j < a.length; j += SPECIES.length()) {
 319                 for (i = 0; i < SPECIES.length(); i++) {
 320                     Assert.assertEquals(r[i+j], f.apply(a[i+j], b[j]));
 321                 }
 322             }
 323         } catch (AssertionError e) {
 324             Assert.assertEquals(r[i+j], f.apply(a[i+j], b[j]), "at index #" + i + ", " + j);
 325         }
 326     }
 327 
 328     static void assertShiftArraysEquals($type$[] a, $type$[] b, $type$[] r, boolean[] mask, FBinOp f) {
 329         assertShiftArraysEquals(a, b, r, mask, FBinMaskOp.lift(f));
 330     }
 331 
 332     static void assertShiftArraysEquals($type$[] a, $type$[] b, $type$[] r, boolean[] mask, FBinMaskOp f) {
 333         int i = 0;
 334         int j = 0;
 335         try {
 336             for (; j < a.length; j += SPECIES.length()) {
 337                 for (i = 0; i < SPECIES.length(); i++) {
 338                     Assert.assertEquals(r[i+j], f.apply(a[i+j], b[j], mask[i]));
 339                 }
 340             }
 341         } catch (AssertionError err) {
 342             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]);
 343         }
 344     }
 345 
 346     interface FTernOp {
 347         $type$ apply($type$ a, $type$ b, $type$ c);
 348     }
 349 
 350     interface FTernMaskOp {
 351         $type$ apply($type$ a, $type$ b, $type$ c, boolean m);
 352 
 353         static FTernMaskOp lift(FTernOp f) {
 354             return (a, b, c, m) -> m ? f.apply(a, b, c) : a;
 355         }
 356     }
 357 
 358     static void assertArraysEquals($type$[] a, $type$[] b, $type$[] c, $type$[] r, FTernOp f) {
 359         int i = 0;
 360         try {
 361             for (; i < a.length; i++) {
 362                 Assert.assertEquals(r[i], f.apply(a[i], b[i], c[i]));
 363             }
 364         } catch (AssertionError e) {
 365             Assert.assertEquals(r[i], f.apply(a[i], b[i], c[i]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]);
 366         }
 367     }
 368 
 369     static void assertArraysEquals($type$[] a, $type$[] b, $type$[] c, $type$[] r, boolean[] mask, FTernOp f) {
 370         assertArraysEquals(a, b, c, r, mask, FTernMaskOp.lift(f));
 371     }
 372 
 373     static void assertArraysEquals($type$[] a, $type$[] b, $type$[] c, $type$[] r, boolean[] mask, FTernMaskOp f) {
 374         int i = 0;
 375         try {
 376             for (; i < a.length; i++) {
 377                 Assert.assertEquals(r[i], f.apply(a[i], b[i], c[i], mask[i % SPECIES.length()]));
 378             }
 379         } catch (AssertionError err) {
 380             Assert.assertEquals(r[i], f.apply(a[i], b[i], c[i], mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = "
 381               + b[i] + ", input3 = " + c[i] + ", mask = " + mask[i % SPECIES.length()]);
 382         }
 383     }
 384 
 385 #if[FP]
 386     static boolean isWithin1Ulp($type$ actual, $type$ expected) {
 387         if ($Type$.isNaN(expected) && !$Type$.isNaN(actual)) {
 388             return false;
 389         } else if (!$Type$.isNaN(expected) && $Type$.isNaN(actual)) {
 390             return false;
 391         }
 392 
 393         $type$ low = Math.nextDown(expected);
 394         $type$ high = Math.nextUp(expected);
 395 
 396         if ($Type$.compare(low, expected) > 0) {
 397             return false;
 398         }
 399 
 400         if ($Type$.compare(high, expected) < 0) {
 401             return false;
 402         }
 403 
 404         return true;
 405     }
 406 
 407     static void assertArraysEqualsWithinOneUlp($type$[] a, $type$[] r, FUnOp mathf, FUnOp strictmathf) {
 408         int i = 0;
 409         try {
 410             // Check that result is within 1 ulp of strict math or equivalent to math implementation.
 411             for (; i < a.length; i++) {
 412                 Assert.assertTrue($Type$.compare(r[i], mathf.apply(a[i])) == 0 ||
 413                                     isWithin1Ulp(r[i], strictmathf.apply(a[i])));
 414             }
 415         } catch (AssertionError e) {
 416             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]));
 417             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]));
 418         }
 419     }
 420 
 421     static void assertArraysEqualsWithinOneUlp($type$[] a, $type$[] b, $type$[] r, FBinOp mathf, FBinOp strictmathf) {
 422         int i = 0;
 423         try {
 424             // Check that result is within 1 ulp of strict math or equivalent to math implementation.
 425             for (; i < a.length; i++) {
 426                 Assert.assertTrue($Type$.compare(r[i], mathf.apply(a[i], b[i])) == 0 ||
 427                                     isWithin1Ulp(r[i], strictmathf.apply(a[i], b[i])));
 428             }
 429         } catch (AssertionError e) {
 430             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]));
 431             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]));
 432         }
 433     }
 434 #end[FP]
 435 
 436     interface FBinArrayOp {
 437         $type$ apply($type$[] a, int b);
 438     }
 439 
 440     static void assertArraysEquals($type$[] a, $type$[] r, FBinArrayOp f) {
 441         int i = 0;
 442         try {
 443             for (; i < a.length; i++) {
 444                 Assert.assertEquals(r[i], f.apply(a, i));
 445             }
 446         } catch (AssertionError e) {
 447             Assert.assertEquals(r[i], f.apply(a,i), "at index #" + i);
 448         }
 449     }
 450 
 451     interface FGatherScatterOp {
 452         $type$[] apply($type$[] a, int ix, int[] b, int iy);
 453     }
 454 
 455     static void assertArraysEquals($type$[] a, int[] b, $type$[] r, FGatherScatterOp f) {
 456         int i = 0;
 457         try {
 458             for (; i < a.length; i += SPECIES.length()) {
 459                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
 460                   f.apply(a, i, b, i));
 461             }
 462         } catch (AssertionError e) {
 463             $type$[] ref = f.apply(a, i, b, i);
 464             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
 465             Assert.assertEquals(res, ref,
 466               "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: "
 467               + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length()))
 468               + ", b: "
 469               + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length()))
 470               + " at index #" + i);
 471         }
 472     }
 473 
 474     interface FGatherMaskedOp {
 475         $type$[] apply($type$[] a, int ix, boolean[] mask, int[] b, int iy);
 476     }
 477 
 478     interface FScatterMaskedOp {
 479         $type$[] apply($type$[] r, $type$[] a, int ix, boolean[] mask, int[] b, int iy);
 480     }
 481 
 482     static void assertArraysEquals($type$[] a, int[] b, $type$[] r, boolean[] mask, FGatherMaskedOp f) {
 483         int i = 0;
 484         try {
 485             for (; i < a.length; i += SPECIES.length()) {
 486                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
 487                   f.apply(a, i, mask, b, i));
 488             }
 489         } catch (AssertionError e) {
 490             $type$[] ref = f.apply(a, i, mask, b, i);
 491             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
 492             Assert.assertEquals(ref, res,
 493               "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: "
 494               + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length()))
 495               + ", b: "
 496               + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length()))
 497               + ", mask: "
 498               + Arrays.toString(mask)
 499               + " at index #" + i);
 500         }
 501     }
 502 
 503     static void assertArraysEquals($type$[] a, int[] b, $type$[] r, boolean[] mask, FScatterMaskedOp f) {
 504         int i = 0;
 505         try {
 506             for (; i < a.length; i += SPECIES.length()) {
 507                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
 508                   f.apply(r, a, i, mask, b, i));
 509             }
 510         } catch (AssertionError e) {
 511             $type$[] ref = f.apply(r, a, i, mask, b, i);
 512             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
 513             Assert.assertEquals(ref, res,
 514               "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: "
 515               + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length()))
 516               + ", b: "
 517               + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length()))
 518               + ", r: "
 519               + Arrays.toString(Arrays.copyOfRange(r, i, i+SPECIES.length()))
 520               + ", mask: "
 521               + Arrays.toString(mask)
 522               + " at index #" + i);
 523         }
 524     }
 525 
 526     interface FLaneOp {
 527         $type$[] apply($type$[] a, int origin, int idx);
 528     }
 529 
 530     static void assertArraysEquals($type$[] a, $type$[] r, int origin, FLaneOp f) {
 531         int i = 0;
 532         try {
 533             for (; i < a.length; i += SPECIES.length()) {
 534                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
 535                   f.apply(a, origin, i));
 536             }
 537         } catch (AssertionError e) {
 538             $type$[] ref = f.apply(a, origin, i);
 539             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
 540             Assert.assertEquals(ref, res, "(ref: " + Arrays.toString(ref)
 541               + ", res: " + Arrays.toString(res)
 542               + "), at index #" + i);
 543         }
 544     }
 545 
 546     interface FLaneBop {
 547         $type$[] apply($type$[] a, $type$[] b, int origin, int idx);
 548     }
 549 
 550     static void assertArraysEquals($type$[] a, $type$[] b, $type$[] r, int origin, FLaneBop f) {
 551         int i = 0;
 552         try {
 553             for (; i < a.length; i += SPECIES.length()) {
 554                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
 555                   f.apply(a, b, origin, i));
 556             }
 557         } catch (AssertionError e) {
 558             $type$[] ref = f.apply(a, b, origin, i);
 559             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
 560             Assert.assertEquals(ref, res, "(ref: " + Arrays.toString(ref)
 561               + ", res: " + Arrays.toString(res)
 562               + "), at index #" + i
 563               + ", at origin #" + origin);
 564         }
 565     }
 566 
 567     interface FLaneMaskedBop {
 568         $type$[] apply($type$[] a, $type$[] b, int origin, boolean[] mask, int idx);
 569     }
 570 
 571     static void assertArraysEquals($type$[] a, $type$[] b, $type$[] r, int origin, boolean[] mask, FLaneMaskedBop f) {
 572         int i = 0;
 573         try {
 574             for (; i < a.length; i += SPECIES.length()) {
 575                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
 576                   f.apply(a, b, origin, mask, i));
 577             }
 578         } catch (AssertionError e) {
 579             $type$[] ref = f.apply(a, b, origin, mask, i);
 580             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
 581             Assert.assertEquals(ref, res, "(ref: " + Arrays.toString(ref)
 582               + ", res: " + Arrays.toString(res)
 583               + "), at index #" + i
 584               + ", at origin #" + origin);
 585         }
 586     }
 587 
 588     interface FLanePartBop {
 589         $type$[] apply($type$[] a, $type$[] b, int origin, int part, int idx);
 590     }
 591 
 592     static void assertArraysEquals($type$[] a, $type$[] b, $type$[] r, int origin, int part, FLanePartBop f) {
 593         int i = 0;
 594         try {
 595             for (; i < a.length; i += SPECIES.length()) {
 596                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
 597                   f.apply(a, b, origin, part, i));
 598             }
 599         } catch (AssertionError e) {
 600             $type$[] ref = f.apply(a, b, origin, part, i);
 601             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
 602             Assert.assertEquals(ref, res, "(ref: " + Arrays.toString(ref)
 603               + ", res: " + Arrays.toString(res)
 604               + "), at index #" + i
 605               + ", at origin #" + origin
 606               + ", with part #" + part);
 607         }
 608     }
 609 
 610     interface FLanePartMaskedBop {
 611         $type$[] apply($type$[] a, $type$[] b, int origin, int part, boolean[] mask, int idx);
 612     }
 613 
 614     static void assertArraysEquals($type$[] a, $type$[] b, $type$[] r, int origin, int part, boolean[] mask, FLanePartMaskedBop f) {
 615         int i = 0;
 616         try {
 617             for (; i < a.length; i += SPECIES.length()) {
 618                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
 619                   f.apply(a, b, origin, part, mask, i));
 620             }
 621         } catch (AssertionError e) {
 622             $type$[] ref = f.apply(a, b, origin, part, mask, i);
 623             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
 624             Assert.assertEquals(ref, res, "(ref: " + Arrays.toString(ref)
 625               + ", res: " + Arrays.toString(res)
 626               + "), at index #" + i
 627               + ", at origin #" + origin
 628               + ", with part #" + part);
 629         }
 630     }
 631 
 632     static $bitstype$ bits($type$ e) {
 633         return {#if[FP]? $Type$.$type$To$Bitstype$Bits(e): e};
 634     }
 635 
 636     static final List<IntFunction<$type$[]>> $TYPE$_GENERATORS = List.of(
 637             withToString("$type$[-i * 5]", (int s) -> {
 638                 return fill(s * BUFFER_REPS,
 639                             i -> ($type$)(-i * 5));
 640             }),
 641             withToString("$type$[i * 5]", (int s) -> {
 642                 return fill(s * BUFFER_REPS,
 643                             i -> ($type$)(i * 5));
 644             }),
 645             withToString("$type$[i + 1]", (int s) -> {
 646                 return fill(s * BUFFER_REPS,
 647                             i -> ((($type$)(i + 1) == 0) ? 1 : ($type$)(i + 1)));
 648             }),
 649             withToString("$type$[cornerCaseValue(i)]", (int s) -> {
 650                 return fill(s * BUFFER_REPS,
 651                             i -> cornerCaseValue(i));
 652             })
 653     );
 654 
 655     // Create combinations of pairs
 656     // @@@ Might be sensitive to order e.g. div by 0
 657     static final List<List<IntFunction<$type$[]>>> $TYPE$_GENERATOR_PAIRS =
 658         Stream.of($TYPE$_GENERATORS.get(0)).
 659                 flatMap(fa -> $TYPE$_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))).
 660                 collect(Collectors.toList());
 661 
 662     @DataProvider
 663     public Object[][] boolUnaryOpProvider() {
 664         return BOOL_ARRAY_GENERATORS.stream().
 665                 map(f -> new Object[]{f}).
 666                 toArray(Object[][]::new);
 667     }
 668 
 669     static final List<List<IntFunction<$type$[]>>> $TYPE$_GENERATOR_TRIPLES =
 670         $TYPE$_GENERATOR_PAIRS.stream().
 671                 flatMap(pair -> $TYPE$_GENERATORS.stream().map(f -> List.of(pair.get(0), pair.get(1), f))).
 672                 collect(Collectors.toList());
 673 
 674     @DataProvider
 675     public Object[][] $type$BinaryOpProvider() {
 676         return $TYPE$_GENERATOR_PAIRS.stream().map(List::toArray).
 677                 toArray(Object[][]::new);
 678     }
 679 
 680     @DataProvider
 681     public Object[][] $type$IndexedOpProvider() {
 682         return $TYPE$_GENERATOR_PAIRS.stream().map(List::toArray).
 683                 toArray(Object[][]::new);
 684     }
 685 
 686     @DataProvider
 687     public Object[][] $type$BinaryOpMaskProvider() {
 688         return BOOLEAN_MASK_GENERATORS.stream().
 689                 flatMap(fm -> $TYPE$_GENERATOR_PAIRS.stream().map(lfa -> {
 690                     return Stream.concat(lfa.stream(), Stream.of(fm)).toArray();
 691                 })).
 692                 toArray(Object[][]::new);
 693     }
 694 
 695     @DataProvider
 696     public Object[][] $type$TernaryOpProvider() {
 697         return $TYPE$_GENERATOR_TRIPLES.stream().map(List::toArray).
 698                 toArray(Object[][]::new);
 699     }
 700 
 701     @DataProvider
 702     public Object[][] $type$TernaryOpMaskProvider() {
 703         return BOOLEAN_MASK_GENERATORS.stream().
 704                 flatMap(fm -> $TYPE$_GENERATOR_TRIPLES.stream().map(lfa -> {
 705                     return Stream.concat(lfa.stream(), Stream.of(fm)).toArray();
 706                 })).
 707                 toArray(Object[][]::new);
 708     }
 709 
 710     @DataProvider
 711     public Object[][] $type$UnaryOpProvider() {
 712         return $TYPE$_GENERATORS.stream().
 713                 map(f -> new Object[]{f}).
 714                 toArray(Object[][]::new);
 715     }
 716 
 717     @DataProvider
 718     public Object[][] $type$UnaryOpMaskProvider() {
 719         return BOOLEAN_MASK_GENERATORS.stream().
 720                 flatMap(fm -> $TYPE$_GENERATORS.stream().map(fa -> {
 721                     return new Object[] {fa, fm};
 722                 })).
 723                 toArray(Object[][]::new);
 724     }
 725 
 726     @DataProvider
 727     public Object[][] $type$UnaryOpShuffleProvider() {
 728         return INT_SHUFFLE_GENERATORS.stream().
 729                 flatMap(fs -> $TYPE$_GENERATORS.stream().map(fa -> {
 730                     return new Object[] {fa, fs};
 731                 })).
 732                 toArray(Object[][]::new);
 733     }
 734 
 735     @DataProvider
 736     public Object[][] $type$UnaryOpIndexProvider() {
 737         return INT_INDEX_GENERATORS.stream().
 738                 flatMap(fs -> $TYPE$_GENERATORS.stream().map(fa -> {
 739                     return new Object[] {fa, fs};
 740                 })).
 741                 toArray(Object[][]::new);
 742     }
 743 
 744     @DataProvider
 745     public Object[][] $type$UnaryMaskedOpIndexProvider() {
 746         return BOOLEAN_MASK_GENERATORS.stream().
 747           flatMap(fs -> INT_INDEX_GENERATORS.stream().flatMap(fm ->
 748             $TYPE$_GENERATORS.stream().map(fa -> {
 749                     return new Object[] {fa, fm, fs};
 750             }))).
 751             toArray(Object[][]::new);
 752     }
 753 
 754     @DataProvider
 755     public Object[][] scatterMaskedOpIndexProvider() {
 756         return BOOLEAN_MASK_GENERATORS.stream().
 757           flatMap(fs -> INT_INDEX_GENERATORS.stream().flatMap(fm ->
 758             $TYPE$_GENERATORS.stream().flatMap(fn ->
 759               $TYPE$_GENERATORS.stream().map(fa -> {
 760                     return new Object[] {fa, fn, fm, fs};
 761             })))).
 762             toArray(Object[][]::new);
 763     }
 764 
 765     static final List<IntFunction<$type$[]>> $TYPE$_COMPARE_GENERATORS = List.of(
 766             withToString("$type$[i]", (int s) -> {
 767                 return fill(s * BUFFER_REPS,
 768                             i -> ($type$)i);
 769             }),
 770             withToString("$type$[i + 1]", (int s) -> {
 771                 return fill(s * BUFFER_REPS,
 772                             i -> ($type$)(i + 1));
 773             }),
 774             withToString("$type$[i - 2]", (int s) -> {
 775                 return fill(s * BUFFER_REPS,
 776                             i -> ($type$)(i - 2));
 777             }),
 778             withToString("$type$[zigZag(i)]", (int s) -> {
 779                 return fill(s * BUFFER_REPS,
 780                             i -> i%3 == 0 ? ($type$)i : (i%3 == 1 ? ($type$)(i + 1) : ($type$)(i - 2)));
 781             }),
 782             withToString("$type$[cornerCaseValue(i)]", (int s) -> {
 783                 return fill(s * BUFFER_REPS,
 784                             i -> cornerCaseValue(i));
 785             })
 786     );
 787 
 788     static final List<List<IntFunction<$type$[]>>> $TYPE$_TEST_GENERATOR_ARGS =
 789         $TYPE$_COMPARE_GENERATORS.stream().
 790                 map(fa -> List.of(fa)).
 791                 collect(Collectors.toList());
 792 
 793     @DataProvider
 794     public Object[][] $type$TestOpProvider() {
 795         return $TYPE$_TEST_GENERATOR_ARGS.stream().map(List::toArray).
 796                 toArray(Object[][]::new);
 797     }
 798 
 799     static final List<List<IntFunction<$type$[]>>> $TYPE$_COMPARE_GENERATOR_PAIRS =
 800         $TYPE$_COMPARE_GENERATORS.stream().
 801                 flatMap(fa -> $TYPE$_COMPARE_GENERATORS.stream().map(fb -> List.of(fa, fb))).
 802                 collect(Collectors.toList());
 803 
 804     @DataProvider
 805     public Object[][] $type$CompareOpProvider() {
 806         return $TYPE$_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray).
 807                 toArray(Object[][]::new);
 808     }
 809 
 810     interface To$Type$F {
 811         $type$ apply(int i);
 812     }
 813 
 814     static $type$[] fill(int s , To$Type$F f) {
 815         return fill(new $type$[s], f);
 816     }
 817 
 818     static $type$[] fill($type$[] a, To$Type$F f) {
 819         for (int i = 0; i < a.length; i++) {
 820             a[i] = f.apply(i);
 821         }
 822         return a;
 823     }
 824 
 825     static $type$ cornerCaseValue(int i) {
 826 #if[FP]
 827         switch(i % 7) {
 828             case 0:
 829                 return $Wideboxtype$.MAX_VALUE;
 830             case 1:
 831                 return $Wideboxtype$.MIN_VALUE;
 832             case 2:
 833                 return $Wideboxtype$.NEGATIVE_INFINITY;
 834             case 3:
 835                 return $Wideboxtype$.POSITIVE_INFINITY;
 836             case 4:
 837                 return $Wideboxtype$.NaN;
 838             case 5:
 839                 return ($type$)0.0;
 840             default:
 841                 return ($type$)-0.0;
 842         }
 843 #else[FP]
 844         switch(i % 5) {
 845             case 0:
 846                 return $Wideboxtype$.MAX_VALUE;
 847             case 1:
 848                 return $Wideboxtype$.MIN_VALUE;
 849             case 2:
 850                 return $Wideboxtype$.MIN_VALUE;
 851             case 3:
 852                 return $Wideboxtype$.MAX_VALUE;
 853             default:
 854                 return ($type$)0;
 855         }
 856 #end[FP]
 857     }
 858    static $type$ get($type$[] a, int i) {
 859        return ($type$) a[i];
 860    }
 861 
 862    static final IntFunction<$type$[]> fr = (vl) -> {
 863         int length = BUFFER_REPS * vl;
 864         return new $type$[length];
 865     };
 866 
 867     static final IntFunction<boolean[]> fmr = (vl) -> {
 868         int length = BUFFER_REPS * vl;
 869         return new boolean[length];
 870     };
 871 
 872 #if[BITWISE]
 873     static void replaceZero($type$[] a, $type$ v) {
 874         for (int i = 0; i < a.length; i++) {
 875             if (a[i] == 0) {
 876                 a[i] = v;
 877             }
 878         }
 879     }
 880 
 881     static void replaceZero($type$[] a, boolean[] mask, $type$ v) {
 882         for (int i = 0; i < a.length; i++) {
 883             if (mask[i % mask.length] && a[i] == 0) {
 884                 a[i] = v;
 885             }
 886         }
 887     }
 888 #end[BITWISE]
 889 
 890     @Test
 891     static void smokeTest1() {
 892         $abstractvectortype$ three = $abstractvectortype$.broadcast(SPECIES, (byte)-3);
 893         $abstractvectortype$ three2 = ($abstractvectortype$) SPECIES.broadcast(-3);
 894         assert(three.eq(three2).allTrue());
 895         $abstractvectortype$ three3 = three2.broadcast(1).broadcast(-3);
 896         assert(three.eq(three3).allTrue());
 897         int scale = 2;
 898         Class<?> ETYPE = $type$.class;
 899         if (ETYPE == double.class || ETYPE == long.class)
 900             scale = 1000000;
 901         else if (ETYPE == byte.class && SPECIES.length() >= 64)
 902             scale = 1;
 903         $abstractvectortype$ higher = three.addIndex(scale);
 904         VectorMask<$Boxtype$> m = three.compare(VectorOperators.LE, higher);
 905         assert(m.allTrue());
 906         m = higher.min(($type$)-1).test(VectorOperators.IS_NEGATIVE);
 907         assert(m.allTrue());
 908 #if[FP]
 909         m = higher.test(VectorOperators.IS_FINITE);
 910         assert(m.allTrue());
 911 #end[FP]
 912         $type$ max = higher.reduceLanes(VectorOperators.MAX);
 913         assert(max == -3 + scale * (SPECIES.length()-1));
 914     }
 915 
 916     private static $type$[]
 917     bothToArray($abstractvectortype$ a, $abstractvectortype$ b) {
 918         $type$[] r = new $type$[a.length() + b.length()];
 919         a.intoArray(r, 0);
 920         b.intoArray(r, a.length());
 921         return r;
 922     }
 923 
 924     @Test
 925     static void smokeTest2() {
 926         // Do some zipping and shuffling.
 927         $abstractvectortype$ io = ($abstractvectortype$) SPECIES.broadcast(0).addIndex(1);
 928         $abstractvectortype$ io2 = ($abstractvectortype$) VectorShuffle.iota(SPECIES,0,1,false).toVector();
 929         Assert.assertEquals(io, io2);
 930         $abstractvectortype$ a = io.add(($type$)1); //[1,2]
 931         $abstractvectortype$ b = a.neg();  //[-1,-2]
 932         $type$[] abValues = bothToArray(a,b); //[1,2,-1,-2]
 933         VectorShuffle<$Boxtype$> zip0 = VectorShuffle.makeZip(SPECIES, 0);
 934         VectorShuffle<$Boxtype$> zip1 = VectorShuffle.makeZip(SPECIES, 1);
 935         $abstractvectortype$ zab0 = a.rearrange(zip0,b); //[1,-1]
 936         $abstractvectortype$ zab1 = a.rearrange(zip1,b); //[2,-2]
 937         $type$[] zabValues = bothToArray(zab0, zab1); //[1,-1,2,-2]
 938         // manually zip
 939         $type$[] manual = new $type$[zabValues.length];
 940         for (int i = 0; i < manual.length; i += 2) {
 941             manual[i+0] = abValues[i/2];
 942             manual[i+1] = abValues[a.length() + i/2];
 943         }
 944         Assert.assertEquals(Arrays.toString(zabValues), Arrays.toString(manual));
 945         VectorShuffle<$Boxtype$> unz0 = VectorShuffle.makeUnzip(SPECIES, 0);
 946         VectorShuffle<$Boxtype$> unz1 = VectorShuffle.makeUnzip(SPECIES, 1);
 947         $abstractvectortype$ uab0 = zab0.rearrange(unz0,zab1);
 948         $abstractvectortype$ uab1 = zab0.rearrange(unz1,zab1);
 949         $type$[] abValues1 = bothToArray(uab0, uab1);
 950         Assert.assertEquals(Arrays.toString(abValues), Arrays.toString(abValues1));
 951     }
 952 
 953     static void iotaShuffle() {
 954         $abstractvectortype$ io = ($abstractvectortype$) SPECIES.broadcast(0).addIndex(1);
 955         $abstractvectortype$ io2 = ($abstractvectortype$) VectorShuffle.iota(SPECIES, 0 , 1, false).toVector();
 956         Assert.assertEquals(io, io2);
 957     }
 958 
 959     @Test
 960     // Test all shuffle related operations.
 961     static void shuffleTest() {
 962         // To test backend instructions, make sure that C2 is used.
 963         for (int loop = 0; loop < INVOC_COUNT * INVOC_COUNT; loop++) {
 964             iotaShuffle();
 965         }
 966     }
 967 
 968     @Test
 969     void viewAsIntegeralLanesTest() {
 970 #if[FP]
 971         Vector<?> asIntegral = SPECIES.zero().viewAsIntegralLanes();
 972         VectorSpecies<?> asIntegralSpecies = asIntegral.species();
 973         Assert.assertNotEquals(asIntegralSpecies.elementType(), SPECIES.elementType());
 974         Assert.assertEquals(asIntegralSpecies.vectorShape(), SPECIES.vectorShape());
 975         Assert.assertEquals(asIntegralSpecies.length(), SPECIES.length());
 976         Assert.assertEquals(asIntegral.viewAsFloatingLanes().species(), SPECIES);
 977 #else[FP]
 978         Vector<?> asIntegral = SPECIES.zero().viewAsIntegralLanes();
 979         Assert.assertEquals(asIntegral.species(), SPECIES);
 980 #end[FP]
 981     }
 982 
 983 #if[FP]
 984     @Test
 985     void viewAsFloatingLanesTest() {
 986         Vector<?> asFloating = SPECIES.zero().viewAsFloatingLanes();
 987         Assert.assertEquals(asFloating.species(), SPECIES);
 988     }
 989 #else[FP]
 990 #if[byteOrShort]
 991     @Test(expectedExceptions = UnsupportedOperationException.class)
 992     void viewAsFloatingLanesTest() {
 993         SPECIES.zero().viewAsFloatingLanes();
 994     }
 995 #else[byteOrShort]
 996     @Test
 997     void viewAsFloatingLanesTest() {
 998         Vector<?> asFloating = SPECIES.zero().viewAsFloatingLanes();
 999         VectorSpecies<?> asFloatingSpecies = asFloating.species();
1000         Assert.assertNotEquals(asFloatingSpecies.elementType(), SPECIES.elementType());
1001         Assert.assertEquals(asFloatingSpecies.vectorShape(), SPECIES.vectorShape());
1002         Assert.assertEquals(asFloatingSpecies.length(), SPECIES.length());
1003         Assert.assertEquals(asFloating.viewAsIntegralLanes().species(), SPECIES);
1004     }
1005 #end[byteOrShort]
1006 #end[FP]
1007 
1008 #if[BITWISE]
1009     @Test
1010     // Test div by 0.
1011     static void bitwiseDivByZeroSmokeTest() {
1012         try {
1013             $abstractvectortype$ a = ($abstractvectortype$) SPECIES.broadcast(0).addIndex(1);
1014             $abstractvectortype$ b = ($abstractvectortype$) SPECIES.broadcast(0);
1015             a.div(b);
1016             Assert.fail();
1017         } catch (ArithmeticException e) {
1018         }
1019 
1020         try {
1021             $abstractvectortype$ a = ($abstractvectortype$) SPECIES.broadcast(0).addIndex(1);
1022             $abstractvectortype$ b = ($abstractvectortype$) SPECIES.broadcast(0);
1023             VectorMask<$Boxtype$> m = a.lt(($type$) 1);
1024             a.div(b, m);
1025             Assert.fail();
1026         } catch (ArithmeticException e) {
1027         }
1028     }
1029 #end[BITWISE]