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