1 /* 2 * Copyright (c) 2018, 2021, 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.foreign jdk.incubator.vector java.base/jdk.internal.vm.annotation 27 * @run testng/othervm --add-opens jdk.incubator.vector/jdk.incubator.vector=ALL-UNNAMED 28 * -XX:-TieredCompilation FloatMaxVectorLoadStoreTests 29 * 30 */ 31 32 // -- This file was mechanically generated: Do not edit! -- // 33 34 import jdk.incubator.vector.FloatVector; 35 import jdk.incubator.vector.VectorMask; 36 import jdk.incubator.vector.VectorShape; 37 import jdk.incubator.vector.VectorSpecies; 38 import jdk.incubator.vector.VectorShuffle; 39 import jdk.internal.vm.annotation.DontInline; 40 import org.testng.Assert; 41 import org.testng.annotations.DataProvider; 42 import org.testng.annotations.Test; 43 44 import java.lang.invoke.MethodHandles; 45 import java.lang.invoke.VarHandle; 46 import java.nio.ByteBuffer; 47 import java.nio.FloatBuffer; 48 import java.nio.ByteOrder; 49 import java.nio.ReadOnlyBufferException; 50 import java.util.List; 51 import java.util.function.*; 52 53 @Test 54 public class FloatMaxVectorLoadStoreTests extends AbstractVectorLoadStoreTest { 55 static final VectorSpecies<Float> SPECIES = 56 FloatVector.SPECIES_MAX; 57 58 static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 100); 59 60 static VectorShape getMaxBit() { 61 return VectorShape.S_Max_BIT; 62 } 63 64 private static final int Max = 256; // juts so we can do N/Max 65 66 static final int BUFFER_REPS = Integer.getInteger("jdk.incubator.vector.test.buffer-vectors", 25000 / Max); 67 68 static void assertArraysEquals(float[] r, float[] a, boolean[] mask) { 69 int i = 0; 70 try { 71 for (; i < a.length; i++) { 72 Assert.assertEquals(r[i], mask[i % SPECIES.length()] ? a[i] : (float) 0); 73 } 74 } catch (AssertionError e) { 75 Assert.assertEquals(r[i], mask[i % SPECIES.length()] ? a[i] : (float) 0, "at index #" + i); 76 } 77 } 78 79 static void assertArraysEquals(byte[] r, byte[] a, boolean[] mask) { 80 int i = 0; 81 try { 82 for (; i < a.length; i++) { 83 Assert.assertEquals(r[i], mask[(i*8/SPECIES.elementSize()) % SPECIES.length()] ? a[i] : (byte) 0); 84 } 85 } catch (AssertionError e) { 86 Assert.assertEquals(r[i], mask[(i*8/SPECIES.elementSize()) % SPECIES.length()] ? a[i] : (byte) 0, "at index #" + i); 87 } 88 } 89 90 static final List<IntFunction<float[]>> FLOAT_GENERATORS = List.of( 91 withToString("float[i * 5]", (int s) -> { 92 return fill(s * BUFFER_REPS, 93 i -> (float)(i * 5)); 94 }), 95 withToString("float[i + 1]", (int s) -> { 96 return fill(s * BUFFER_REPS, 97 i -> (((float)(i + 1) == 0) ? 1 : (float)(i + 1))); 98 }) 99 ); 100 101 // Relative to array.length 102 static final List<IntFunction<Integer>> INDEX_GENERATORS = List.of( 103 withToString("-1", (int l) -> { 104 return -1; 105 }), 106 withToString("l", (int l) -> { 107 return l; 108 }), 109 withToString("l - 1", (int l) -> { 110 return l - 1; 111 }), 112 withToString("l + 1", (int l) -> { 113 return l + 1; 114 }), 115 withToString("l - speciesl + 1", (int l) -> { 116 return l - SPECIES.length() + 1; 117 }), 118 withToString("l + speciesl - 1", (int l) -> { 119 return l + SPECIES.length() - 1; 120 }), 121 withToString("l + speciesl", (int l) -> { 122 return l + SPECIES.length(); 123 }), 124 withToString("l + speciesl + 1", (int l) -> { 125 return l + SPECIES.length() + 1; 126 }) 127 ); 128 129 // Relative to byte[] array.length or ByteBuffer.limit() 130 static final List<IntFunction<Integer>> BYTE_INDEX_GENERATORS = List.of( 131 withToString("-1", (int l) -> { 132 return -1; 133 }), 134 withToString("l", (int l) -> { 135 return l; 136 }), 137 withToString("l - 1", (int l) -> { 138 return l - 1; 139 }), 140 withToString("l + 1", (int l) -> { 141 return l + 1; 142 }), 143 withToString("l - speciesl*ebsize + 1", (int l) -> { 144 return l - SPECIES.vectorByteSize() + 1; 145 }), 146 withToString("l + speciesl*ebsize - 1", (int l) -> { 147 return l + SPECIES.vectorByteSize() - 1; 148 }), 149 withToString("l + speciesl*ebsize", (int l) -> { 150 return l + SPECIES.vectorByteSize(); 151 }), 152 withToString("l + speciesl*ebsize + 1", (int l) -> { 153 return l + SPECIES.vectorByteSize() + 1; 154 }) 155 ); 156 157 @DataProvider 158 public Object[][] floatProvider() { 159 return FLOAT_GENERATORS.stream(). 160 map(f -> new Object[]{f}). 161 toArray(Object[][]::new); 162 } 163 164 @DataProvider 165 public Object[][] maskProvider() { 166 return BOOLEAN_MASK_GENERATORS.stream(). 167 map(f -> new Object[]{f}). 168 toArray(Object[][]::new); 169 } 170 171 @DataProvider 172 public Object[][] floatProviderForIOOBE() { 173 var f = FLOAT_GENERATORS.get(0); 174 return INDEX_GENERATORS.stream().map(fi -> { 175 return new Object[] {f, fi}; 176 }). 177 toArray(Object[][]::new); 178 } 179 180 @DataProvider 181 public Object[][] floatMaskProvider() { 182 return BOOLEAN_MASK_GENERATORS.stream(). 183 flatMap(fm -> FLOAT_GENERATORS.stream().map(fa -> { 184 return new Object[] {fa, fm}; 185 })). 186 toArray(Object[][]::new); 187 } 188 189 @DataProvider 190 public Object[][] floatMaskProviderForIOOBE() { 191 var f = FLOAT_GENERATORS.get(0); 192 return BOOLEAN_MASK_GENERATORS.stream(). 193 flatMap(fm -> INDEX_GENERATORS.stream().map(fi -> { 194 return new Object[] {f, fi, fm}; 195 })). 196 toArray(Object[][]::new); 197 } 198 199 @DataProvider 200 public Object[][] floatByteBufferProvider() { 201 return FLOAT_GENERATORS.stream(). 202 flatMap(fa -> BYTE_BUFFER_GENERATORS.stream(). 203 flatMap(fb -> BYTE_ORDER_VALUES.stream().map(bo -> { 204 return new Object[]{fa, fb, bo}; 205 }))). 206 toArray(Object[][]::new); 207 } 208 209 @DataProvider 210 public Object[][] floatByteBufferMaskProvider() { 211 return BOOLEAN_MASK_GENERATORS.stream(). 212 flatMap(fm -> FLOAT_GENERATORS.stream(). 213 flatMap(fa -> BYTE_BUFFER_GENERATORS.stream(). 214 flatMap(fb -> BYTE_ORDER_VALUES.stream().map(bo -> { 215 return new Object[]{fa, fb, fm, bo}; 216 })))). 217 toArray(Object[][]::new); 218 } 219 220 @DataProvider 221 public Object[][] floatByteArrayProvider() { 222 return FLOAT_GENERATORS.stream(). 223 flatMap(fa -> BYTE_ORDER_VALUES.stream().map(bo -> { 224 return new Object[]{fa, bo}; 225 })). 226 toArray(Object[][]::new); 227 } 228 229 @DataProvider 230 public Object[][] floatByteArrayMaskProvider() { 231 return BOOLEAN_MASK_GENERATORS.stream(). 232 flatMap(fm -> FLOAT_GENERATORS.stream(). 233 flatMap(fa -> BYTE_ORDER_VALUES.stream().map(bo -> { 234 return new Object[]{fa, fm, bo}; 235 }))). 236 toArray(Object[][]::new); 237 } 238 239 @DataProvider 240 public Object[][] floatByteProviderForIOOBE() { 241 var f = FLOAT_GENERATORS.get(0); 242 return BYTE_INDEX_GENERATORS.stream().map(fi -> { 243 return new Object[] {f, fi}; 244 }). 245 toArray(Object[][]::new); 246 } 247 248 @DataProvider 249 public Object[][] floatByteMaskProviderForIOOBE() { 250 var f = FLOAT_GENERATORS.get(0); 251 return BOOLEAN_MASK_GENERATORS.stream(). 252 flatMap(fm -> BYTE_INDEX_GENERATORS.stream().map(fi -> { 253 return new Object[] {f, fi, fm}; 254 })). 255 toArray(Object[][]::new); 256 } 257 258 static ByteBuffer toBuffer(float[] a, IntFunction<ByteBuffer> fb) { 259 ByteBuffer bb = fb.apply(a.length * SPECIES.elementSize() / 8); 260 for (float v : a) { 261 bb.putFloat(v); 262 } 263 return bb.clear(); 264 } 265 266 static float[] bufferToArray(ByteBuffer bb) { 267 FloatBuffer db = bb.asFloatBuffer(); 268 float[] d = new float[db.capacity()]; 269 db.get(0, d); 270 return d; 271 } 272 273 static byte[] toByteArray(float[] a, IntFunction<byte[]> fb, ByteOrder bo) { 274 byte[] b = fb.apply(a.length * SPECIES.elementSize() / 8); 275 FloatBuffer bb = ByteBuffer.wrap(b, 0, b.length).order(bo).asFloatBuffer(); 276 for (float v : a) { 277 bb.put(v); 278 } 279 return b; 280 } 281 282 283 interface ToFloatF { 284 float apply(int i); 285 } 286 287 static float[] fill(int s , ToFloatF f) { 288 return fill(new float[s], f); 289 } 290 291 static float[] fill(float[] a, ToFloatF f) { 292 for (int i = 0; i < a.length; i++) { 293 a[i] = f.apply(i); 294 } 295 return a; 296 } 297 298 @DontInline 299 static FloatVector fromArray(float[] a, int i) { 300 return FloatVector.fromArray(SPECIES, a, i); 301 } 302 303 @DontInline 304 static FloatVector fromArray(float[] a, int i, VectorMask<Float> m) { 305 return FloatVector.fromArray(SPECIES, a, i, m); 306 } 307 308 @DontInline 309 static void intoArray(FloatVector v, float[] a, int i) { 310 v.intoArray(a, i); 311 } 312 313 @DontInline 314 static void intoArray(FloatVector v, float[] a, int i, VectorMask<Float> m) { 315 v.intoArray(a, i, m); 316 } 317 318 @DontInline 319 static FloatVector fromByteArray(byte[] a, int i, ByteOrder bo) { 320 return FloatVector.fromByteArray(SPECIES, a, i, bo); 321 } 322 323 @DontInline 324 static FloatVector fromByteArray(byte[] a, int i, ByteOrder bo, VectorMask<Float> m) { 325 return FloatVector.fromByteArray(SPECIES, a, i, bo, m); 326 } 327 328 @DontInline 329 static void intoByteArray(FloatVector v, byte[] a, int i, ByteOrder bo) { 330 v.intoByteArray(a, i, bo); 331 } 332 333 @DontInline 334 static void intoByteArray(FloatVector v, byte[] a, int i, ByteOrder bo, VectorMask<Float> m) { 335 v.intoByteArray(a, i, bo, m); 336 } 337 338 @DontInline 339 static FloatVector fromByteBuffer(ByteBuffer a, int i, ByteOrder bo) { 340 return FloatVector.fromByteBuffer(SPECIES, a, i, bo); 341 } 342 343 @DontInline 344 static FloatVector fromByteBuffer(ByteBuffer a, int i, ByteOrder bo, VectorMask<Float> m) { 345 return FloatVector.fromByteBuffer(SPECIES, a, i, bo, m); 346 } 347 348 @DontInline 349 static void intoByteBuffer(FloatVector v, ByteBuffer a, int i, ByteOrder bo) { 350 v.intoByteBuffer(a, i, bo); 351 } 352 353 @DontInline 354 static void intoByteBuffer(FloatVector v, ByteBuffer a, int i, ByteOrder bo, VectorMask<Float> m) { 355 v.intoByteBuffer(a, i, bo, m); 356 } 357 358 359 @Test(dataProvider = "floatProvider") 360 static void loadStoreArray(IntFunction<float[]> fa) { 361 float[] a = fa.apply(SPECIES.length()); 362 float[] r = new float[a.length]; 363 364 for (int ic = 0; ic < INVOC_COUNT; ic++) { 365 for (int i = 0; i < a.length; i += SPECIES.length()) { 366 FloatVector av = FloatVector.fromArray(SPECIES, a, i); 367 av.intoArray(r, i); 368 } 369 } 370 Assert.assertEquals(r, a); 371 } 372 373 @Test(dataProvider = "floatProviderForIOOBE") 374 static void loadArrayIOOBE(IntFunction<float[]> fa, IntFunction<Integer> fi) { 375 float[] a = fa.apply(SPECIES.length()); 376 float[] r = new float[a.length]; 377 378 for (int ic = 0; ic < INVOC_COUNT; ic++) { 379 for (int i = 0; i < a.length; i += SPECIES.length()) { 380 FloatVector av = fromArray(a, i); 381 av.intoArray(r, i); 382 } 383 } 384 385 int index = fi.apply(a.length); 386 boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length); 387 try { 388 fromArray(a, index); 389 if (shouldFail) { 390 Assert.fail("Failed to throw IndexOutOfBoundsException"); 391 } 392 } catch (IndexOutOfBoundsException e) { 393 if (!shouldFail) { 394 Assert.fail("Unexpected IndexOutOfBoundsException"); 395 } 396 } 397 } 398 399 @Test(dataProvider = "floatProviderForIOOBE") 400 static void storeArrayIOOBE(IntFunction<float[]> fa, IntFunction<Integer> fi) { 401 float[] a = fa.apply(SPECIES.length()); 402 float[] r = new float[a.length]; 403 404 for (int ic = 0; ic < INVOC_COUNT; ic++) { 405 for (int i = 0; i < a.length; i += SPECIES.length()) { 406 FloatVector av = FloatVector.fromArray(SPECIES, a, i); 407 intoArray(av, r, i); 408 } 409 } 410 411 int index = fi.apply(a.length); 412 boolean shouldFail = isIndexOutOfBounds(SPECIES.length(), index, a.length); 413 try { 414 FloatVector av = FloatVector.fromArray(SPECIES, a, 0); 415 intoArray(av, r, index); 416 if (shouldFail) { 417 Assert.fail("Failed to throw IndexOutOfBoundsException"); 418 } 419 } catch (IndexOutOfBoundsException e) { 420 if (!shouldFail) { 421 Assert.fail("Unexpected IndexOutOfBoundsException"); 422 } 423 } 424 } 425 426 427 @Test(dataProvider = "floatMaskProvider") 428 static void loadStoreMaskArray(IntFunction<float[]> fa, 429 IntFunction<boolean[]> fm) { 430 float[] a = fa.apply(SPECIES.length()); 431 float[] r = new float[a.length]; 432 boolean[] mask = fm.apply(SPECIES.length()); 433 VectorMask<Float> vmask = VectorMask.fromValues(SPECIES, mask); 434 435 for (int ic = 0; ic < INVOC_COUNT; ic++) { 436 for (int i = 0; i < a.length; i += SPECIES.length()) { 437 FloatVector av = FloatVector.fromArray(SPECIES, a, i, vmask); 438 av.intoArray(r, i); 439 } 440 } 441 assertArraysEquals(r, a, mask); 442 443 444 r = new float[a.length]; 445 446 for (int ic = 0; ic < INVOC_COUNT; ic++) { 447 for (int i = 0; i < a.length; i += SPECIES.length()) { 448 FloatVector av = FloatVector.fromArray(SPECIES, a, i); 449 av.intoArray(r, i, vmask); 450 } 451 } 452 assertArraysEquals(r, a, mask); 453 } 454 455 @Test(dataProvider = "floatMaskProviderForIOOBE") 456 static void loadArrayMaskIOOBE(IntFunction<float[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) { 457 float[] a = fa.apply(SPECIES.length()); 458 float[] r = new float[a.length]; 459 boolean[] mask = fm.apply(SPECIES.length()); 460 VectorMask<Float> vmask = VectorMask.fromValues(SPECIES, mask); 461 462 for (int ic = 0; ic < INVOC_COUNT; ic++) { 463 for (int i = 0; i < a.length; i += SPECIES.length()) { 464 FloatVector av = fromArray(a, i, vmask); 465 av.intoArray(r, i); 466 } 467 } 468 469 int index = fi.apply(a.length); 470 boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length); 471 try { 472 fromArray(a, index, vmask); 473 if (shouldFail) { 474 Assert.fail("Failed to throw IndexOutOfBoundsException"); 475 } 476 } catch (IndexOutOfBoundsException e) { 477 if (!shouldFail) { 478 Assert.fail("Unexpected IndexOutOfBoundsException"); 479 } 480 } 481 } 482 483 @Test(dataProvider = "floatMaskProviderForIOOBE") 484 static void storeArrayMaskIOOBE(IntFunction<float[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) { 485 float[] a = fa.apply(SPECIES.length()); 486 float[] r = new float[a.length]; 487 boolean[] mask = fm.apply(SPECIES.length()); 488 VectorMask<Float> vmask = VectorMask.fromValues(SPECIES, mask); 489 490 for (int ic = 0; ic < INVOC_COUNT; ic++) { 491 for (int i = 0; i < a.length; i += SPECIES.length()) { 492 FloatVector av = FloatVector.fromArray(SPECIES, a, i); 493 intoArray(av, r, i, vmask); 494 } 495 } 496 497 int index = fi.apply(a.length); 498 boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length); 499 try { 500 FloatVector av = FloatVector.fromArray(SPECIES, a, 0); 501 intoArray(av, a, index, vmask); 502 if (shouldFail) { 503 Assert.fail("Failed to throw IndexOutOfBoundsException"); 504 } 505 } catch (IndexOutOfBoundsException e) { 506 if (!shouldFail) { 507 Assert.fail("Unexpected IndexOutOfBoundsException"); 508 } 509 } 510 } 511 512 513 @Test(dataProvider = "floatMaskProvider") 514 static void loadStoreMask(IntFunction<float[]> fa, 515 IntFunction<boolean[]> fm) { 516 boolean[] mask = fm.apply(SPECIES.length()); 517 boolean[] r = new boolean[mask.length]; 518 519 for (int ic = 0; ic < INVOC_COUNT; ic++) { 520 for (int i = 0; i < mask.length; i += SPECIES.length()) { 521 VectorMask<Float> vmask = VectorMask.fromArray(SPECIES, mask, i); 522 vmask.intoArray(r, i); 523 } 524 } 525 Assert.assertEquals(r, mask); 526 } 527 528 529 @Test(dataProvider = "floatByteBufferProvider") 530 static void loadStoreByteBuffer(IntFunction<float[]> fa, 531 IntFunction<ByteBuffer> fb, 532 ByteOrder bo) { 533 ByteBuffer a = toBuffer(fa.apply(SPECIES.length()), fb); 534 ByteBuffer r = fb.apply(a.limit()); 535 536 int l = a.limit(); 537 int s = SPECIES.vectorByteSize(); 538 539 for (int ic = 0; ic < INVOC_COUNT; ic++) { 540 for (int i = 0; i < l; i += s) { 541 FloatVector av = FloatVector.fromByteBuffer(SPECIES, a, i, bo); 542 av.intoByteBuffer(r, i, bo); 543 } 544 } 545 Assert.assertEquals(a.position(), 0, "Input buffer position changed"); 546 Assert.assertEquals(a.limit(), l, "Input buffer limit changed"); 547 Assert.assertEquals(r.position(), 0, "Result buffer position changed"); 548 Assert.assertEquals(r.limit(), l, "Result buffer limit changed"); 549 Assert.assertEquals(r, a, "Buffers not equal"); 550 } 551 552 @Test(dataProvider = "floatByteProviderForIOOBE") 553 static void loadByteBufferIOOBE(IntFunction<float[]> fa, IntFunction<Integer> fi) { 554 ByteBuffer a = toBuffer(fa.apply(SPECIES.length()), ByteBuffer::allocateDirect); 555 ByteBuffer r = ByteBuffer.allocateDirect(a.limit()); 556 557 int l = a.limit(); 558 int s = SPECIES.vectorByteSize(); 559 560 for (int ic = 0; ic < INVOC_COUNT; ic++) { 561 for (int i = 0; i < l; i += s) { 562 FloatVector av = fromByteBuffer(a, i, ByteOrder.nativeOrder()); 563 av.intoByteBuffer(r, i, ByteOrder.nativeOrder()); 564 } 565 } 566 567 int index = fi.apply(a.limit()); 568 boolean shouldFail = isIndexOutOfBounds(SPECIES.vectorByteSize(), index, a.limit()); 569 try { 570 fromByteBuffer(a, index, ByteOrder.nativeOrder()); 571 if (shouldFail) { 572 Assert.fail("Failed to throw IndexOutOfBoundsException"); 573 } 574 } catch (IndexOutOfBoundsException e) { 575 if (!shouldFail) { 576 Assert.fail("Unexpected IndexOutOfBoundsException"); 577 } 578 } 579 } 580 581 @Test(dataProvider = "floatByteProviderForIOOBE") 582 static void storeByteBufferIOOBE(IntFunction<float[]> fa, IntFunction<Integer> fi) { 583 ByteBuffer a = toBuffer(fa.apply(SPECIES.length()), ByteBuffer::allocateDirect); 584 ByteBuffer r = ByteBuffer.allocateDirect(a.limit()); 585 586 int l = a.limit(); 587 int s = SPECIES.vectorByteSize(); 588 589 for (int ic = 0; ic < INVOC_COUNT; ic++) { 590 for (int i = 0; i < l; i += s) { 591 FloatVector av = FloatVector.fromByteBuffer(SPECIES, a, i, ByteOrder.nativeOrder()); 592 intoByteBuffer(av, r, i, ByteOrder.nativeOrder()); 593 } 594 } 595 596 int index = fi.apply(a.limit()); 597 boolean shouldFail = isIndexOutOfBounds(SPECIES.vectorByteSize(), index, a.limit()); 598 try { 599 FloatVector av = FloatVector.fromByteBuffer(SPECIES, a, 0, ByteOrder.nativeOrder()); 600 intoByteBuffer(av, r, index, ByteOrder.nativeOrder()); 601 if (shouldFail) { 602 Assert.fail("Failed to throw IndexOutOfBoundsException"); 603 } 604 } catch (IndexOutOfBoundsException e) { 605 if (!shouldFail) { 606 Assert.fail("Unexpected IndexOutOfBoundsException"); 607 } 608 } 609 } 610 611 612 @Test(dataProvider = "floatByteBufferMaskProvider") 613 static void loadStoreByteBufferMask(IntFunction<float[]> fa, 614 IntFunction<ByteBuffer> fb, 615 IntFunction<boolean[]> fm, 616 ByteOrder bo) { 617 float[] _a = fa.apply(SPECIES.length()); 618 ByteBuffer a = toBuffer(_a, fb); 619 ByteBuffer r = fb.apply(a.limit()); 620 boolean[] mask = fm.apply(SPECIES.length()); 621 VectorMask<Float> vmask = VectorMask.fromValues(SPECIES, mask); 622 623 int l = a.limit(); 624 int s = SPECIES.vectorByteSize(); 625 626 for (int ic = 0; ic < INVOC_COUNT; ic++) { 627 for (int i = 0; i < l; i += s) { 628 FloatVector av = FloatVector.fromByteBuffer(SPECIES, a, i, bo, vmask); 629 av.intoByteBuffer(r, i, bo); 630 } 631 } 632 Assert.assertEquals(a.position(), 0, "Input buffer position changed"); 633 Assert.assertEquals(a.limit(), l, "Input buffer limit changed"); 634 Assert.assertEquals(r.position(), 0, "Result buffer position changed"); 635 Assert.assertEquals(r.limit(), l, "Result buffer limit changed"); 636 assertArraysEquals(bufferToArray(r), _a, mask); 637 638 639 r = fb.apply(a.limit()); 640 641 for (int ic = 0; ic < INVOC_COUNT; ic++) { 642 for (int i = 0; i < l; i += s) { 643 FloatVector av = FloatVector.fromByteBuffer(SPECIES, a, i, bo); 644 av.intoByteBuffer(r, i, bo, vmask); 645 } 646 } 647 Assert.assertEquals(a.position(), 0, "Input buffer position changed"); 648 Assert.assertEquals(a.limit(), l, "Input buffer limit changed"); 649 Assert.assertEquals(r.position(), 0, "Result buffer position changed"); 650 Assert.assertEquals(r.limit(), l, "Result buffer limit changed"); 651 assertArraysEquals(bufferToArray(r), _a, mask); 652 } 653 654 @Test(dataProvider = "floatByteMaskProviderForIOOBE") 655 static void loadByteBufferMaskIOOBE(IntFunction<float[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) { 656 ByteBuffer a = toBuffer(fa.apply(SPECIES.length()), ByteBuffer::allocateDirect); 657 ByteBuffer r = ByteBuffer.allocateDirect(a.limit()); 658 boolean[] mask = fm.apply(SPECIES.length()); 659 VectorMask<Float> vmask = VectorMask.fromValues(SPECIES, mask); 660 661 int l = a.limit(); 662 int s = SPECIES.vectorByteSize(); 663 664 for (int ic = 0; ic < INVOC_COUNT; ic++) { 665 for (int i = 0; i < l; i += s) { 666 FloatVector av = fromByteBuffer(a, i, ByteOrder.nativeOrder(), vmask); 667 av.intoByteBuffer(r, i, ByteOrder.nativeOrder()); 668 } 669 } 670 671 int index = fi.apply(a.limit()); 672 boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.limit(), SPECIES.elementSize() / 8); 673 try { 674 fromByteBuffer(a, index, ByteOrder.nativeOrder(), vmask); 675 if (shouldFail) { 676 Assert.fail("Failed to throw IndexOutOfBoundsException"); 677 } 678 } catch (IndexOutOfBoundsException e) { 679 if (!shouldFail) { 680 Assert.fail("Unexpected IndexOutOfBoundsException"); 681 } 682 } 683 } 684 685 @Test(dataProvider = "floatByteMaskProviderForIOOBE") 686 static void storeByteBufferMaskIOOBE(IntFunction<float[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) { 687 ByteBuffer a = toBuffer(fa.apply(SPECIES.length()), ByteBuffer::allocateDirect); 688 ByteBuffer r = ByteBuffer.allocateDirect(a.limit()); 689 boolean[] mask = fm.apply(SPECIES.length()); 690 VectorMask<Float> vmask = VectorMask.fromValues(SPECIES, mask); 691 692 int l = a.limit(); 693 int s = SPECIES.vectorByteSize(); 694 695 for (int ic = 0; ic < INVOC_COUNT; ic++) { 696 for (int i = 0; i < l; i += s) { 697 FloatVector av = FloatVector.fromByteBuffer(SPECIES, a, i, ByteOrder.nativeOrder()); 698 intoByteBuffer(av, r, i, ByteOrder.nativeOrder(), vmask); 699 } 700 } 701 702 int index = fi.apply(a.limit()); 703 boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.limit(), SPECIES.elementSize() / 8); 704 try { 705 FloatVector av = FloatVector.fromByteBuffer(SPECIES, a, 0, ByteOrder.nativeOrder()); 706 intoByteBuffer(av, a, index, ByteOrder.nativeOrder(), vmask); 707 if (shouldFail) { 708 Assert.fail("Failed to throw IndexOutOfBoundsException"); 709 } 710 } catch (IndexOutOfBoundsException e) { 711 if (!shouldFail) { 712 Assert.fail("Unexpected IndexOutOfBoundsException"); 713 } 714 } 715 } 716 717 718 @Test(dataProvider = "floatByteBufferProvider") 719 static void loadStoreReadonlyByteBuffer(IntFunction<float[]> fa, 720 IntFunction<ByteBuffer> fb, 721 ByteOrder bo) { 722 ByteBuffer a = toBuffer(fa.apply(SPECIES.length()), fb).asReadOnlyBuffer(); 723 724 try { 725 SPECIES.zero().intoByteBuffer(a, 0, bo); 726 Assert.fail("ReadOnlyBufferException expected"); 727 } catch (ReadOnlyBufferException e) { 728 } 729 730 try { 731 SPECIES.zero().intoByteBuffer(a, 0, bo, SPECIES.maskAll(true)); 732 Assert.fail("ReadOnlyBufferException expected"); 733 } catch (ReadOnlyBufferException e) { 734 } 735 736 try { 737 SPECIES.zero().intoByteBuffer(a, 0, bo, SPECIES.maskAll(false)); 738 Assert.fail("ReadOnlyBufferException expected"); 739 } catch (ReadOnlyBufferException e) { 740 } 741 742 try { 743 VectorMask<Float> m = SPECIES.shuffleFromOp(i -> i % 2 == 0 ? 1 : -1) 744 .laneIsValid(); 745 SPECIES.zero().intoByteBuffer(a, 0, bo, m); 746 Assert.fail("ReadOnlyBufferException expected"); 747 } catch (ReadOnlyBufferException e) { 748 } 749 } 750 751 752 @Test(dataProvider = "floatByteArrayProvider") 753 static void loadStoreByteArray(IntFunction<float[]> fa, 754 ByteOrder bo) { 755 byte[] a = toByteArray(fa.apply(SPECIES.length()), byte[]::new, bo); 756 byte[] r = new byte[a.length]; 757 758 int s = SPECIES.vectorByteSize(); 759 int l = a.length; 760 761 for (int ic = 0; ic < INVOC_COUNT; ic++) { 762 for (int i = 0; i < l; i += s) { 763 FloatVector av = FloatVector.fromByteArray(SPECIES, a, i, bo); 764 av.intoByteArray(r, i, bo); 765 } 766 } 767 Assert.assertEquals(r, a, "Byte arrays not equal"); 768 } 769 770 @Test(dataProvider = "floatByteProviderForIOOBE") 771 static void loadByteArrayIOOBE(IntFunction<float[]> fa, IntFunction<Integer> fi) { 772 byte[] a = toByteArray(fa.apply(SPECIES.length()), byte[]::new, ByteOrder.nativeOrder()); 773 byte[] r = new byte[a.length]; 774 775 int s = SPECIES.vectorByteSize(); 776 int l = a.length; 777 778 for (int ic = 0; ic < INVOC_COUNT; ic++) { 779 for (int i = 0; i < l; i += s) { 780 FloatVector av = fromByteArray(a, i, ByteOrder.nativeOrder()); 781 av.intoByteArray(r, i, ByteOrder.nativeOrder()); 782 } 783 } 784 785 int index = fi.apply(a.length); 786 boolean shouldFail = isIndexOutOfBounds(SPECIES.vectorByteSize(), index, a.length); 787 try { 788 fromByteArray(a, index, ByteOrder.nativeOrder()); 789 if (shouldFail) { 790 Assert.fail("Failed to throw IndexOutOfBoundsException"); 791 } 792 } catch (IndexOutOfBoundsException e) { 793 if (!shouldFail) { 794 Assert.fail("Unexpected IndexOutOfBoundsException"); 795 } 796 } 797 } 798 799 @Test(dataProvider = "floatByteProviderForIOOBE") 800 static void storeByteArrayIOOBE(IntFunction<float[]> fa, IntFunction<Integer> fi) { 801 byte[] a = toByteArray(fa.apply(SPECIES.length()), byte[]::new, ByteOrder.nativeOrder()); 802 byte[] r = new byte[a.length]; 803 804 int s = SPECIES.vectorByteSize(); 805 int l = a.length; 806 807 for (int ic = 0; ic < INVOC_COUNT; ic++) { 808 for (int i = 0; i < l; i += s) { 809 FloatVector av = FloatVector.fromByteArray(SPECIES, a, i, ByteOrder.nativeOrder()); 810 intoByteArray(av, r, i, ByteOrder.nativeOrder()); 811 } 812 } 813 814 int index = fi.apply(a.length); 815 boolean shouldFail = isIndexOutOfBounds(SPECIES.vectorByteSize(), index, a.length); 816 try { 817 FloatVector av = FloatVector.fromByteArray(SPECIES, a, 0, ByteOrder.nativeOrder()); 818 intoByteArray(av, r, index, ByteOrder.nativeOrder()); 819 if (shouldFail) { 820 Assert.fail("Failed to throw IndexOutOfBoundsException"); 821 } 822 } catch (IndexOutOfBoundsException e) { 823 if (!shouldFail) { 824 Assert.fail("Unexpected IndexOutOfBoundsException"); 825 } 826 } 827 } 828 829 830 @Test(dataProvider = "floatByteArrayMaskProvider") 831 static void loadStoreByteArrayMask(IntFunction<float[]> fa, 832 IntFunction<boolean[]> fm, 833 ByteOrder bo) { 834 byte[] a = toByteArray(fa.apply(SPECIES.length()), byte[]::new, bo); 835 byte[] r = new byte[a.length]; 836 boolean[] mask = fm.apply(SPECIES.length()); 837 VectorMask<Float> vmask = VectorMask.fromValues(SPECIES, mask); 838 839 int s = SPECIES.vectorByteSize(); 840 int l = a.length; 841 842 for (int ic = 0; ic < INVOC_COUNT; ic++) { 843 for (int i = 0; i < l; i += s) { 844 FloatVector av = FloatVector.fromByteArray(SPECIES, a, i, bo, vmask); 845 av.intoByteArray(r, i, bo); 846 } 847 } 848 assertArraysEquals(r, a, mask); 849 850 851 r = new byte[a.length]; 852 853 for (int ic = 0; ic < INVOC_COUNT; ic++) { 854 for (int i = 0; i < l; i += s) { 855 FloatVector av = FloatVector.fromByteArray(SPECIES, a, i, bo); 856 av.intoByteArray(r, i, bo, vmask); 857 } 858 } 859 assertArraysEquals(r, a, mask); 860 } 861 862 @Test(dataProvider = "floatByteMaskProviderForIOOBE") 863 static void loadByteArrayMaskIOOBE(IntFunction<float[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) { 864 byte[] a = toByteArray(fa.apply(SPECIES.length()), byte[]::new, ByteOrder.nativeOrder()); 865 byte[] r = new byte[a.length]; 866 boolean[] mask = fm.apply(SPECIES.length()); 867 VectorMask<Float> vmask = VectorMask.fromValues(SPECIES, mask); 868 869 int s = SPECIES.vectorByteSize(); 870 int l = a.length; 871 872 for (int ic = 0; ic < INVOC_COUNT; ic++) { 873 for (int i = 0; i < l; i += s) { 874 FloatVector av = fromByteArray(a, i, ByteOrder.nativeOrder(), vmask); 875 av.intoByteArray(r, i, ByteOrder.nativeOrder()); 876 } 877 } 878 879 int index = fi.apply(a.length); 880 boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length, SPECIES.elementSize() / 8); 881 try { 882 fromByteArray(a, index, ByteOrder.nativeOrder(), vmask); 883 if (shouldFail) { 884 Assert.fail("Failed to throw IndexOutOfBoundsException"); 885 } 886 } catch (IndexOutOfBoundsException e) { 887 if (!shouldFail) { 888 Assert.fail("Unexpected IndexOutOfBoundsException"); 889 } 890 } 891 } 892 893 @Test(dataProvider = "floatByteMaskProviderForIOOBE") 894 static void storeByteArrayMaskIOOBE(IntFunction<float[]> fa, IntFunction<Integer> fi, IntFunction<boolean[]> fm) { 895 byte[] a = toByteArray(fa.apply(SPECIES.length()), byte[]::new, ByteOrder.nativeOrder()); 896 byte[] r = new byte[a.length]; 897 boolean[] mask = fm.apply(SPECIES.length()); 898 VectorMask<Float> vmask = VectorMask.fromValues(SPECIES, mask); 899 900 int s = SPECIES.vectorByteSize(); 901 int l = a.length; 902 903 for (int ic = 0; ic < INVOC_COUNT; ic++) { 904 for (int i = 0; i < l; i += s) { 905 FloatVector av = FloatVector.fromByteArray(SPECIES, a, i, ByteOrder.nativeOrder()); 906 intoByteArray(av, r, i, ByteOrder.nativeOrder(), vmask); 907 } 908 } 909 910 int index = fi.apply(a.length); 911 boolean shouldFail = isIndexOutOfBoundsForMask(mask, index, a.length, SPECIES.elementSize() / 8); 912 try { 913 FloatVector av = FloatVector.fromByteArray(SPECIES, a, 0, ByteOrder.nativeOrder()); 914 intoByteArray(av, a, index, ByteOrder.nativeOrder(), vmask); 915 if (shouldFail) { 916 Assert.fail("Failed to throw IndexOutOfBoundsException"); 917 } 918 } catch (IndexOutOfBoundsException e) { 919 if (!shouldFail) { 920 Assert.fail("Unexpected IndexOutOfBoundsException"); 921 } 922 } 923 } 924 925 @Test(dataProvider = "maskProvider") 926 static void loadStoreMask(IntFunction<boolean[]> fm) { 927 boolean[] a = fm.apply(SPECIES.length()); 928 boolean[] r = new boolean[a.length]; 929 930 for (int ic = 0; ic < INVOC_COUNT; ic++) { 931 for (int i = 0; i < a.length; i += SPECIES.length()) { 932 VectorMask<Float> vmask = SPECIES.loadMask(a, i); 933 vmask.intoArray(r, i); 934 } 935 } 936 Assert.assertEquals(r, a); 937 } 938 939 @Test 940 static void loadStoreShuffle() { 941 IntUnaryOperator fn = a -> a + 5; 942 for (int ic = 0; ic < INVOC_COUNT; ic++) { 943 var shuffle = VectorShuffle.fromOp(SPECIES, fn); 944 int [] r = shuffle.toArray(); 945 946 int [] a = expectedShuffle(SPECIES.length(), fn); 947 Assert.assertEquals(r, a); 948 } 949 } 950 951 952 953 954 955 // Gather/Scatter load/store tests 956 957 static void assertGatherArraysEquals(float[] r, float[] a, int[] indexMap) { 958 int i = 0; 959 int j = 0; 960 try { 961 for (; i < a.length; i += SPECIES.length()) { 962 j = i; 963 for (; j < i + SPECIES.length(); j++) { 964 Assert.assertEquals(r[j], a[i + indexMap[j]]); 965 } 966 } 967 } catch (AssertionError e) { 968 Assert.assertEquals(r[j], a[i + indexMap[j]], "at index #" + j); 969 } 970 } 971 972 static void assertGatherArraysEquals(float[] r, float[] a, int[] indexMap, boolean[] mask) { 973 int i = 0; 974 int j = 0; 975 try { 976 for (; i < a.length; i += SPECIES.length()) { 977 j = i; 978 for (; j < i + SPECIES.length(); j++) { 979 Assert.assertEquals(r[j], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (float) 0); 980 } 981 } 982 } catch (AssertionError e) { 983 Assert.assertEquals(r[i], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (float) 0, "at index #" + j); 984 } 985 } 986 987 static void assertScatterArraysEquals(float[] r, float[] a, int[] indexMap, boolean[] mask) { 988 float[] expected = new float[r.length]; 989 990 // Store before checking, since the same location may be stored to more than once 991 for (int i = 0; i < a.length; i += SPECIES.length()) { 992 for (int j = i; j < i + SPECIES.length(); j++) { 993 if (mask[j % SPECIES.length()]) { 994 expected[i + indexMap[j]] = a[j]; 995 } 996 } 997 } 998 999 Assert.assertEquals(r, expected); 1000 } 1001 1002 static void assertScatterArraysEquals(float[] r, float[] a, int[] indexMap) { 1003 float[] expected = new float[r.length]; 1004 1005 // Store before checking, since the same location may be stored to more than once 1006 for (int i = 0; i < a.length; i += SPECIES.length()) { 1007 for (int j = i; j < i + SPECIES.length(); j++) { 1008 expected[i + indexMap[j]] = a[j]; 1009 } 1010 } 1011 1012 Assert.assertEquals(r, expected); 1013 } 1014 1015 @DataProvider 1016 public Object[][] gatherScatterProvider() { 1017 return INT_INDEX_GENERATORS.stream(). 1018 flatMap(fs -> FLOAT_GENERATORS.stream().map(fa -> { 1019 return new Object[] {fa, fs}; 1020 })). 1021 toArray(Object[][]::new); 1022 } 1023 1024 @DataProvider 1025 public Object[][] gatherScatterMaskProvider() { 1026 return BOOLEAN_MASK_GENERATORS.stream(). 1027 flatMap(fs -> INT_INDEX_GENERATORS.stream().flatMap(fm -> 1028 FLOAT_GENERATORS.stream().map(fa -> { 1029 return new Object[] {fa, fm, fs}; 1030 }))). 1031 toArray(Object[][]::new); 1032 } 1033 1034 1035 @Test(dataProvider = "gatherScatterProvider") 1036 static void gather(IntFunction<float[]> fa, BiFunction<Integer,Integer,int[]> fs) { 1037 float[] a = fa.apply(SPECIES.length()); 1038 int[] b = fs.apply(a.length, SPECIES.length()); 1039 float[] r = new float[a.length]; 1040 1041 for (int ic = 0; ic < INVOC_COUNT; ic++) { 1042 for (int i = 0; i < a.length; i += SPECIES.length()) { 1043 FloatVector av = FloatVector.fromArray(SPECIES, a, i, b, i); 1044 av.intoArray(r, i); 1045 } 1046 } 1047 1048 assertGatherArraysEquals(r, a, b); 1049 } 1050 1051 @Test(dataProvider = "gatherScatterMaskProvider") 1052 static void gatherMask(IntFunction<float[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) { 1053 float[] a = fa.apply(SPECIES.length()); 1054 int[] b = fs.apply(a.length, SPECIES.length()); 1055 float[] r = new float[a.length]; 1056 boolean[] mask = fm.apply(SPECIES.length()); 1057 VectorMask<Float> vmask = VectorMask.fromArray(SPECIES, mask, 0); 1058 1059 for (int ic = 0; ic < INVOC_COUNT; ic++) { 1060 for (int i = 0; i < a.length; i += SPECIES.length()) { 1061 FloatVector av = FloatVector.fromArray(SPECIES, a, i, b, i, vmask); 1062 av.intoArray(r, i); 1063 } 1064 } 1065 1066 assertGatherArraysEquals(r, a, b, mask); 1067 } 1068 1069 @Test(dataProvider = "gatherScatterProvider") 1070 static void scatter(IntFunction<float[]> fa, BiFunction<Integer,Integer,int[]> fs) { 1071 float[] a = fa.apply(SPECIES.length()); 1072 int[] b = fs.apply(a.length, SPECIES.length()); 1073 float[] r = new float[a.length]; 1074 1075 for (int ic = 0; ic < INVOC_COUNT; ic++) { 1076 for (int i = 0; i < a.length; i += SPECIES.length()) { 1077 FloatVector av = FloatVector.fromArray(SPECIES, a, i); 1078 av.intoArray(r, i, b, i); 1079 } 1080 } 1081 1082 assertScatterArraysEquals(r, a, b); 1083 } 1084 1085 @Test(dataProvider = "gatherScatterMaskProvider") 1086 static void scatterMask(IntFunction<float[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) { 1087 float[] a = fa.apply(SPECIES.length()); 1088 int[] b = fs.apply(a.length, SPECIES.length()); 1089 float[] r = new float[a.length]; 1090 boolean[] mask = fm.apply(SPECIES.length()); 1091 VectorMask<Float> vmask = VectorMask.fromArray(SPECIES, mask, 0); 1092 1093 for (int ic = 0; ic < INVOC_COUNT; ic++) { 1094 for (int i = 0; i < a.length; i += SPECIES.length()) { 1095 FloatVector av = FloatVector.fromArray(SPECIES, a, i); 1096 av.intoArray(r, i, b, i, vmask); 1097 } 1098 } 1099 1100 assertScatterArraysEquals(r, a, b, mask); 1101 } 1102 1103 1104 1105 }