1 /*
   2  * Copyright (c) 2018, 2025, 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  * @key randomness
  27  *
  28  * @library /test/lib
  29  * @modules jdk.incubator.vector
  30  * @run testng/othervm/timeout=300 -ea -esa -Xbatch -XX:-TieredCompilation $vectorteststype$
  31  */
  32 
  33 #warn This file is preprocessed before being compiled
  34 
  35 import jdk.incubator.vector.VectorShape;
  36 import jdk.incubator.vector.VectorSpecies;
  37 import jdk.incubator.vector.VectorShuffle;
  38 import jdk.incubator.vector.VectorMask;
  39 import jdk.incubator.vector.VectorOperators;
  40 import jdk.incubator.vector.Vector;
  41 #if[!FP]
  42 import jdk.incubator.vector.VectorMath;
  43 #end[!FP]
  44 
  45 #if[Byte]
  46 import jdk.incubator.vector.ByteVector;
  47 #end[Byte]
  48 #if[Float]
  49 import jdk.incubator.vector.FloatVector;
  50 #end[Float]
  51 #if[Int]
  52 import jdk.incubator.vector.IntVector;
  53 #end[Int]
  54 #if[Double]
  55 import jdk.incubator.vector.DoubleVector;
  56 #end[Double]
  57 #if[Short]
  58 import jdk.incubator.vector.ShortVector;
  59 #end[Short]
  60 #if[Long]
  61 import jdk.incubator.vector.LongVector;
  62 #end[Long]
  63 
  64 import org.testng.Assert;
  65 import org.testng.annotations.DataProvider;
  66 import org.testng.annotations.Test;
  67 
  68 import java.lang.Integer;
  69 import java.util.List;
  70 import java.util.Arrays;
  71 import java.util.function.BiFunction;
  72 import java.util.function.IntFunction;
  73 import java.util.Objects;
  74 import java.util.stream.Collectors;
  75 import java.util.stream.Stream;
  76 
  77 @Test
  78 public class $vectorteststype$ extends AbstractVectorTest {
  79 
  80 #if[MaxBit]
  81     static final VectorSpecies<$Wideboxtype$> SPECIES =
  82                 $Type$Vector.SPECIES_MAX;
  83 #else[MaxBit]
  84     static final VectorSpecies<$Wideboxtype$> SPECIES =
  85                 $Type$Vector.SPECIES_$bits$;
  86 #end[MaxBit]
  87 
  88     static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 100);
  89 
  90     static $abstractvectortype$ bcast_vec = $abstractvectortype$.broadcast(SPECIES, ($type$)10);
  91 
  92 #if[MaxBit]
  93     static VectorShape getMaxBit() {
  94         return VectorShape.S_Max_BIT;
  95     }
  96 
  97     private static final int Max = 256;  // juts so we can do N/$bits$
  98 #end[MaxBit]
  99 
 100 #if[BITWISE]
 101     private static final $type$ CONST_SHIFT = $Boxtype$.SIZE / 2;
 102 #end[BITWISE]
 103 #if[FP]
 104     // for floating point addition reduction ops that may introduce rounding errors
 105     private static final $type$ RELATIVE_ROUNDING_ERROR_FACTOR_ADD = ($type$)10.0;
 106 
 107     // for floating point multiplication reduction ops that may introduce rounding errors
 108     private static final $type$ RELATIVE_ROUNDING_ERROR_FACTOR_MUL = ($type$)50.0;
 109 #end[FP]
 110 
 111     static final int BUFFER_REPS = Integer.getInteger("jdk.incubator.vector.test.buffer-vectors", 25000 / $bits$);
 112 
 113     static void assertArraysStrictlyEquals($type$[] r, $type$[] a) {
 114         for (int i = 0; i < a.length; i++) {
 115 #if[FP]
 116             $bitstype$ ir = $Wideboxtype$.$type$ToRaw$Bitstype$Bits(r[i]);
 117             $bitstype$ ia = $Wideboxtype$.$type$ToRaw$Bitstype$Bits(a[i]);
 118             if (ir != ia) {
 119 #if[Float]
 120                 Assert.fail(String.format("at index #%d, expected = %08X, actual = %08X", i, ia, ir));
 121 #else[Float]
 122                 Assert.fail(String.format("at index #%d, expected = %016X, actual = %016X", i, ia, ir));
 123 #end[Float]
 124             }
 125 #else[FP]
 126             if (r[i] != a[i]) {
 127                 Assert.fail("at index #" + i + ", expected = " + a[i] + ", actual = " + r[i]);
 128             }
 129 #end[FP]
 130         }
 131     }
 132 
 133     interface FUnOp {
 134         $type$ apply($type$ a);
 135     }
 136 
 137     static void assertArraysEquals($type$[] r, $type$[] a, FUnOp f) {
 138         int i = 0;
 139         try {
 140             for (; i < a.length; i++) {
 141                 Assert.assertEquals(r[i], f.apply(a[i]));
 142             }
 143         } catch (AssertionError e) {
 144             Assert.assertEquals(r[i], f.apply(a[i]), "at index #" + i + ", input = " + a[i]);
 145         }
 146     }
 147 
 148     interface FUnArrayOp {
 149         $type$[] apply($type$ a);
 150     }
 151 
 152     static void assertArraysEquals($type$[] r, $type$[] a, FUnArrayOp f) {
 153         int i = 0;
 154         try {
 155             for (; i < a.length; i += SPECIES.length()) {
 156                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
 157                   f.apply(a[i]));
 158             }
 159         } catch (AssertionError e) {
 160             $type$[] ref = f.apply(a[i]);
 161             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
 162             Assert.assertEquals(res, ref, "(ref: " + Arrays.toString(ref)
 163               + ", res: " + Arrays.toString(res)
 164               + "), at index #" + i);
 165         }
 166     }
 167 
 168     static void assertArraysEquals($type$[] r, $type$[] a, boolean[] mask, FUnOp f) {
 169         int i = 0;
 170         try {
 171             for (; i < a.length; i++) {
 172                 Assert.assertEquals(r[i], mask[i % SPECIES.length()] ? f.apply(a[i]) : a[i]);
 173             }
 174         } catch (AssertionError e) {
 175             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()]);
 176         }
 177     }
 178 
 179     interface FReductionOp {
 180         $type$ apply($type$[] a, int idx);
 181     }
 182 
 183     interface FReductionAllOp {
 184         $type$ apply($type$[] a);
 185     }
 186 
 187     static void assertReductionArraysEquals($type$[] r, $type$ rc, $type$[] a,
 188                                             FReductionOp f, FReductionAllOp fa) {
 189 #if[FP]
 190         assertReductionArraysEquals(r, rc, a, f, fa, ($type$)0.0);
 191 #else[FP]
 192         int i = 0;
 193         try {
 194             Assert.assertEquals(rc, fa.apply(a));
 195             for (; i < a.length; i += SPECIES.length()) {
 196                 Assert.assertEquals(r[i], f.apply(a, i));
 197             }
 198         } catch (AssertionError e) {
 199             Assert.assertEquals(rc, fa.apply(a), "Final result is incorrect!");
 200             Assert.assertEquals(r[i], f.apply(a, i), "at index #" + i);
 201         }
 202 #end[FP]
 203     }
 204 #if[FP]
 205 
 206     static void assertReductionArraysEquals($type$[] r, $type$ rc, $type$[] a,
 207                                             FReductionOp f, FReductionAllOp fa,
 208                                             $type$ relativeErrorFactor) {
 209         int i = 0;
 210         try {
 211             Assert.assertEquals(rc, fa.apply(a), Math.ulp(rc) * relativeErrorFactor);
 212             for (; i < a.length; i += SPECIES.length()) {
 213                 Assert.assertEquals(r[i], f.apply(a, i), Math.ulp(r[i]) * relativeErrorFactor);
 214             }
 215         } catch (AssertionError e) {
 216             Assert.assertEquals(rc, fa.apply(a), Math.ulp(rc) * relativeErrorFactor, "Final result is incorrect!");
 217             Assert.assertEquals(r[i], f.apply(a, i), Math.ulp(r[i]) * relativeErrorFactor, "at index #" + i);
 218         }
 219     }
 220 #end[FP]
 221 
 222     interface FReductionMaskedOp {
 223         $type$ apply($type$[] a, int idx, boolean[] mask);
 224     }
 225 
 226     interface FReductionAllMaskedOp {
 227         $type$ apply($type$[] a, boolean[] mask);
 228     }
 229 
 230     static void assertReductionArraysEqualsMasked($type$[] r, $type$ rc, $type$[] a, boolean[] mask,
 231                                             FReductionMaskedOp f, FReductionAllMaskedOp fa) {
 232 #if[FP]
 233         assertReductionArraysEqualsMasked(r, rc, a, mask, f, fa, ($type$)0.0);
 234 #else[FP]
 235         int i = 0;
 236         try {
 237             Assert.assertEquals(rc, fa.apply(a, mask));
 238             for (; i < a.length; i += SPECIES.length()) {
 239                 Assert.assertEquals(r[i], f.apply(a, i, mask));
 240             }
 241         } catch (AssertionError e) {
 242             Assert.assertEquals(rc, fa.apply(a, mask), "Final result is incorrect!");
 243             Assert.assertEquals(r[i], f.apply(a, i, mask), "at index #" + i);
 244         }
 245 #end[FP]
 246     }
 247 #if[FP]
 248 
 249     static void assertReductionArraysEqualsMasked($type$[] r, $type$ rc, $type$[] a, boolean[] mask,
 250                                             FReductionMaskedOp f, FReductionAllMaskedOp fa,
 251                                             $type$ relativeError) {
 252         int i = 0;
 253         try {
 254             Assert.assertEquals(rc, fa.apply(a, mask), Math.abs(rc * relativeError));
 255             for (; i < a.length; i += SPECIES.length()) {
 256                 Assert.assertEquals(r[i], f.apply(a, i, mask), Math.abs(r[i] *
 257 relativeError));
 258             }
 259         } catch (AssertionError e) {
 260             Assert.assertEquals(rc, fa.apply(a, mask), Math.abs(rc * relativeError), "Final result is incorrect!");
 261             Assert.assertEquals(r[i], f.apply(a, i, mask), Math.abs(r[i] * relativeError), "at index #" + i);
 262         }
 263     }
 264 #end[FP]
 265 
 266 #if[!Long]
 267     interface FReductionOpLong {
 268         long apply($type$[] a, int idx);
 269     }
 270 
 271     interface FReductionAllOpLong {
 272         long apply($type$[] a);
 273     }
 274 
 275     static void assertReductionLongArraysEquals(long[] r, long rc, $type$[] a,
 276                                             FReductionOpLong f, FReductionAllOpLong fa) {
 277         int i = 0;
 278         try {
 279             Assert.assertEquals(rc, fa.apply(a));
 280             for (; i < a.length; i += SPECIES.length()) {
 281                 Assert.assertEquals(r[i], f.apply(a, i));
 282             }
 283         } catch (AssertionError e) {
 284             Assert.assertEquals(rc, fa.apply(a), "Final result is incorrect!");
 285             Assert.assertEquals(r[i], f.apply(a, i), "at index #" + i);
 286         }
 287     }
 288 
 289     interface FReductionMaskedOpLong {
 290         long apply($type$[] a, int idx, boolean[] mask);
 291     }
 292 
 293     interface FReductionAllMaskedOpLong {
 294         long apply($type$[] a, boolean[] mask);
 295     }
 296 
 297     static void assertReductionLongArraysEqualsMasked(long[] r, long rc, $type$[] a, boolean[] mask,
 298                                             FReductionMaskedOpLong f, FReductionAllMaskedOpLong fa) {
 299         int i = 0;
 300         try {
 301             Assert.assertEquals(rc, fa.apply(a, mask));
 302             for (; i < a.length; i += SPECIES.length()) {
 303                 Assert.assertEquals(r[i], f.apply(a, i, mask));
 304             }
 305         } catch (AssertionError e) {
 306             Assert.assertEquals(rc, fa.apply(a, mask), "Final result is incorrect!");
 307             Assert.assertEquals(r[i], f.apply(a, i, mask), "at index #" + i);
 308         }
 309     }
 310 #end[!Long]
 311 
 312     interface FBoolReductionOp {
 313         boolean apply(boolean[] a, int idx);
 314     }
 315 
 316     static void assertReductionBoolArraysEquals(boolean[] r, boolean[] a, FBoolReductionOp f) {
 317         int i = 0;
 318         try {
 319             for (; i < a.length; i += SPECIES.length()) {
 320                 Assert.assertEquals(r[i], f.apply(a, i));
 321             }
 322         } catch (AssertionError e) {
 323             Assert.assertEquals(r[i], f.apply(a, i), "at index #" + i);
 324         }
 325     }
 326 
 327     interface FMaskReductionOp {
 328         int apply(boolean[] a, int idx);
 329     }
 330 
 331     static void assertMaskReductionArraysEquals(int[] r, boolean[] a, FMaskReductionOp f) {
 332         int i = 0;
 333         try {
 334             for (; i < a.length; i += SPECIES.length()) {
 335                 Assert.assertEquals(r[i], f.apply(a, i));
 336             }
 337         } catch (AssertionError e) {
 338             Assert.assertEquals(r[i], f.apply(a, i), "at index #" + i);
 339         }
 340     }
 341 
 342     static void assertRearrangeArraysEquals($type$[] r, $type$[] a, int[] order, int vector_len) {
 343         int i = 0, j = 0;
 344         try {
 345             for (; i < a.length; i += vector_len) {
 346                 for (j = 0; j < vector_len; j++) {
 347                     Assert.assertEquals(r[i+j], a[i+order[i+j]]);
 348                 }
 349             }
 350         } catch (AssertionError e) {
 351             int idx = i + j;
 352             Assert.assertEquals(r[i+j], a[i+order[i+j]], "at index #" + idx + ", input = " + a[i+order[i+j]]);
 353         }
 354     }
 355 
 356     static void assertcompressArraysEquals($type$[] r, $type$[] a, boolean[] m, int vector_len) {
 357         int i = 0, j = 0, k = 0;
 358         try {
 359             for (; i < a.length; i += vector_len) {
 360                 k = 0;
 361                 for (j = 0; j < vector_len; j++) {
 362                     if (m[(i + j) % SPECIES.length()]) {
 363                         Assert.assertEquals(r[i + k], a[i + j]);
 364                         k++;
 365                     }
 366                 }
 367                 for (; k < vector_len; k++) {
 368                     Assert.assertEquals(r[i + k], ($type$)0);
 369                 }
 370             }
 371         } catch (AssertionError e) {
 372             int idx = i + k;
 373             if (m[(i + j) % SPECIES.length()]) {
 374                 Assert.assertEquals(r[idx], a[i + j], "at index #" + idx);
 375             } else {
 376                 Assert.assertEquals(r[idx], ($type$)0, "at index #" + idx);
 377             }
 378         }
 379     }
 380 
 381     static void assertexpandArraysEquals($type$[] r, $type$[] a, boolean[] m, int vector_len) {
 382         int i = 0, j = 0, k = 0;
 383         try {
 384             for (; i < a.length; i += vector_len) {
 385                 k = 0;
 386                 for (j = 0; j < vector_len; j++) {
 387                     if (m[(i + j) % SPECIES.length()]) {
 388                         Assert.assertEquals(r[i + j], a[i + k]);
 389                         k++;
 390                     } else {
 391                         Assert.assertEquals(r[i + j], ($type$)0);
 392                     }
 393                 }
 394             }
 395         } catch (AssertionError e) {
 396             int idx = i + j;
 397             if (m[idx % SPECIES.length()]) {
 398                 Assert.assertEquals(r[idx], a[i + k], "at index #" + idx);
 399             } else {
 400                 Assert.assertEquals(r[idx], ($type$)0, "at index #" + idx);
 401             }
 402         }
 403     }
 404 
 405     static void assertSelectFromTwoVectorEquals($type$[] r, $type$[] order, $type$[] a, $type$[] b, int vector_len) {
 406         int i = 0, j = 0;
 407         boolean is_exceptional_idx = false;
 408         int idx = 0, wrapped_index = 0, oidx = 0;
 409         try {
 410             for (; i < a.length; i += vector_len) {
 411                 for (j = 0; j < vector_len; j++) {
 412                     idx = i + j;
 413                     wrapped_index = Math.floorMod((int)order[idx], 2 * vector_len);
 414                     is_exceptional_idx = wrapped_index >= vector_len;
 415                     oidx = is_exceptional_idx ? (wrapped_index - vector_len) : wrapped_index;
 416                     Assert.assertEquals(r[idx], (is_exceptional_idx ? b[i + oidx] : a[i + oidx]));
 417                 }
 418             }
 419         } catch (AssertionError e) {
 420             Assert.assertEquals(r[idx], (is_exceptional_idx ? b[i + oidx] : a[i + oidx]), "at index #" + idx + ", order = " + order[idx] + ", a = " + a[i + oidx] + ", b = " + b[i + oidx]);
 421         }
 422     }
 423 
 424     static void assertSelectFromArraysEquals($type$[] r, $type$[] a, $type$[] order, int vector_len) {
 425         int i = 0, j = 0;
 426         try {
 427             for (; i < a.length; i += vector_len) {
 428                 for (j = 0; j < vector_len; j++) {
 429                     Assert.assertEquals(r[i+j], a[i+(int)order[i+j]]);
 430                 }
 431             }
 432         } catch (AssertionError e) {
 433             int idx = i + j;
 434             Assert.assertEquals(r[i+j], a[i+(int)order[i+j]], "at index #" + idx + ", input = " + a[i+(int)order[i+j]]);
 435         }
 436     }
 437 
 438     static void assertRearrangeArraysEquals($type$[] r, $type$[] a, int[] order, boolean[] mask, int vector_len) {
 439         int i = 0, j = 0;
 440         try {
 441             for (; i < a.length; i += vector_len) {
 442                 for (j = 0; j < vector_len; j++) {
 443                     if (mask[j % SPECIES.length()])
 444                          Assert.assertEquals(r[i+j], a[i+order[i+j]]);
 445                     else
 446                          Assert.assertEquals(r[i+j], ($type$)0);
 447                 }
 448             }
 449         } catch (AssertionError e) {
 450             int idx = i + j;
 451             if (mask[j % SPECIES.length()])
 452                 Assert.assertEquals(r[i+j], a[i+order[i+j]], "at index #" + idx + ", input = " + a[i+order[i+j]] + ", mask = " + mask[j % SPECIES.length()]);
 453             else
 454                 Assert.assertEquals(r[i+j], ($type$)0, "at index #" + idx + ", input = " + a[i+order[i+j]] + ", mask = " + mask[j % SPECIES.length()]);
 455         }
 456     }
 457 
 458     static void assertSelectFromArraysEquals($type$[] r, $type$[] a, $type$[] order, boolean[] mask, int vector_len) {
 459         int i = 0, j = 0;
 460         try {
 461             for (; i < a.length; i += vector_len) {
 462                 for (j = 0; j < vector_len; j++) {
 463                     if (mask[j % SPECIES.length()])
 464                          Assert.assertEquals(r[i+j], a[i+(int)order[i+j]]);
 465                     else
 466                          Assert.assertEquals(r[i+j], ($type$)0);
 467                 }
 468             }
 469         } catch (AssertionError e) {
 470             int idx = i + j;
 471             if (mask[j % SPECIES.length()])
 472                 Assert.assertEquals(r[i+j], a[i+(int)order[i+j]], "at index #" + idx + ", input = " + a[i+(int)order[i+j]] + ", mask = " + mask[j % SPECIES.length()]);
 473             else
 474                 Assert.assertEquals(r[i+j], ($type$)0, "at index #" + idx + ", input = " + a[i+(int)order[i+j]] + ", mask = " + mask[j % SPECIES.length()]);
 475         }
 476     }
 477 
 478     static void assertBroadcastArraysEquals($type$[] r, $type$[] a) {
 479         int i = 0;
 480         for (; i < a.length; i += SPECIES.length()) {
 481             int idx = i;
 482             for (int j = idx; j < (idx + SPECIES.length()); j++)
 483                 a[j]=a[idx];
 484         }
 485 
 486         try {
 487             for (i = 0; i < a.length; i++) {
 488                 Assert.assertEquals(r[i], a[i]);
 489             }
 490         } catch (AssertionError e) {
 491             Assert.assertEquals(r[i], a[i], "at index #" + i + ", input = " + a[i]);
 492         }
 493     }
 494 
 495     interface FBinOp {
 496         $type$ apply($type$ a, $type$ b);
 497     }
 498 
 499     interface FBinMaskOp {
 500         $type$ apply($type$ a, $type$ b, boolean m);
 501 
 502         static FBinMaskOp lift(FBinOp f) {
 503             return (a, b, m) -> m ? f.apply(a, b) : a;
 504         }
 505     }
 506 
 507     static void assertArraysEqualsAssociative($type$[] rl, $type$[] rr, $type$[] a, $type$[] b, $type$[] c, FBinOp f) {
 508         int i = 0;
 509         try {
 510             for (; i < a.length; i++) {
 511                 //Left associative
 512                 Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]));
 513 
 514                 //Right associative
 515                 Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])));
 516 
 517                 //Results equal sanity check
 518                 Assert.assertEquals(rl[i], rr[i]);
 519             }
 520         } catch (AssertionError e) {
 521             Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]);
 522             Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]);
 523             Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]);
 524         }
 525     }
 526 
 527    static void assertArraysEqualsAssociative($type$[] rl, $type$[] rr, $type$[] a, $type$[] b, $type$[] c, boolean[] mask, FBinOp f) {
 528        assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f));
 529    }
 530 
 531     static void assertArraysEqualsAssociative($type$[] rl, $type$[] rr, $type$[] a, $type$[] b, $type$[] c, boolean[] mask, FBinMaskOp f) {
 532         int i = 0;
 533         boolean mask_bit = false;
 534         try {
 535             for (; i < a.length; i++) {
 536                 mask_bit = mask[i % SPECIES.length()];
 537                 //Left associative
 538                 Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit));
 539 
 540                 //Right associative
 541                 Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit));
 542 
 543                 //Results equal sanity check
 544                 Assert.assertEquals(rl[i], rr[i]);
 545             }
 546         } catch (AssertionError e) {
 547             Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit);
 548             Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit);
 549             Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]);
 550         }
 551     }
 552 
 553     static void assertArraysEquals($type$[] r, $type$[] a, $type$[] b, FBinOp f) {
 554         int i = 0;
 555         try {
 556             for (; i < a.length; i++) {
 557                 Assert.assertEquals(r[i], f.apply(a[i], b[i]));
 558             }
 559         } catch (AssertionError e) {
 560             Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i);
 561         }
 562     }
 563 
 564     static void assertArraysEquals($type$[] r, $type$[] a, $type$ b, FBinOp f) {
 565         int i = 0;
 566         try {
 567             for (; i < a.length; i++) {
 568                 Assert.assertEquals(r[i], f.apply(a[i], b));
 569             }
 570         } catch (AssertionError e) {
 571             Assert.assertEquals(r[i], f.apply(a[i], b), "(" + a[i] + ", " + b + ") at index #" + i);
 572         }
 573     }
 574 
 575     static void assertBroadcastArraysEquals($type$[] r, $type$[] a, $type$[] b, FBinOp f) {
 576         int i = 0;
 577         try {
 578             for (; i < a.length; i++) {
 579                 Assert.assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]));
 580             }
 581         } catch (AssertionError e) {
 582             Assert.assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]),
 583                                 "(" + a[i] + ", " + b[(i / SPECIES.length()) * SPECIES.length()] + ") at index #" + i);
 584         }
 585     }
 586 
 587     static void assertBroadcastLongArraysEquals($type$[] r, $type$[] a, $type$[] b, FBinOp f) {
 588         int i = 0;
 589         try {
 590             for (; i < a.length; i++) {
 591                 Assert.assertEquals(r[i], f.apply(a[i], ($type$)((long)b[(i / SPECIES.length()) * SPECIES.length()])));
 592             }
 593         } catch (AssertionError e) {
 594             Assert.assertEquals(r[i], f.apply(a[i], ($type$)((long)b[(i / SPECIES.length()) * SPECIES.length()])),
 595                                 "(" + a[i] + ", " + b[(i / SPECIES.length()) * SPECIES.length()] + ") at index #" + i);
 596         }
 597     }
 598 
 599     static void assertArraysEquals($type$[] r, $type$[] a, $type$[] b, boolean[] mask, FBinOp f) {
 600         assertArraysEquals(r, a, b, mask, FBinMaskOp.lift(f));
 601     }
 602 
 603     static void assertArraysEquals($type$[] r, $type$[] a, $type$[] b, boolean[] mask, FBinMaskOp f) {
 604         int i = 0;
 605         try {
 606             for (; i < a.length; i++) {
 607                 Assert.assertEquals(r[i], f.apply(a[i], b[i], mask[i % SPECIES.length()]));
 608             }
 609         } catch (AssertionError err) {
 610             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()]);
 611         }
 612     }
 613 
 614     static void assertArraysEquals($type$[] r, $type$[] a, $type$ b, boolean[] mask, FBinOp f) {
 615         assertArraysEquals(r, a, b, mask, FBinMaskOp.lift(f));
 616     }
 617 
 618     static void assertArraysEquals($type$[] r, $type$[] a, $type$ b, boolean[] mask, FBinMaskOp f) {
 619         int i = 0;
 620         try {
 621             for (; i < a.length; i++) {
 622                 Assert.assertEquals(r[i], f.apply(a[i], b, mask[i % SPECIES.length()]));
 623             }
 624         } catch (AssertionError err) {
 625             Assert.assertEquals(r[i], f.apply(a[i], b, mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b + ", mask = " + mask[i % SPECIES.length()]);
 626         }
 627     }
 628 
 629     static void assertBroadcastArraysEquals($type$[] r, $type$[] a, $type$[] b, boolean[] mask, FBinOp f) {
 630         assertBroadcastArraysEquals(r, a, b, mask, FBinMaskOp.lift(f));
 631     }
 632 
 633     static void assertBroadcastArraysEquals($type$[] r, $type$[] a, $type$[] b, boolean[] mask, FBinMaskOp f) {
 634         int i = 0;
 635         try {
 636             for (; i < a.length; i++) {
 637                 Assert.assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], mask[i % SPECIES.length()]));
 638             }
 639         } catch (AssertionError err) {
 640             Assert.assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()],
 641                                 mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] +
 642                                 ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " +
 643                                 mask[i % SPECIES.length()]);
 644         }
 645     }
 646 
 647     static void assertBroadcastLongArraysEquals($type$[] r, $type$[] a, $type$[] b, boolean[] mask, FBinOp f) {
 648         assertBroadcastLongArraysEquals(r, a, b, mask, FBinMaskOp.lift(f));
 649     }
 650 
 651     static void assertBroadcastLongArraysEquals($type$[] r, $type$[] a, $type$[] b, boolean[] mask, FBinMaskOp f) {
 652         int i = 0;
 653         try {
 654             for (; i < a.length; i++) {
 655                 Assert.assertEquals(r[i], f.apply(a[i], ($type$)((long)b[(i / SPECIES.length()) * SPECIES.length()]), mask[i % SPECIES.length()]));
 656             }
 657         } catch (AssertionError err) {
 658             Assert.assertEquals(r[i], f.apply(a[i], ($type$)((long)b[(i / SPECIES.length()) * SPECIES.length()]),
 659                                 mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] +
 660                                 ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " +
 661                                 mask[i % SPECIES.length()]);
 662         }
 663     }
 664 
 665     static void assertShiftArraysEquals($type$[] r, $type$[] a, $type$[] b, FBinOp f) {
 666         int i = 0;
 667         int j = 0;
 668         try {
 669             for (; j < a.length; j += SPECIES.length()) {
 670                 for (i = 0; i < SPECIES.length(); i++) {
 671                     Assert.assertEquals(r[i+j], f.apply(a[i+j], b[j]));
 672                 }
 673             }
 674         } catch (AssertionError e) {
 675             Assert.assertEquals(r[i+j], f.apply(a[i+j], b[j]), "at index #" + i + ", " + j);
 676         }
 677     }
 678 
 679     static void assertShiftArraysEquals($type$[] r, $type$[] a, $type$[] b, boolean[] mask, FBinOp f) {
 680         assertShiftArraysEquals(r, a, b, mask, FBinMaskOp.lift(f));
 681     }
 682 
 683     static void assertShiftArraysEquals($type$[] r, $type$[] a, $type$[] b, boolean[] mask, FBinMaskOp f) {
 684         int i = 0;
 685         int j = 0;
 686         try {
 687             for (; j < a.length; j += SPECIES.length()) {
 688                 for (i = 0; i < SPECIES.length(); i++) {
 689                     Assert.assertEquals(r[i+j], f.apply(a[i+j], b[j], mask[i]));
 690                 }
 691             }
 692         } catch (AssertionError err) {
 693             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]);
 694         }
 695     }
 696 
 697     interface FBinConstOp {
 698         $type$ apply($type$ a);
 699     }
 700 
 701     interface FBinConstMaskOp {
 702         $type$ apply($type$ a, boolean m);
 703 
 704         static FBinConstMaskOp lift(FBinConstOp f) {
 705             return (a, m) -> m ? f.apply(a) : a;
 706         }
 707     }
 708 
 709     static void assertShiftConstEquals($type$[] r, $type$[] a, FBinConstOp f) {
 710         int i = 0;
 711         int j = 0;
 712         try {
 713             for (; j < a.length; j += SPECIES.length()) {
 714                 for (i = 0; i < SPECIES.length(); i++) {
 715                     Assert.assertEquals(r[i+j], f.apply(a[i+j]));
 716                 }
 717             }
 718         } catch (AssertionError e) {
 719             Assert.assertEquals(r[i+j], f.apply(a[i+j]), "at index #" + i + ", " + j);
 720         }
 721     }
 722 
 723     static void assertShiftConstEquals($type$[] r, $type$[] a, boolean[] mask, FBinConstOp f) {
 724         assertShiftConstEquals(r, a, mask, FBinConstMaskOp.lift(f));
 725     }
 726 
 727     static void assertShiftConstEquals($type$[] r, $type$[] a, boolean[] mask, FBinConstMaskOp f) {
 728         int i = 0;
 729         int j = 0;
 730         try {
 731             for (; j < a.length; j += SPECIES.length()) {
 732                 for (i = 0; i < SPECIES.length(); i++) {
 733                     Assert.assertEquals(r[i+j], f.apply(a[i+j], mask[i]));
 734                 }
 735             }
 736         } catch (AssertionError err) {
 737             Assert.assertEquals(r[i+j], f.apply(a[i+j], mask[i]), "at index #" + i + ", input1 = " + a[i+j] + ", mask = " + mask[i]);
 738         }
 739     }
 740 
 741     interface FTernOp {
 742         $type$ apply($type$ a, $type$ b, $type$ c);
 743     }
 744 
 745     interface FTernMaskOp {
 746         $type$ apply($type$ a, $type$ b, $type$ c, boolean m);
 747 
 748         static FTernMaskOp lift(FTernOp f) {
 749             return (a, b, c, m) -> m ? f.apply(a, b, c) : a;
 750         }
 751     }
 752 
 753     static void assertArraysEquals($type$[] r, $type$[] a, $type$[] b, $type$[] c, FTernOp f) {
 754         int i = 0;
 755         try {
 756             for (; i < a.length; i++) {
 757                 Assert.assertEquals(r[i], f.apply(a[i], b[i], c[i]));
 758             }
 759         } catch (AssertionError e) {
 760             Assert.assertEquals(r[i], f.apply(a[i], b[i], c[i]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]);
 761         }
 762     }
 763 
 764     static void assertArraysEquals($type$[] r, $type$[] a, $type$[] b, $type$[] c, boolean[] mask, FTernOp f) {
 765         assertArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f));
 766     }
 767 
 768     static void assertArraysEquals($type$[] r, $type$[] a, $type$[] b, $type$[] c, boolean[] mask, FTernMaskOp f) {
 769         int i = 0;
 770         try {
 771             for (; i < a.length; i++) {
 772                 Assert.assertEquals(r[i], f.apply(a[i], b[i], c[i], mask[i % SPECIES.length()]));
 773             }
 774         } catch (AssertionError err) {
 775             Assert.assertEquals(r[i], f.apply(a[i], b[i], c[i], mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = "
 776               + b[i] + ", input3 = " + c[i] + ", mask = " + mask[i % SPECIES.length()]);
 777         }
 778     }
 779 
 780     static void assertBroadcastArraysEquals($type$[] r, $type$[] a, $type$[] b, $type$[] c, FTernOp f) {
 781         int i = 0;
 782         try {
 783             for (; i < a.length; i++) {
 784                 Assert.assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()]));
 785             }
 786         } catch (AssertionError e) {
 787             Assert.assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()]), "at index #" +
 788                                 i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " +
 789                                 c[(i / SPECIES.length()) * SPECIES.length()]);
 790         }
 791     }
 792 
 793     static void assertAltBroadcastArraysEquals($type$[] r, $type$[] a, $type$[] b, $type$[] c, FTernOp f) {
 794         int i = 0;
 795         try {
 796             for (; i < a.length; i++) {
 797                 Assert.assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i]));
 798             }
 799         } catch (AssertionError e) {
 800             Assert.assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i]), "at index #" +
 801                                 i + ", input1 = " + a[i] + ", input2 = " +
 802                                 b[(i / SPECIES.length()) * SPECIES.length()] + ",  input3 = " + c[i]);
 803         }
 804     }
 805 
 806     static void assertBroadcastArraysEquals($type$[] r, $type$[] a, $type$[] b, $type$[] c, boolean[] mask,
 807                                             FTernOp f) {
 808         assertBroadcastArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f));
 809     }
 810 
 811     static void assertBroadcastArraysEquals($type$[] r, $type$[] a, $type$[] b, $type$[] c, boolean[] mask,
 812                                             FTernMaskOp f) {
 813         int i = 0;
 814         try {
 815             for (; i < a.length; i++) {
 816                 Assert.assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()],
 817                                     mask[i % SPECIES.length()]));
 818             }
 819         } catch (AssertionError err) {
 820             Assert.assertEquals(r[i], f.apply(a[i], b[i], c[(i / SPECIES.length()) * SPECIES.length()],
 821                                 mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] + ", input2 = " +
 822                                 b[i] + ", input3 = " + c[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " +
 823                                 mask[i % SPECIES.length()]);
 824         }
 825     }
 826 
 827     static void assertAltBroadcastArraysEquals($type$[] r, $type$[] a, $type$[] b, $type$[] c, boolean[] mask,
 828                                             FTernOp f) {
 829         assertAltBroadcastArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f));
 830     }
 831 
 832     static void assertAltBroadcastArraysEquals($type$[] r, $type$[] a, $type$[] b, $type$[] c, boolean[] mask,
 833                                             FTernMaskOp f) {
 834         int i = 0;
 835         try {
 836             for (; i < a.length; i++) {
 837                 Assert.assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i],
 838                                     mask[i % SPECIES.length()]));
 839             }
 840         } catch (AssertionError err) {
 841             Assert.assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()], c[i],
 842                                 mask[i % SPECIES.length()]), "at index #" + i + ", input1 = " + a[i] +
 843                                 ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] +
 844                                 ", input3 = " + c[i] + ", mask = " + mask[i % SPECIES.length()]);
 845         }
 846     }
 847 
 848     static void assertDoubleBroadcastArraysEquals($type$[] r, $type$[] a, $type$[] b, $type$[] c, FTernOp f) {
 849         int i = 0;
 850         try {
 851             for (; i < a.length; i++) {
 852                 Assert.assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()],
 853                                     c[(i / SPECIES.length()) * SPECIES.length()]));
 854             }
 855         } catch (AssertionError e) {
 856             Assert.assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()],
 857                                 c[(i / SPECIES.length()) * SPECIES.length()]), "at index #" + i + ", input1 = " + a[i]
 858                                 + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] + ", input3 = " +
 859                                 c[(i / SPECIES.length()) * SPECIES.length()]);
 860         }
 861     }
 862 
 863     static void assertDoubleBroadcastArraysEquals($type$[] r, $type$[] a, $type$[] b, $type$[] c, boolean[] mask,
 864                                                   FTernOp f) {
 865         assertDoubleBroadcastArraysEquals(r, a, b, c, mask, FTernMaskOp.lift(f));
 866     }
 867 
 868     static void assertDoubleBroadcastArraysEquals($type$[] r, $type$[] a, $type$[] b, $type$[] c, boolean[] mask,
 869                                                   FTernMaskOp f) {
 870         int i = 0;
 871         try {
 872             for (; i < a.length; i++) {
 873                 Assert.assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()],
 874                                     c[(i / SPECIES.length()) * SPECIES.length()], mask[i % SPECIES.length()]));
 875             }
 876         } catch (AssertionError err) {
 877             Assert.assertEquals(r[i], f.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()],
 878                                 c[(i / SPECIES.length()) * SPECIES.length()], mask[i % SPECIES.length()]), "at index #"
 879                                 + i + ", input1 = " + a[i] + ", input2 = " + b[(i / SPECIES.length()) * SPECIES.length()] +
 880                                 ", input3 = " + c[(i / SPECIES.length()) * SPECIES.length()] + ", mask = " +
 881                                 mask[i % SPECIES.length()]);
 882         }
 883     }
 884 
 885 
 886 #if[FP]
 887     static boolean isWithin1Ulp($type$ actual, $type$ expected) {
 888         if ($Type$.isNaN(expected) && !$Type$.isNaN(actual)) {
 889             return false;
 890         } else if (!$Type$.isNaN(expected) && $Type$.isNaN(actual)) {
 891             return false;
 892         }
 893 
 894         $type$ low = Math.nextDown(expected);
 895         $type$ high = Math.nextUp(expected);
 896 
 897         if ($Type$.compare(low, expected) > 0) {
 898             return false;
 899         }
 900 
 901         if ($Type$.compare(high, expected) < 0) {
 902             return false;
 903         }
 904 
 905         return true;
 906     }
 907 
 908     static void assertArraysEqualsWithinOneUlp($type$[] r, $type$[] a, FUnOp mathf, FUnOp strictmathf) {
 909         int i = 0;
 910         try {
 911             // Check that result is within 1 ulp of strict math or equivalent to math implementation.
 912             for (; i < a.length; i++) {
 913                 Assert.assertTrue($Type$.compare(r[i], mathf.apply(a[i])) == 0 ||
 914                                     isWithin1Ulp(r[i], strictmathf.apply(a[i])));
 915             }
 916         } catch (AssertionError e) {
 917             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]));
 918             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]));
 919         }
 920     }
 921 
 922     static void assertArraysEqualsWithinOneUlp($type$[] r, $type$[] a, $type$[] b, FBinOp mathf, FBinOp strictmathf) {
 923         int i = 0;
 924         try {
 925             // Check that result is within 1 ulp of strict math or equivalent to math implementation.
 926             for (; i < a.length; i++) {
 927                 Assert.assertTrue($Type$.compare(r[i], mathf.apply(a[i], b[i])) == 0 ||
 928                                     isWithin1Ulp(r[i], strictmathf.apply(a[i], b[i])));
 929             }
 930         } catch (AssertionError e) {
 931             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]));
 932             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]));
 933         }
 934     }
 935 
 936     static void assertBroadcastArraysEqualsWithinOneUlp($type$[] r, $type$[] a, $type$[] b,
 937                                                         FBinOp mathf, FBinOp strictmathf) {
 938         int i = 0;
 939         try {
 940             // Check that result is within 1 ulp of strict math or equivalent to math implementation.
 941             for (; i < a.length; i++) {
 942                 Assert.assertTrue($Type$.compare(r[i],
 943                                   mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])) == 0 ||
 944                                   isWithin1Ulp(r[i],
 945                                   strictmathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])));
 946             }
 947         } catch (AssertionError e) {
 948             Assert.assertTrue($Type$.compare(r[i],
 949                               mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])) == 0,
 950                               "at index #" + i + ", input1 = " + a[i] + ", input2 = " +
 951                               b[(i / SPECIES.length()) * SPECIES.length()] + ", actual = " + r[i] +
 952                               ", expected = " + mathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()]));
 953             Assert.assertTrue(isWithin1Ulp(r[i],
 954                               strictmathf.apply(a[i], b[(i / SPECIES.length()) * SPECIES.length()])),
 955                              "at index #" + i + ", input1 = " + a[i] + ", input2 = " +
 956                              b[(i / SPECIES.length()) * SPECIES.length()] + ", actual = " + r[i] +
 957                              ", expected (within 1 ulp) = " + strictmathf.apply(a[i],
 958                              b[(i / SPECIES.length()) * SPECIES.length()]));
 959         }
 960     }
 961 #end[FP]
 962 
 963     interface FGatherScatterOp {
 964         $type$[] apply($type$[] a, int ix, int[] b, int iy);
 965     }
 966 
 967     static void assertArraysEquals($type$[] r, $type$[] a, int[] b, FGatherScatterOp f) {
 968         int i = 0;
 969         try {
 970             for (; i < a.length; i += SPECIES.length()) {
 971                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
 972                   f.apply(a, i, b, i));
 973             }
 974         } catch (AssertionError e) {
 975             $type$[] ref = f.apply(a, i, b, i);
 976             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
 977             Assert.assertEquals(res, ref,
 978               "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: "
 979               + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length()))
 980               + ", b: "
 981               + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length()))
 982               + " at index #" + i);
 983         }
 984     }
 985 
 986     interface FGatherMaskedOp {
 987         $type$[] apply($type$[] a, int ix, boolean[] mask, int[] b, int iy);
 988     }
 989 
 990     interface FScatterMaskedOp {
 991         $type$[] apply($type$[] r, $type$[] a, int ix, boolean[] mask, int[] b, int iy);
 992     }
 993 
 994     static void assertArraysEquals($type$[] r, $type$[] a, int[] b, boolean[] mask, FGatherMaskedOp f) {
 995         int i = 0;
 996         try {
 997             for (; i < a.length; i += SPECIES.length()) {
 998                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
 999                   f.apply(a, i, mask, b, i));
1000             }
1001         } catch (AssertionError e) {
1002             $type$[] ref = f.apply(a, i, mask, b, i);
1003             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
1004             Assert.assertEquals(res, ref,
1005               "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: "
1006               + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length()))
1007               + ", b: "
1008               + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length()))
1009               + ", mask: "
1010               + Arrays.toString(mask)
1011               + " at index #" + i);
1012         }
1013     }
1014 
1015     static void assertArraysEquals($type$[] r, $type$[] a, int[] b, boolean[] mask, FScatterMaskedOp f) {
1016         int i = 0;
1017         try {
1018             for (; i < a.length; i += SPECIES.length()) {
1019                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
1020                   f.apply(r, a, i, mask, b, i));
1021             }
1022         } catch (AssertionError e) {
1023             $type$[] ref = f.apply(r, a, i, mask, b, i);
1024             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
1025             Assert.assertEquals(res, ref,
1026               "(ref: " + Arrays.toString(ref) + ", res: " + Arrays.toString(res) + ", a: "
1027               + Arrays.toString(Arrays.copyOfRange(a, i, i+SPECIES.length()))
1028               + ", b: "
1029               + Arrays.toString(Arrays.copyOfRange(b, i, i+SPECIES.length()))
1030               + ", r: "
1031               + Arrays.toString(Arrays.copyOfRange(r, i, i+SPECIES.length()))
1032               + ", mask: "
1033               + Arrays.toString(mask)
1034               + " at index #" + i);
1035         }
1036     }
1037 
1038     interface FLaneOp {
1039         $type$[] apply($type$[] a, int origin, int idx);
1040     }
1041 
1042     static void assertArraysEquals($type$[] r, $type$[] a, int origin, FLaneOp f) {
1043         int i = 0;
1044         try {
1045             for (; i < a.length; i += SPECIES.length()) {
1046                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
1047                   f.apply(a, origin, i));
1048             }
1049         } catch (AssertionError e) {
1050             $type$[] ref = f.apply(a, origin, i);
1051             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
1052             Assert.assertEquals(res, ref, "(ref: " + Arrays.toString(ref)
1053               + ", res: " + Arrays.toString(res)
1054               + "), at index #" + i);
1055         }
1056     }
1057 
1058     interface FLaneBop {
1059         $type$[] apply($type$[] a, $type$[] b, int origin, int idx);
1060     }
1061 
1062     static void assertArraysEquals($type$[] r, $type$[] a, $type$[] b, int origin, FLaneBop f) {
1063         int i = 0;
1064         try {
1065             for (; i < a.length; i += SPECIES.length()) {
1066                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
1067                   f.apply(a, b, origin, i));
1068             }
1069         } catch (AssertionError e) {
1070             $type$[] ref = f.apply(a, b, origin, i);
1071             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
1072             Assert.assertEquals(res, ref, "(ref: " + Arrays.toString(ref)
1073               + ", res: " + Arrays.toString(res)
1074               + "), at index #" + i
1075               + ", at origin #" + origin);
1076         }
1077     }
1078 
1079     interface FLaneMaskedBop {
1080         $type$[] apply($type$[] a, $type$[] b, int origin, boolean[] mask, int idx);
1081     }
1082 
1083     static void assertArraysEquals($type$[] r, $type$[] a, $type$[] b, int origin, boolean[] mask, FLaneMaskedBop f) {
1084         int i = 0;
1085         try {
1086             for (; i < a.length; i += SPECIES.length()) {
1087                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
1088                   f.apply(a, b, origin, mask, i));
1089             }
1090         } catch (AssertionError e) {
1091             $type$[] ref = f.apply(a, b, origin, mask, i);
1092             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
1093             Assert.assertEquals(res, ref, "(ref: " + Arrays.toString(ref)
1094               + ", res: " + Arrays.toString(res)
1095               + "), at index #" + i
1096               + ", at origin #" + origin);
1097         }
1098     }
1099 
1100     interface FLanePartBop {
1101         $type$[] apply($type$[] a, $type$[] b, int origin, int part, int idx);
1102     }
1103 
1104     static void assertArraysEquals($type$[] r, $type$[] a, $type$[] b, int origin, int part, FLanePartBop f) {
1105         int i = 0;
1106         try {
1107             for (; i < a.length; i += SPECIES.length()) {
1108                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
1109                   f.apply(a, b, origin, part, i));
1110             }
1111         } catch (AssertionError e) {
1112             $type$[] ref = f.apply(a, b, origin, part, i);
1113             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
1114             Assert.assertEquals(res, ref, "(ref: " + Arrays.toString(ref)
1115               + ", res: " + Arrays.toString(res)
1116               + "), at index #" + i
1117               + ", at origin #" + origin
1118               + ", with part #" + part);
1119         }
1120     }
1121 
1122     interface FLanePartMaskedBop {
1123         $type$[] apply($type$[] a, $type$[] b, int origin, int part, boolean[] mask, int idx);
1124     }
1125 
1126     static void assertArraysEquals($type$[] r, $type$[] a, $type$[] b, int origin, int part, boolean[] mask, FLanePartMaskedBop f) {
1127         int i = 0;
1128         try {
1129             for (; i < a.length; i += SPECIES.length()) {
1130                 Assert.assertEquals(Arrays.copyOfRange(r, i, i+SPECIES.length()),
1131                   f.apply(a, b, origin, part, mask, i));
1132             }
1133         } catch (AssertionError e) {
1134             $type$[] ref = f.apply(a, b, origin, part, mask, i);
1135             $type$[] res = Arrays.copyOfRange(r, i, i+SPECIES.length());
1136             Assert.assertEquals(res, ref, "(ref: " + Arrays.toString(ref)
1137               + ", res: " + Arrays.toString(res)
1138               + "), at index #" + i
1139               + ", at origin #" + origin
1140               + ", with part #" + part);
1141         }
1142     }
1143 
1144 #if[!Int]
1145 #if[!byteOrShort]
1146     static int intCornerCaseValue(int i) {
1147         switch(i % 5) {
1148             case 0:
1149                 return Integer.MAX_VALUE;
1150             case 1:
1151                 return Integer.MIN_VALUE;
1152             case 2:
1153                 return Integer.MIN_VALUE;
1154             case 3:
1155                 return Integer.MAX_VALUE;
1156             default:
1157                 return (int)0;
1158         }
1159     }
1160 
1161     static final List<IntFunction<$type$[]>> INT_$TYPE$_GENERATORS = List.of(
1162             withToString("$type$[-i * 5]", (int s) -> {
1163                 return fill(s * BUFFER_REPS,
1164                             i -> ($type$)(-i * 5));
1165             }),
1166             withToString("$type$[i * 5]", (int s) -> {
1167                 return fill(s * BUFFER_REPS,
1168                             i -> ($type$)(i * 5));
1169             }),
1170             withToString("$type$[i + 1]", (int s) -> {
1171                 return fill(s * BUFFER_REPS,
1172                             i -> ((($type$)(i + 1) == 0) ? 1 : ($type$)(i + 1)));
1173             }),
1174             withToString("$type$[intCornerCaseValue(i)]", (int s) -> {
1175                 return fill(s * BUFFER_REPS,
1176                             i -> ($type$)intCornerCaseValue(i));
1177             })
1178     );
1179 #end[!byteOrShort]
1180 #end[!Int]
1181 
1182     static void assertArraysEquals(int[] r, $type$[] a, int offs) {
1183         int i = 0;
1184         try {
1185             for (; i < r.length; i++) {
1186                 Assert.assertEquals(r[i], (int)(a[i+offs]));
1187             }
1188         } catch (AssertionError e) {
1189             Assert.assertEquals(r[i], (int)(a[i+offs]), "at index #" + i + ", input = " + a[i+offs]);
1190         }
1191     }
1192 
1193 #if[!Long]
1194 #if[FP]
1195     static long longCornerCaseValue(int i) {
1196         switch(i % 5) {
1197             case 0:
1198                 return Long.MAX_VALUE;
1199             case 1:
1200                 return Long.MIN_VALUE;
1201             case 2:
1202                 return Long.MIN_VALUE;
1203             case 3:
1204                 return Long.MAX_VALUE;
1205             default:
1206                 return (long)0;
1207         }
1208     }
1209 
1210     static final List<IntFunction<$type$[]>> LONG_$TYPE$_GENERATORS = List.of(
1211             withToString("$type$[-i * 5]", (int s) -> {
1212                 return fill(s * BUFFER_REPS,
1213                             i -> ($type$)(-i * 5));
1214             }),
1215             withToString("$type$[i * 5]", (int s) -> {
1216                 return fill(s * BUFFER_REPS,
1217                             i -> ($type$)(i * 5));
1218             }),
1219             withToString("$type$[i + 1]", (int s) -> {
1220                 return fill(s * BUFFER_REPS,
1221                             i -> ((($type$)(i + 1) == 0) ? 1 : ($type$)(i + 1)));
1222             }),
1223             withToString("$type$[cornerCaseValue(i)]", (int s) -> {
1224                 return fill(s * BUFFER_REPS,
1225                             i -> ($type$)longCornerCaseValue(i));
1226             })
1227     );
1228 #end[FP]
1229 #end[!Long]
1230 
1231 #if[byte]
1232     static void assertArraysEquals($type$[] r, $type$[] a, int offs) {
1233         int i = 0;
1234         try {
1235             for (; i < r.length; i++) {
1236                 Assert.assertEquals(r[i], (long)(a[i+offs]));
1237             }
1238         } catch (AssertionError e) {
1239             Assert.assertEquals(r[i], (long)(a[i+offs]), "at index #" + i + ", input = " + a[i+offs]);
1240         }
1241     }
1242 #end[byte]
1243 
1244     static void assertArraysEquals(long[] r, $type$[] a, int offs) {
1245         int i = 0;
1246         try {
1247             for (; i < r.length; i++) {
1248                 Assert.assertEquals(r[i], (long)(a[i+offs]));
1249             }
1250         } catch (AssertionError e) {
1251             Assert.assertEquals(r[i], (long)(a[i+offs]), "at index #" + i + ", input = " + a[i+offs]);
1252         }
1253     }
1254 #if[!Double]
1255 
1256     static void assertArraysEquals(double[] r, $type$[] a, int offs) {
1257         int i = 0;
1258         try {
1259             for (; i < r.length; i++) {
1260                 Assert.assertEquals(r[i], (double)(a[i+offs]));
1261             }
1262         } catch (AssertionError e) {
1263             Assert.assertEquals(r[i], (double)(a[i+offs]), "at index #" + i + ", input = " + a[i+offs]);
1264         }
1265     }
1266 #end[!Double]
1267 
1268     static $bitstype$ bits($type$ e) {
1269         return {#if[FP]? $Type$.$type$To$Bitstype$Bits(e): e};
1270     }
1271 
1272     static final List<IntFunction<$type$[]>> $TYPE$_GENERATORS = List.of(
1273             withToString("$type$[-i * 5]", (int s) -> {
1274                 return fill(s * BUFFER_REPS,
1275                             i -> ($type$)(-i * 5));
1276             }),
1277             withToString("$type$[i * 5]", (int s) -> {
1278                 return fill(s * BUFFER_REPS,
1279                             i -> ($type$)(i * 5));
1280             }),
1281             withToString("$type$[i + 1]", (int s) -> {
1282                 return fill(s * BUFFER_REPS,
1283                             i -> ((($type$)(i + 1) == 0) ? 1 : ($type$)(i + 1)));
1284             }),
1285 #if[FP]
1286             withToString("$type$[0.01 + (i / (i + 1))]", (int s) -> {
1287                 return fill(s * BUFFER_REPS,
1288                             i -> ($type$)0.01 + (($type$)i / (i + 1)));
1289             }),
1290             withToString("$type$[i -> i % 17 == 0 ? cornerCaseValue(i) : 0.01 + (i / (i + 1))]", (int s) -> {
1291                 return fill(s * BUFFER_REPS,
1292                             i -> i % 17 == 0 ? cornerCaseValue(i) : ($type$)0.01 + (($type$)i / (i + 1)));
1293             }),
1294 #end[FP]
1295             withToString("$type$[cornerCaseValue(i)]", (int s) -> {
1296                 return fill(s * BUFFER_REPS,
1297                             i -> cornerCaseValue(i));
1298             })
1299     );
1300 
1301 #if[!FP]
1302     static final List<IntFunction<$type$[]>> $TYPE$_SATURATING_GENERATORS = List.of(
1303             withToString("$type$[$Boxtype$.MIN_VALUE]", (int s) -> {
1304                 return fill(s * BUFFER_REPS,
1305                             i -> ($type$)($Boxtype$.MIN_VALUE));
1306             }),
1307             withToString("$type$[$Boxtype$.MAX_VALUE]", (int s) -> {
1308                 return fill(s * BUFFER_REPS,
1309                             i -> ($type$)($Boxtype$.MAX_VALUE));
1310             }),
1311             withToString("$type$[$Boxtype$.MAX_VALUE - 100]", (int s) -> {
1312                 return fill(s * BUFFER_REPS,
1313                             i -> ($type$)($Boxtype$.MAX_VALUE - 100));
1314             }),
1315             withToString("$type$[$Boxtype$.MIN_VALUE + 100]", (int s) -> {
1316                 return fill(s * BUFFER_REPS,
1317                             i -> ($type$)($Boxtype$.MIN_VALUE + 100));
1318             }),
1319             withToString("$type$[-i * 5]", (int s) -> {
1320                 return fill(s * BUFFER_REPS,
1321                             i -> ($type$)(-i * 5));
1322             }),
1323             withToString("$type$[i * 5]", (int s) -> {
1324                 return fill(s * BUFFER_REPS,
1325                             i -> ($type$)(i * 5));
1326             })
1327     );
1328 
1329     static final List<IntFunction<$type$[]>> $TYPE$_SATURATING_GENERATORS_ASSOC = List.of(
1330             withToString("$type$[$Boxtype$.MAX_VALUE]", (int s) -> {
1331                 return fill(s * BUFFER_REPS,
1332                             i -> ($type$)($Boxtype$.MAX_VALUE));
1333             }),
1334             withToString("$type$[$Boxtype$.MAX_VALUE - 100]", (int s) -> {
1335                 return fill(s * BUFFER_REPS,
1336                             i -> ($type$)($Boxtype$.MAX_VALUE - 100));
1337             }),
1338             withToString("$type$[-1]", (int s) -> {
1339                 return fill(s * BUFFER_REPS,
1340                             i -> ($type$)(-1));
1341             })
1342     );
1343 
1344 #end[!FP]
1345     // Create combinations of pairs
1346     // @@@ Might be sensitive to order e.g. div by 0
1347     static final List<List<IntFunction<$type$[]>>> $TYPE$_GENERATOR_PAIRS =
1348         Stream.of($TYPE$_GENERATORS.get(0)).
1349                 flatMap(fa -> $TYPE$_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))).
1350                 collect(Collectors.toList());
1351 
1352 #if[!FP]
1353     static final List<List<IntFunction<$type$[]>>> $TYPE$_SATURATING_GENERATOR_PAIRS =
1354         Stream.of($TYPE$_GENERATORS.get(0)).
1355                 flatMap(fa -> $TYPE$_SATURATING_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))).
1356                 collect(Collectors.toList());
1357 
1358     static final List<List<IntFunction<$type$[]>>> $TYPE$_SATURATING_GENERATOR_TRIPLETS =
1359             Stream.of($TYPE$_GENERATORS.get(1))
1360                     .flatMap(fa -> $TYPE$_SATURATING_GENERATORS_ASSOC.stream().map(fb -> List.of(fa, fb)))
1361                     .flatMap(pair -> $TYPE$_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f)))
1362                     .collect(Collectors.toList());
1363 
1364 #end[!FP]
1365     @DataProvider
1366     public Object[][] boolUnaryOpProvider() {
1367         return BOOL_ARRAY_GENERATORS.stream().
1368                 map(f -> new Object[]{f}).
1369                 toArray(Object[][]::new);
1370     }
1371 
1372     static final List<List<IntFunction<$type$[]>>> $TYPE$_GENERATOR_TRIPLES =
1373         $TYPE$_GENERATOR_PAIRS.stream().
1374                 flatMap(pair -> $TYPE$_GENERATORS.stream().map(f -> List.of(pair.get(0), pair.get(1), f))).
1375                 collect(Collectors.toList());
1376 
1377     static final List<IntFunction<$type$[]>> SELECT_FROM_INDEX_GENERATORS = List.of(
1378             withToString("$type$[0..VECLEN*2)", (int s) -> {
1379                 return fill(s * BUFFER_REPS,
1380                             i -> ($type$)(RAND.nextInt()));
1381             })
1382     );
1383 
1384     static final List<List<IntFunction<$type$[]>>> $TYPE$_GENERATOR_SELECT_FROM_TRIPLES =
1385         $TYPE$_GENERATOR_PAIRS.stream().
1386                 flatMap(pair -> SELECT_FROM_INDEX_GENERATORS.stream().map(f -> List.of(pair.get(0), pair.get(1), f))).
1387                 collect(Collectors.toList());
1388 
1389     @DataProvider
1390     public Object[][] $type$BinaryOpProvider() {
1391         return $TYPE$_GENERATOR_PAIRS.stream().map(List::toArray).
1392                 toArray(Object[][]::new);
1393     }
1394 
1395 #if[!FP]
1396     @DataProvider
1397     public Object[][] $type$SaturatingBinaryOpProvider() {
1398         return $TYPE$_SATURATING_GENERATOR_PAIRS.stream().map(List::toArray).
1399                 toArray(Object[][]::new);
1400     }
1401 
1402     @DataProvider
1403     public Object[][] $type$SaturatingBinaryOpAssocProvider() {
1404         return $TYPE$_SATURATING_GENERATOR_TRIPLETS.stream().map(List::toArray).
1405                 toArray(Object[][]::new);
1406     }
1407 
1408     @DataProvider
1409     public Object[][] $type$SaturatingBinaryOpAssocMaskProvider() {
1410         return BOOLEAN_MASK_GENERATORS.stream().
1411                 flatMap(fm -> $TYPE$_SATURATING_GENERATOR_TRIPLETS.stream().map(lfa -> {
1412                     return Stream.concat(lfa.stream(), Stream.of(fm)).toArray();
1413                 })).
1414                 toArray(Object[][]::new);
1415     }
1416 
1417 
1418 #end[!FP]
1419     @DataProvider
1420     public Object[][] $type$IndexedOpProvider() {
1421         return $TYPE$_GENERATOR_PAIRS.stream().map(List::toArray).
1422                 toArray(Object[][]::new);
1423     }
1424 
1425 #if[!FP]
1426     @DataProvider
1427     public Object[][] $type$SaturatingBinaryOpMaskProvider() {
1428         return BOOLEAN_MASK_GENERATORS.stream().
1429                 flatMap(fm -> $TYPE$_SATURATING_GENERATOR_PAIRS.stream().map(lfa -> {
1430                     return Stream.concat(lfa.stream(), Stream.of(fm)).toArray();
1431                 })).
1432                 toArray(Object[][]::new);
1433     }
1434 
1435    @DataProvider
1436    public Object[][] $type$SaturatingUnaryOpProvider() {
1437        return $TYPE$_SATURATING_GENERATORS.stream().
1438                     map(f -> new Object[]{f}).
1439                     toArray(Object[][]::new);
1440    }
1441 
1442    @DataProvider
1443    public Object[][] $type$SaturatingUnaryOpMaskProvider() {
1444         return BOOLEAN_MASK_GENERATORS.stream().
1445                 flatMap(fm -> $TYPE$_SATURATING_GENERATORS.stream().map(fa -> {
1446                     return new Object[] {fa, fm};
1447                 })).
1448                 toArray(Object[][]::new);
1449    }
1450 
1451 #end[!FP]
1452     @DataProvider
1453     public Object[][] $type$BinaryOpMaskProvider() {
1454         return BOOLEAN_MASK_GENERATORS.stream().
1455                 flatMap(fm -> $TYPE$_GENERATOR_PAIRS.stream().map(lfa -> {
1456                     return Stream.concat(lfa.stream(), Stream.of(fm)).toArray();
1457                 })).
1458                 toArray(Object[][]::new);
1459     }
1460 
1461     @DataProvider
1462     public Object[][] $type$TernaryOpProvider() {
1463         return $TYPE$_GENERATOR_TRIPLES.stream().map(List::toArray).
1464                 toArray(Object[][]::new);
1465     }
1466 
1467     @DataProvider
1468     public Object[][] $type$SelectFromTwoVectorOpProvider() {
1469         return $TYPE$_GENERATOR_SELECT_FROM_TRIPLES.stream().map(List::toArray).
1470                 toArray(Object[][]::new);
1471     }
1472 
1473     @DataProvider
1474     public Object[][] $type$TernaryOpMaskProvider() {
1475         return BOOLEAN_MASK_GENERATORS.stream().
1476                 flatMap(fm -> $TYPE$_GENERATOR_TRIPLES.stream().map(lfa -> {
1477                     return Stream.concat(lfa.stream(), Stream.of(fm)).toArray();
1478                 })).
1479                 toArray(Object[][]::new);
1480     }
1481 
1482     @DataProvider
1483     public Object[][] $type$UnaryOpProvider() {
1484         return $TYPE$_GENERATORS.stream().
1485                 map(f -> new Object[]{f}).
1486                 toArray(Object[][]::new);
1487     }
1488 
1489     @DataProvider
1490     public Object[][] $type$UnaryOpMaskProvider() {
1491         return BOOLEAN_MASK_GENERATORS.stream().
1492                 flatMap(fm -> $TYPE$_GENERATORS.stream().map(fa -> {
1493                     return new Object[] {fa, fm};
1494                 })).
1495                 toArray(Object[][]::new);
1496     }
1497 #if[!Int]
1498 #if[!byteOrShort]
1499 
1500     @DataProvider
1501     public Object[][] $type$toIntUnaryOpProvider() {
1502         return INT_$TYPE$_GENERATORS.stream().
1503                 map(f -> new Object[]{f}).
1504                 toArray(Object[][]::new);
1505     }
1506 #end[!byteOrShort]
1507 #end[!Int]
1508 #if[FP]
1509 
1510     @DataProvider
1511     public Object[][] $type$toLongUnaryOpProvider() {
1512         return LONG_$TYPE$_GENERATORS.stream().
1513                 map(f -> new Object[]{f}).
1514                 toArray(Object[][]::new);
1515     }
1516 #end[FP]
1517 
1518     @DataProvider
1519     public Object[][] maskProvider() {
1520         return BOOLEAN_MASK_GENERATORS.stream().
1521                 map(f -> new Object[]{f}).
1522                 toArray(Object[][]::new);
1523     }
1524 
1525     @DataProvider
1526     public Object[][] maskCompareOpProvider() {
1527         return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray).
1528                 toArray(Object[][]::new);
1529     }
1530 
1531     @DataProvider
1532     public Object[][] shuffleProvider() {
1533         return INT_SHUFFLE_GENERATORS.stream().
1534                 map(f -> new Object[]{f}).
1535                 toArray(Object[][]::new);
1536     }
1537 
1538     @DataProvider
1539     public Object[][] shuffleCompareOpProvider() {
1540         return INT_SHUFFLE_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray).
1541                 toArray(Object[][]::new);
1542     }
1543 
1544     @DataProvider
1545     public Object[][] $type$UnaryOpShuffleProvider() {
1546         return INT_SHUFFLE_GENERATORS.stream().
1547                 flatMap(fs -> $TYPE$_GENERATORS.stream().map(fa -> {
1548                     return new Object[] {fa, fs};
1549                 })).
1550                 toArray(Object[][]::new);
1551     }
1552 
1553     @DataProvider
1554     public Object[][] $type$UnaryOpShuffleMaskProvider() {
1555         return BOOLEAN_MASK_GENERATORS.stream().
1556                 flatMap(fm -> INT_SHUFFLE_GENERATORS.stream().
1557                     flatMap(fs -> $TYPE$_GENERATORS.stream().map(fa -> {
1558                         return new Object[] {fa, fs, fm};
1559                 }))).
1560                 toArray(Object[][]::new);
1561     }
1562 #if[!Int]
1563 
1564     static final List<BiFunction<Integer,Integer,$type$[]>> $TYPE$_SHUFFLE_GENERATORS = List.of(
1565             withToStringBi("shuffle[random]", (Integer l, Integer m) -> {
1566                 $type$[] a = new $type$[l];
1567 #if[ByteMax]
1568                 int upper = Math.min(Byte.MAX_VALUE + 1, m);
1569 #else[ByteMax]
1570                 int upper = m;
1571 #end[ByteMax]
1572                 for (int i = 0; i < 1; i++) {
1573                     a[i] = ($type$)RAND.nextInt(upper);
1574                 }
1575                 return a;
1576             })
1577     );
1578 
1579     @DataProvider
1580     public Object[][] $type$UnaryOpSelectFromProvider() {
1581         return $TYPE$_SHUFFLE_GENERATORS.stream().
1582                 flatMap(fs -> $TYPE$_GENERATORS.stream().map(fa -> {
1583                     return new Object[] {fa, fs};
1584                 })).
1585                 toArray(Object[][]::new);
1586     }
1587 
1588     @DataProvider
1589     public Object[][] $type$UnaryOpSelectFromMaskProvider() {
1590         return BOOLEAN_MASK_GENERATORS.stream().
1591                 flatMap(fm -> $TYPE$_SHUFFLE_GENERATORS.stream().
1592                     flatMap(fs -> $TYPE$_GENERATORS.stream().map(fa -> {
1593                         return new Object[] {fa, fs, fm};
1594                 }))).
1595                 toArray(Object[][]::new);
1596     }
1597 #end[!Int]
1598 
1599     static final List<IntFunction<$type$[]>> $TYPE$_COMPARE_GENERATORS = List.of(
1600             withToString("$type$[i]", (int s) -> {
1601                 return fill(s * BUFFER_REPS,
1602                             i -> ($type$)i);
1603             }),
1604             withToString("$type$[i - length / 2]", (int s) -> {
1605                 return fill(s * BUFFER_REPS,
1606                             i -> ($type$)(i - (s * BUFFER_REPS / 2)));
1607             }),
1608             withToString("$type$[i + 1]", (int s) -> {
1609                 return fill(s * BUFFER_REPS,
1610                             i -> ($type$)(i + 1));
1611             }),
1612             withToString("$type$[i - 2]", (int s) -> {
1613                 return fill(s * BUFFER_REPS,
1614                             i -> ($type$)(i - 2));
1615             }),
1616             withToString("$type$[zigZag(i)]", (int s) -> {
1617                 return fill(s * BUFFER_REPS,
1618                             i -> i%3 == 0 ? ($type$)i : (i%3 == 1 ? ($type$)(i + 1) : ($type$)(i - 2)));
1619             }),
1620             withToString("$type$[cornerCaseValue(i)]", (int s) -> {
1621                 return fill(s * BUFFER_REPS,
1622                             i -> cornerCaseValue(i));
1623             })
1624     );
1625 
1626     static final List<List<IntFunction<$type$[]>>> $TYPE$_TEST_GENERATOR_ARGS =
1627         $TYPE$_COMPARE_GENERATORS.stream().
1628                 map(fa -> List.of(fa)).
1629                 collect(Collectors.toList());
1630 
1631     @DataProvider
1632     public Object[][] $type$TestOpProvider() {
1633         return $TYPE$_TEST_GENERATOR_ARGS.stream().map(List::toArray).
1634                 toArray(Object[][]::new);
1635     }
1636 
1637     @DataProvider
1638     public Object[][] $type$TestOpMaskProvider() {
1639         return BOOLEAN_MASK_GENERATORS.stream().
1640                 flatMap(fm -> $TYPE$_TEST_GENERATOR_ARGS.stream().map(lfa -> {
1641                     return Stream.concat(lfa.stream(), Stream.of(fm)).toArray();
1642                 })).
1643                 toArray(Object[][]::new);
1644     }
1645 
1646     static final List<List<IntFunction<$type$[]>>> $TYPE$_COMPARE_GENERATOR_PAIRS =
1647         $TYPE$_COMPARE_GENERATORS.stream().
1648                 flatMap(fa -> $TYPE$_COMPARE_GENERATORS.stream().map(fb -> List.of(fa, fb))).
1649                 collect(Collectors.toList());
1650 
1651     @DataProvider
1652     public Object[][] $type$CompareOpProvider() {
1653         return $TYPE$_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray).
1654                 toArray(Object[][]::new);
1655     }
1656 
1657     @DataProvider
1658     public Object[][] $type$CompareOpMaskProvider() {
1659         return BOOLEAN_MASK_GENERATORS.stream().
1660                 flatMap(fm -> $TYPE$_COMPARE_GENERATOR_PAIRS.stream().map(lfa -> {
1661                     return Stream.concat(lfa.stream(), Stream.of(fm)).toArray();
1662                 })).
1663                 toArray(Object[][]::new);
1664     }
1665 
1666     interface To$Type$F {
1667         $type$ apply(int i);
1668     }
1669 
1670     static $type$[] fill(int s , To$Type$F f) {
1671         return fill(new $type$[s], f);
1672     }
1673 
1674     static $type$[] fill($type$[] a, To$Type$F f) {
1675         for (int i = 0; i < a.length; i++) {
1676             a[i] = f.apply(i);
1677         }
1678         return a;
1679     }
1680 
1681     static $type$ cornerCaseValue(int i) {
1682 #if[FP]
1683         return switch(i % 8) {
1684             case 0  -> $Wideboxtype$.MAX_VALUE;
1685             case 1  -> $Wideboxtype$.MIN_VALUE;
1686             case 2  -> $Wideboxtype$.NEGATIVE_INFINITY;
1687             case 3  -> $Wideboxtype$.POSITIVE_INFINITY;
1688             case 4  -> $Wideboxtype$.NaN;
1689 #if[Float]
1690             case 5  -> Float.intBitsToFloat(0x7F812345);
1691 #else[Float]
1692             case 5  -> Double.longBitsToDouble(0x7FF123456789ABCDL);
1693 #end[Float]
1694             case 6  -> ($type$)0.0;
1695             default -> ($type$)-0.0;
1696         };
1697 #else[FP]
1698         switch(i % 5) {
1699             case 0:
1700                 return $Wideboxtype$.MAX_VALUE;
1701             case 1:
1702                 return $Wideboxtype$.MIN_VALUE;
1703             case 2:
1704                 return $Wideboxtype$.MIN_VALUE;
1705             case 3:
1706                 return $Wideboxtype$.MAX_VALUE;
1707             default:
1708                 return ($type$)0;
1709         }
1710 #end[FP]
1711     }
1712 
1713     static final IntFunction<$type$[]> fr = (vl) -> {
1714         int length = BUFFER_REPS * vl;
1715         return new $type$[length];
1716     };
1717 
1718     static final IntFunction<boolean[]> fmr = (vl) -> {
1719         int length = BUFFER_REPS * vl;
1720         return new boolean[length];
1721     };
1722 #if[!Long]
1723 
1724     static final IntFunction<long[]> lfr = (vl) -> {
1725         int length = BUFFER_REPS * vl;
1726         return new long[length];
1727     };
1728 #end[!Long]
1729 #if[BITWISE]
1730 
1731     static void replaceZero($type$[] a, $type$ v) {
1732         for (int i = 0; i < a.length; i++) {
1733             if (a[i] == 0) {
1734                 a[i] = v;
1735             }
1736         }
1737     }
1738 
1739     static void replaceZero($type$[] a, boolean[] mask, $type$ v) {
1740         for (int i = 0; i < a.length; i++) {
1741             if (mask[i % mask.length] && a[i] == 0) {
1742                 a[i] = v;
1743             }
1744         }
1745     }
1746 
1747     static $type$ ROL_scalar($type$ a, $type$ b) {
1748 #if[intOrLong]
1749         return $Wideboxtype$.rotateLeft(a, ((int)b));
1750 #else[intOrLong]
1751 #if[short]
1752         return (short)(((((short)a) & 0xFFFF) << (b & 15)) | ((((short)a) & 0xFFFF) >>> (16 - (b & 15))));
1753 #else[short]
1754         return (byte)(((((byte)a) & 0xFF) << (b & 7)) | ((((byte)a) & 0xFF) >>> (8 - (b & 7))));
1755 #end[short]
1756 #end[intOrLong]
1757     }
1758 
1759     static $type$ ROR_scalar($type$ a, $type$ b) {
1760 #if[intOrLong]
1761         return $Wideboxtype$.rotateRight(a, ((int)b));
1762 #else[intOrLong]
1763 #if[short]
1764         return (short)(((((short)a) & 0xFFFF) >>> (b & 15)) | ((((short)a) & 0xFFFF) << (16 - (b & 15))));
1765 #else[short]
1766         return (byte)(((((byte)a) & 0xFF) >>> (b & 7)) | ((((byte)a) & 0xFF) << (8 - (b & 7))));
1767 #end[short]
1768 #end[intOrLong]
1769     }
1770 
1771     static $type$ TRAILING_ZEROS_COUNT_scalar($type$ a) {
1772 #if[intOrLong]
1773         return $Wideboxtype$.numberOfTrailingZeros(a);
1774 #else[intOrLong]
1775 #if[short]
1776         return (short) (a != 0 ? Integer.numberOfTrailingZeros(a) : 16);
1777 #else[short]
1778         return (byte) (a != 0 ? Integer.numberOfTrailingZeros(a) : 8);
1779 #end[short]
1780 #end[intOrLong]
1781     }
1782 
1783     static $type$ LEADING_ZEROS_COUNT_scalar($type$ a) {
1784 #if[intOrLong]
1785         return $Wideboxtype$.numberOfLeadingZeros(a);
1786 #else[intOrLong]
1787 #if[short]
1788         return (short) (a >= 0 ? Integer.numberOfLeadingZeros(a) - 16 : 0);
1789 #else[short]
1790         return (byte) (a >= 0 ? Integer.numberOfLeadingZeros(a) - 24 : 0);
1791 #end[short]
1792 #end[intOrLong]
1793     }
1794 
1795     static $type$ REVERSE_scalar($type$ a) {
1796 #if[intOrLong]
1797         return $Wideboxtype$.reverse(a);
1798 #else[intOrLong]
1799 #if[short]
1800         $type$ b = ROL_scalar(a, ($type$) 8);
1801         b = (short) (((b & 0x5555) << 1) | ((b & 0xAAAA) >>> 1));
1802         b = (short) (((b & 0x3333) << 2) | ((b & 0xCCCC) >>> 2));
1803         b = (short) (((b & 0x0F0F) << 4) | ((b & 0xF0F0) >>> 4));
1804         return b;
1805 #else[short]
1806         $type$ b = ($type$) ROL_scalar(a, ($type$) 4);
1807         b = (byte) (((b & 0x55) << 1) | ((b & 0xAA) >>> 1));
1808         b = (byte) (((b & 0x33) << 2) | ((b & 0xCC) >>> 2));
1809         return b;
1810 #end[short]
1811 #end[intOrLong]
1812     }
1813 #end[BITWISE]
1814 
1815     static boolean eq($type$ a, $type$ b) {
1816         return a == b;
1817     }
1818 
1819     static boolean neq($type$ a, $type$ b) {
1820         return a != b;
1821     }
1822 
1823     static boolean lt($type$ a, $type$ b) {
1824         return a < b;
1825     }
1826 
1827     static boolean le($type$ a, $type$ b) {
1828         return a <= b;
1829     }
1830 
1831     static boolean gt($type$ a, $type$ b) {
1832         return a > b;
1833     }
1834 
1835     static boolean ge($type$ a, $type$ b) {
1836         return a >= b;
1837     }
1838 #if[!FP]
1839 
1840     static boolean ult($type$ a, $type$ b) {
1841         return $Boxtype$.compareUnsigned(a, b) < 0;
1842     }
1843 
1844     static boolean ule($type$ a, $type$ b) {
1845         return $Boxtype$.compareUnsigned(a, b) <= 0;
1846     }
1847 
1848     static boolean ugt($type$ a, $type$ b) {
1849         return $Boxtype$.compareUnsigned(a, b) > 0;
1850     }
1851 
1852     static boolean uge($type$ a, $type$ b) {
1853         return $Boxtype$.compareUnsigned(a, b) >= 0;
1854     }
1855 #end[!FP]
1856 
1857     static $type$ firstNonZero($type$ a, $type$ b) {
1858         return $Boxtype$.compare(a, ($type$) 0) != 0 ? a : b;
1859     }
1860 
1861     @Test
1862     static void smokeTest1() {
1863         $abstractvectortype$ three = $abstractvectortype$.broadcast(SPECIES, (byte)-3);
1864         $abstractvectortype$ three2 = ($abstractvectortype$) SPECIES.broadcast(-3);
1865         assert(three.eq(three2).allTrue());
1866         $abstractvectortype$ three3 = three2.broadcast(1).broadcast(-3);
1867         assert(three.eq(three3).allTrue());
1868         int scale = 2;
1869         Class<?> ETYPE = $type$.class;
1870         if (ETYPE == double.class || ETYPE == long.class)
1871             scale = 1000000;
1872         else if (ETYPE == byte.class && SPECIES.length() >= 64)
1873             scale = 1;
1874         $abstractvectortype$ higher = three.addIndex(scale);
1875         VectorMask<$Boxtype$> m = three.compare(VectorOperators.LE, higher);
1876         assert(m.allTrue());
1877         m = higher.min(($type$)-1).test(VectorOperators.IS_NEGATIVE);
1878         assert(m.allTrue());
1879 #if[FP]
1880         m = higher.test(VectorOperators.IS_FINITE);
1881         assert(m.allTrue());
1882 #end[FP]
1883         $type$ max = higher.reduceLanes(VectorOperators.MAX);
1884         assert(max == -3 + scale * (SPECIES.length()-1));
1885     }
1886 
1887     private static $type$[]
1888     bothToArray($abstractvectortype$ a, $abstractvectortype$ b) {
1889         $type$[] r = new $type$[a.length() + b.length()];
1890         a.intoArray(r, 0);
1891         b.intoArray(r, a.length());
1892         return r;
1893     }
1894 
1895     @Test
1896     static void smokeTest2() {
1897         // Do some zipping and shuffling.
1898         $abstractvectortype$ io = ($abstractvectortype$) SPECIES.broadcast(0).addIndex(1);
1899         $abstractvectortype$ io2 = ($abstractvectortype$) VectorShuffle.iota(SPECIES,0,1,false).toVector();
1900         Assert.assertEquals(io, io2);
1901         $abstractvectortype$ a = io.add(($type$)1); //[1,2]
1902         $abstractvectortype$ b = a.neg();  //[-1,-2]
1903         $type$[] abValues = bothToArray(a,b); //[1,2,-1,-2]
1904         VectorShuffle<$Boxtype$> zip0 = VectorShuffle.makeZip(SPECIES, 0);
1905         VectorShuffle<$Boxtype$> zip1 = VectorShuffle.makeZip(SPECIES, 1);
1906         $abstractvectortype$ zab0 = a.rearrange(zip0,b); //[1,-1]
1907         $abstractvectortype$ zab1 = a.rearrange(zip1,b); //[2,-2]
1908         $type$[] zabValues = bothToArray(zab0, zab1); //[1,-1,2,-2]
1909         // manually zip
1910         $type$[] manual = new $type$[zabValues.length];
1911         for (int i = 0; i < manual.length; i += 2) {
1912             manual[i+0] = abValues[i/2];
1913             manual[i+1] = abValues[a.length() + i/2];
1914         }
1915         Assert.assertEquals(Arrays.toString(zabValues), Arrays.toString(manual));
1916         VectorShuffle<$Boxtype$> unz0 = VectorShuffle.makeUnzip(SPECIES, 0);
1917         VectorShuffle<$Boxtype$> unz1 = VectorShuffle.makeUnzip(SPECIES, 1);
1918         $abstractvectortype$ uab0 = zab0.rearrange(unz0,zab1);
1919         $abstractvectortype$ uab1 = zab0.rearrange(unz1,zab1);
1920         $type$[] abValues1 = bothToArray(uab0, uab1);
1921         Assert.assertEquals(Arrays.toString(abValues), Arrays.toString(abValues1));
1922     }
1923 
1924     static void iotaShuffle() {
1925         $abstractvectortype$ io = ($abstractvectortype$) SPECIES.broadcast(0).addIndex(1);
1926         $abstractvectortype$ io2 = ($abstractvectortype$) VectorShuffle.iota(SPECIES, 0 , 1, false).toVector();
1927         Assert.assertEquals(io, io2);
1928     }
1929 
1930     @Test
1931     // Test all shuffle related operations.
1932     static void shuffleTest() {
1933         // To test backend instructions, make sure that C2 is used.
1934         for (int loop = 0; loop < INVOC_COUNT * INVOC_COUNT; loop++) {
1935             iotaShuffle();
1936         }
1937     }
1938 
1939     @Test
1940     void viewAsIntegeralLanesTest() {
1941 #if[FP]
1942         Vector<?> asIntegral = SPECIES.zero().viewAsIntegralLanes();
1943         VectorSpecies<?> asIntegralSpecies = asIntegral.species();
1944         Assert.assertNotEquals(asIntegralSpecies.elementType(), SPECIES.elementType());
1945         Assert.assertEquals(asIntegralSpecies.vectorShape(), SPECIES.vectorShape());
1946         Assert.assertEquals(asIntegralSpecies.length(), SPECIES.length());
1947         Assert.assertEquals(asIntegral.viewAsFloatingLanes().species(), SPECIES);
1948 #else[FP]
1949         Vector<?> asIntegral = SPECIES.zero().viewAsIntegralLanes();
1950         Assert.assertEquals(asIntegral.species(), SPECIES);
1951 #end[FP]
1952     }
1953 #if[FP]
1954 
1955     @Test
1956     void viewAsFloatingLanesTest() {
1957         Vector<?> asFloating = SPECIES.zero().viewAsFloatingLanes();
1958         Assert.assertEquals(asFloating.species(), SPECIES);
1959     }
1960 #else[FP]
1961 #if[byteOrShort]
1962 
1963     @Test(expectedExceptions = UnsupportedOperationException.class)
1964     void viewAsFloatingLanesTest() {
1965         SPECIES.zero().viewAsFloatingLanes();
1966     }
1967 #else[byteOrShort]
1968 
1969     @Test
1970     void viewAsFloatingLanesTest() {
1971         Vector<?> asFloating = SPECIES.zero().viewAsFloatingLanes();
1972         VectorSpecies<?> asFloatingSpecies = asFloating.species();
1973         Assert.assertNotEquals(asFloatingSpecies.elementType(), SPECIES.elementType());
1974         Assert.assertEquals(asFloatingSpecies.vectorShape(), SPECIES.vectorShape());
1975         Assert.assertEquals(asFloatingSpecies.length(), SPECIES.length());
1976         Assert.assertEquals(asFloating.viewAsIntegralLanes().species(), SPECIES);
1977     }
1978 #end[byteOrShort]
1979 #end[FP]
1980 #if[BITWISE]
1981 
1982     @Test
1983     // Test div by 0.
1984     static void bitwiseDivByZeroSmokeTest() {
1985         try {
1986             $abstractvectortype$ a = ($abstractvectortype$) SPECIES.broadcast(0).addIndex(1);
1987             $abstractvectortype$ b = ($abstractvectortype$) SPECIES.broadcast(0);
1988             a.div(b);
1989             Assert.fail();
1990         } catch (ArithmeticException e) {
1991         }
1992 
1993         try {
1994             $abstractvectortype$ a = ($abstractvectortype$) SPECIES.broadcast(0).addIndex(1);
1995             $abstractvectortype$ b = ($abstractvectortype$) SPECIES.broadcast(0);
1996             VectorMask<$Boxtype$> m = a.lt(($type$) 1);
1997             a.div(b, m);
1998             Assert.fail();
1999         } catch (ArithmeticException e) {
2000         }
2001     }
2002 #end[BITWISE]