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