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