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