1 /* 2 * Copyright (c) 2017, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have 23 * questions. 24 */ 25 package jdk.incubator.vector; 26 27 import jdk.internal.vm.annotation.ForceInline; 28 29 import java.nio.ByteBuffer; 30 import java.nio.ByteOrder; 31 import java.nio.IntBuffer; 32 import java.util.Objects; 33 import java.util.concurrent.ThreadLocalRandom; 34 35 36 /** 37 * A specialized {@link Vector} representing an ordered immutable sequence of 38 * {@code int} values. 39 * 40 * @param <S> the type of shape of this vector 41 */ 42 @SuppressWarnings("cast") 43 public abstract class IntVector<S extends Vector.Shape> extends Vector<Integer,S> { 44 45 IntVector() {} 46 47 // Unary operator 48 49 interface FUnOp { 50 int apply(int i, int a); 51 } 52 53 abstract IntVector<S> uOp(FUnOp f); 54 55 abstract IntVector<S> uOp(Mask<Integer, S> m, FUnOp f); 56 57 // Binary operator 58 59 interface FBinOp { 60 int apply(int i, int a, int b); 61 } 62 63 abstract IntVector<S> bOp(Vector<Integer,S> o, FBinOp f); 64 65 abstract IntVector<S> bOp(Vector<Integer,S> o, Mask<Integer, S> m, FBinOp f); 66 67 // Trinary operator 68 69 interface FTriOp { 70 int apply(int i, int a, int b, int c); 71 } 72 73 abstract IntVector<S> tOp(Vector<Integer,S> o1, Vector<Integer,S> o2, FTriOp f); 74 75 abstract IntVector<S> tOp(Vector<Integer,S> o1, Vector<Integer,S> o2, Mask<Integer, S> m, FTriOp f); 76 77 // Reduction operator 78 79 abstract int rOp(int v, FBinOp f); 80 81 // Binary test 82 83 interface FBinTest { 84 boolean apply(int i, int a, int b); 85 } 86 87 abstract Mask<Integer, S> bTest(Vector<Integer,S> o, FBinTest f); 88 89 // Foreach 90 91 interface FUnCon { 92 void apply(int i, int a); 93 } 94 95 abstract void forEach(FUnCon f); 96 97 abstract void forEach(Mask<Integer, S> m, FUnCon f); 98 99 // 100 101 @Override 102 public IntVector<S> add(Vector<Integer,S> o) { 103 return bOp(o, (i, a, b) -> (int) (a + b)); 104 } 105 106 /** 107 * Adds this vector to the result of broadcasting an input scalar. 108 * <p> 109 * This is a vector binary operation where the primitive addition operation 110 * ({@code +}) is applied to lane elements. 111 * 112 * @param b the input scalar 113 * @return the result of adding this vector to the broadcast of an input 114 * scalar 115 */ 116 public abstract IntVector<S> add(int b); 117 118 @Override 119 public IntVector<S> add(Vector<Integer,S> o, Mask<Integer, S> m) { 120 return bOp(o, m, (i, a, b) -> (int) (a + b)); 121 } 122 123 /** 124 * Adds this vector to the result of broadcasting an input scalar, 125 * selecting lane elements controlled by a mask. 126 * <p> 127 * This is a vector binary operation where the primitive addition operation 128 * ({@code +}) is applied to lane elements. 129 * 130 * @param b the input vector 131 * @param m the mask controlling lane selection 132 * @return the result of adding this vector to the broadcast of an input 133 * scalar 134 */ 135 public abstract IntVector<S> add(int b, Mask<Integer, S> m); 136 137 @Override 138 public IntVector<S> addSaturate(Vector<Integer,S> o) { 139 return bOp(o, (i, a, b) -> (int) ((a >= Integer.MAX_VALUE || Integer.MAX_VALUE - b > a) ? Integer.MAX_VALUE : a + b)); 140 } 141 142 public abstract IntVector<S> addSaturate(int o); 143 144 @Override 145 public IntVector<S> addSaturate(Vector<Integer,S> o, Mask<Integer, S> m) { 146 return bOp(o, m, (i, a, b) -> (int) ((a >= Integer.MAX_VALUE || Integer.MAX_VALUE - b > a) ? Integer.MAX_VALUE : a + b)); 147 } 148 149 public abstract IntVector<S> addSaturate(int o, Mask<Integer, S> m); 150 151 @Override 152 public IntVector<S> sub(Vector<Integer,S> o) { 153 return bOp(o, (i, a, b) -> (int) (a - b)); 154 } 155 156 public abstract IntVector<S> sub(int o); 157 158 @Override 159 public IntVector<S> sub(Vector<Integer,S> o, Mask<Integer, S> m) { 160 return bOp(o, m, (i, a, b) -> (int) (a - b)); 161 } 162 163 public abstract IntVector<S> sub(int o, Mask<Integer, S> m); 164 165 @Override 166 public IntVector<S> subSaturate(Vector<Integer,S> o) { 167 return bOp(o, (i, a, b) -> (int) ((a >= Integer.MIN_VALUE || Integer.MIN_VALUE + b > a) ? Integer.MAX_VALUE : a - b)); 168 } 169 170 public abstract IntVector<S> subSaturate(int o); 171 172 @Override 173 public IntVector<S> subSaturate(Vector<Integer,S> o, Mask<Integer, S> m) { 174 return bOp(o, m, (i, a, b) -> (int) ((a >= Integer.MIN_VALUE || Integer.MIN_VALUE + b > a) ? Integer.MAX_VALUE : a - b)); 175 } 176 177 public abstract IntVector<S> subSaturate(int o, Mask<Integer, S> m); 178 179 @Override 180 public IntVector<S> mul(Vector<Integer,S> o) { 181 return bOp(o, (i, a, b) -> (int) (a * b)); 182 } 183 184 public abstract IntVector<S> mul(int o); 185 186 @Override 187 public IntVector<S> mul(Vector<Integer,S> o, Mask<Integer, S> m) { 188 return bOp(o, m, (i, a, b) -> (int) (a * b)); 189 } 190 191 public abstract IntVector<S> mul(int o, Mask<Integer, S> m); 192 193 @Override 194 public IntVector<S> neg() { 195 return uOp((i, a) -> (int) (-a)); 196 } 197 198 @Override 199 public IntVector<S> neg(Mask<Integer, S> m) { 200 return uOp(m, (i, a) -> (int) (-a)); 201 } 202 203 @Override 204 public IntVector<S> abs() { 205 return uOp((i, a) -> (int) Math.abs(a)); 206 } 207 208 @Override 209 public IntVector<S> abs(Mask<Integer, S> m) { 210 return uOp(m, (i, a) -> (int) Math.abs(a)); 211 } 212 213 @Override 214 public IntVector<S> min(Vector<Integer,S> o) { 215 return bOp(o, (i, a, b) -> (a <= b) ? a : b); 216 } 217 218 public abstract IntVector<S> min(int o); 219 220 @Override 221 public IntVector<S> max(Vector<Integer,S> o) { 222 return bOp(o, (i, a, b) -> (a >= b) ? a : b); 223 } 224 225 public abstract IntVector<S> max(int o); 226 227 @Override 228 public Mask<Integer, S> equal(Vector<Integer,S> o) { 229 return bTest(o, (i, a, b) -> a == b); 230 } 231 232 public abstract Mask<Integer, S> equal(int o); 233 234 @Override 235 public Mask<Integer, S> notEqual(Vector<Integer,S> o) { 236 return bTest(o, (i, a, b) -> a != b); 237 } 238 239 public abstract Mask<Integer, S> notEqual(int o); 240 241 @Override 242 public Mask<Integer, S> lessThan(Vector<Integer,S> o) { 243 return bTest(o, (i, a, b) -> a < b); 244 } 245 246 public abstract Mask<Integer, S> lessThan(int o); 247 248 @Override 249 public Mask<Integer, S> lessThanEq(Vector<Integer,S> o) { 250 return bTest(o, (i, a, b) -> a <= b); 251 } 252 253 public abstract Mask<Integer, S> lessThanEq(int o); 254 255 @Override 256 public Mask<Integer, S> greaterThan(Vector<Integer,S> o) { 257 return bTest(o, (i, a, b) -> a > b); 258 } 259 260 public abstract Mask<Integer, S> greaterThan(int o); 261 262 @Override 263 public Mask<Integer, S> greaterThanEq(Vector<Integer,S> o) { 264 return bTest(o, (i, a, b) -> a >= b); 265 } 266 267 public abstract Mask<Integer, S> greaterThanEq(int o); 268 269 @Override 270 public IntVector<S> blend(Vector<Integer,S> o, Mask<Integer, S> m) { 271 return bOp(o, (i, a, b) -> m.getElement(i) ? b : a); 272 } 273 274 public abstract IntVector<S> blend(int o, Mask<Integer, S> m); 275 276 @Override 277 public abstract IntVector<S> shuffle(Vector<Integer,S> o, Shuffle<Integer, S> m); 278 279 @Override 280 public abstract IntVector<S> swizzle(Shuffle<Integer, S> m); 281 282 @Override 283 @ForceInline 284 public <T extends Shape> IntVector<T> resize(Species<Integer, T> species) { 285 return (IntVector<T>) species.reshape(this); 286 } 287 288 @Override 289 public abstract IntVector<S> rotateEL(int i); 290 291 @Override 292 public abstract IntVector<S> rotateER(int i); 293 294 @Override 295 public abstract IntVector<S> shiftEL(int i); 296 297 @Override 298 public abstract IntVector<S> shiftER(int i); 299 300 301 public IntVector<S> and(Vector<Integer,S> o) { 302 return bOp(o, (i, a, b) -> (int) (a & b)); 303 } 304 305 public abstract IntVector<S> and(int o); 306 307 public IntVector<S> and(Vector<Integer,S> o, Mask<Integer, S> m) { 308 return bOp(o, m, (i, a, b) -> (int) (a & b)); 309 } 310 311 public abstract IntVector<S> and(int o, Mask<Integer, S> m); 312 313 public IntVector<S> or(Vector<Integer,S> o) { 314 return bOp(o, (i, a, b) -> (int) (a | b)); 315 } 316 317 public abstract IntVector<S> or(int o); 318 319 public IntVector<S> or(Vector<Integer,S> o, Mask<Integer, S> m) { 320 return bOp(o, m, (i, a, b) -> (int) (a | b)); 321 } 322 323 public abstract IntVector<S> or(int o, Mask<Integer, S> m); 324 325 public IntVector<S> xor(Vector<Integer,S> o) { 326 return bOp(o, (i, a, b) -> (int) (a ^ b)); 327 } 328 329 public abstract IntVector<S> xor(int o); 330 331 public IntVector<S> xor(Vector<Integer,S> o, Mask<Integer, S> m) { 332 return bOp(o, m, (i, a, b) -> (int) (a ^ b)); 333 } 334 335 public abstract IntVector<S> xor(int o, Mask<Integer, S> m); 336 337 public IntVector<S> not() { 338 return uOp((i, a) -> (int) (~a)); 339 } 340 341 public IntVector<S> not(Mask<Integer, S> m) { 342 return uOp(m, (i, a) -> (int) (~a)); 343 } 344 345 // logical shift left 346 public IntVector<S> shiftL(int s) { 347 return uOp((i, a) -> (int) (a << s)); 348 } 349 350 public IntVector<S> shiftL(int s, Mask<Integer, S> m) { 351 return uOp(m, (i, a) -> (int) (a << s)); 352 } 353 354 public IntVector<S> shiftL(Vector<Integer,S> o) { 355 return bOp(o, (i, a, b) -> (int) (a << b)); 356 } 357 358 public IntVector<S> shiftL(Vector<Integer,S> o, Mask<Integer, S> m) { 359 return bOp(o, m, (i, a, b) -> (int) (a << b)); 360 } 361 362 // logical, or unsigned, shift right 363 public IntVector<S> shiftR(int s) { 364 return uOp((i, a) -> (int) (a >>> s)); 365 } 366 367 public IntVector<S> shiftR(int s, Mask<Integer, S> m) { 368 return uOp(m, (i, a) -> (int) (a >>> s)); 369 } 370 371 public IntVector<S> shiftR(Vector<Integer,S> o) { 372 return bOp(o, (i, a, b) -> (int) (a >>> b)); 373 } 374 375 public IntVector<S> shiftR(Vector<Integer,S> o, Mask<Integer, S> m) { 376 return bOp(o, m, (i, a, b) -> (int) (a >>> b)); 377 } 378 379 // arithmetic, or signed, shift right 380 public IntVector<S> aShiftR(int s) { 381 return uOp((i, a) -> (int) (a >> s)); 382 } 383 384 public IntVector<S> aShiftR(int s, Mask<Integer, S> m) { 385 return uOp(m, (i, a) -> (int) (a >> s)); 386 } 387 388 public IntVector<S> ashiftR(Vector<Integer,S> o) { 389 return bOp(o, (i, a, b) -> (int) (a >> b)); 390 } 391 392 public IntVector<S> ashiftR(Vector<Integer,S> o, Mask<Integer, S> m) { 393 return bOp(o, m, (i, a, b) -> (int) (a >> b)); 394 } 395 396 public IntVector<S> rotateL(int j) { 397 return uOp((i, a) -> (int) Integer.rotateLeft(a, j)); 398 } 399 400 public IntVector<S> rotateR(int j) { 401 return uOp((i, a) -> (int) Integer.rotateRight(a, j)); 402 } 403 404 @Override 405 public void intoByteArray(byte[] a, int ix) { 406 ByteBuffer bb = ByteBuffer.wrap(a, ix, a.length - ix); 407 intoByteBuffer(bb); 408 } 409 410 @Override 411 public void intoByteArray(byte[] a, int ix, Mask<Integer, S> m) { 412 ByteBuffer bb = ByteBuffer.wrap(a, ix, a.length - ix); 413 intoByteBuffer(bb, m); 414 } 415 416 @Override 417 public void intoByteBuffer(ByteBuffer bb) { 418 IntBuffer fb = bb.asIntBuffer(); 419 forEach((i, a) -> fb.put(a)); 420 } 421 422 @Override 423 public void intoByteBuffer(ByteBuffer bb, Mask<Integer, S> m) { 424 IntBuffer fb = bb.asIntBuffer(); 425 forEach((i, a) -> { 426 if (m.getElement(i)) 427 fb.put(a); 428 else 429 fb.position(fb.position() + 1); 430 }); 431 } 432 433 @Override 434 public void intoByteBuffer(ByteBuffer bb, int ix) { 435 bb = bb.duplicate().position(ix); 436 IntBuffer fb = bb.asIntBuffer(); 437 forEach((i, a) -> fb.put(i, a)); 438 } 439 440 @Override 441 public void intoByteBuffer(ByteBuffer bb, int ix, Mask<Integer, S> m) { 442 bb = bb.duplicate().position(ix); 443 IntBuffer fb = bb.asIntBuffer(); 444 forEach(m, (i, a) -> fb.put(i, a)); 445 } 446 447 448 // Type specific horizontal reductions 449 450 /** 451 * Sums all lane elements of this vector. 452 * <p> 453 * This is an associative vector reduction operation where the addition 454 * operation ({@code +}) is applied to lane elements, and the identity value 455 * is {@code 0}. 456 * 457 * @return the sum of all the lane elements of this vector 458 */ 459 public int addAll() { 460 return rOp((int) 0, (i, a, b) -> (int) (a + b)); 461 } 462 463 public int subAll() { 464 return rOp((int) 0, (i, a, b) -> (int) (a - b)); 465 } 466 467 public int mulAll() { 468 return rOp((int) 1, (i, a, b) -> (int) (a * b)); 469 } 470 471 public int minAll() { 472 return rOp(Integer.MAX_VALUE, (i, a, b) -> a > b ? b : a); 473 } 474 475 public int maxAll() { 476 return rOp(Integer.MIN_VALUE, (i, a, b) -> a < b ? b : a); 477 } 478 479 public int orAll() { 480 return rOp((int) 0, (i, a, b) -> (int) (a | b)); 481 } 482 483 public int andAll() { 484 return rOp((int) -1, (i, a, b) -> (int) (a & b)); 485 } 486 487 public int xorAll() { 488 return rOp((int) 0, (i, a, b) -> (int) (a ^ b)); 489 } 490 491 // Type specific accessors 492 493 /** 494 * Gets the lane element at lane index {@code i} 495 * 496 * @param i the lane index 497 * @return the lane element at lane index {@code i} 498 */ 499 public abstract int get(int i); 500 501 /** 502 * Replaces the lane element of this vector at lane index {@code i} with 503 * value {@code e}. 504 * <p> 505 * This is a cross-lane operation and behaves it returns the result of 506 * blending this vector with an input vector that is the result of 507 * broadcasting {@code e} and a mask that has only one lane set at lane 508 * index {@code i}. 509 * 510 * @param i the lane index of the lane element to be replaced 511 * @param e the value to be placed 512 * @return the result of replacing the lane element of this vector at lane 513 * index {@code i} with value {@code e}. 514 */ 515 public abstract IntVector<S> with(int i, int e); 516 517 // Type specific extractors 518 519 /** 520 * Returns an array containing the lane elements of this vector. 521 * <p> 522 * This method behaves as if it {@link #intoArray(int[], int)} stores} 523 * this vector into an allocated array and returns the array as follows: 524 * <pre>{@code 525 * int[] a = new int[this.length()]; 526 * this.intoArray(a, 0); 527 * return a; 528 * }</pre> 529 * 530 * @return an array containing the the lane elements of this vector 531 */ 532 @ForceInline 533 public int[] toArray() { 534 int[] a = new int[species().length()]; 535 intoArray(a, 0); 536 return a; 537 } 538 539 /** 540 * Stores this vector into an array starting at offset. 541 * <p> 542 * For each vector lane, where {@code N} is the vector lane index, 543 * the lane element at index {@code N} is stored into the array at index 544 * {@code i + N}. 545 * 546 * @param a the array 547 * @param i the offset into the array 548 * @throws IndexOutOfBoundsException if {@code i < 0}, or 549 * {@code i > a.length - this.length()} 550 */ 551 public void intoArray(int[] a, int i) { 552 forEach((n, e) -> a[i + n] = e); 553 } 554 555 /** 556 * Stores this vector into an array starting at offset and using a mask. 557 * <p> 558 * For each vector lane, where {@code N} is the vector lane index, 559 * if the mask lane at index {@code N} is set then the lane element at 560 * index {@code N} is stored into the array index {@code i + N}. 561 * 562 * @param a the array 563 * @param i the offset into the array 564 * @param m the mask 565 * @throws IndexOutOfBoundsException if {@code i < 0}, or 566 * for any vector lane index {@code N} where the mask at lane {@code N} 567 * is set {@code i >= a.length - N} 568 */ 569 public void intoArray(int[] a, int i, Mask<Integer, S> m) { 570 forEach(m, (n, e) -> a[i + n] = e); 571 } 572 573 /** 574 * Stores this vector into an array using indexes obtained from an index 575 * map. 576 * <p> 577 * For each vector lane, where {@code N} is the vector lane index, the 578 * lane element at index {@code N} is stored into the array at index 579 * {@code i + indexMap[j + N]}. 580 * 581 * @param a the array 582 * @param i the offset into the array, may be negative if relative 583 * indexes in the index map compensate to produce a value within the 584 * array bounds 585 * @param indexMap the index map 586 * @param j the offset into the index map 587 * @throws IndexOutOfBoundsException if {@code j < 0}, or 588 * {@code j > indexMap.length - this.length()}, 589 * or for any vector lane index {@code N} the result of 590 * {@code i + indexMap[j + N]} is {@code < 0} or {@code >= a.length} 591 */ 592 public void intoArray(int[] a, int i, int[] indexMap, int j) { 593 forEach((n, e) -> a[i + indexMap[j + n]] = e); 594 } 595 596 /** 597 * Stores this vector into an array using indexes obtained from an index 598 * map and using a mask. 599 * <p> 600 * For each vector lane, where {@code N} is the vector lane index, 601 * if the mask lane at index {@code N} is set then the lane element at 602 * index {@code N} is stored into the array at index 603 * {@code i + indexMap[j + N]}. 604 * 605 * @param a the array 606 * @param i the offset into the array, may be negative if relative 607 * indexes in the index map compensate to produce a value within the 608 * array bounds 609 * @param m the mask 610 * @param indexMap the index map 611 * @param j the offset into the index map 612 * @throws IndexOutOfBoundsException if {@code j < 0}, or 613 * {@code j > indexMap.length - this.length()}, 614 * or for any vector lane index {@code N} where the mask at lane 615 * {@code N} is set the result of {@code i + indexMap[j + N]} is 616 * {@code < 0} or {@code >= a.length} 617 */ 618 public void intoArray(int[] a, int i, Mask<Integer, S> m, int[] indexMap, int j) { 619 forEach(m, (n, e) -> a[i + indexMap[j + n]] = e); 620 } 621 622 // Species 623 624 @Override 625 public abstract IntSpecies<S> species(); 626 627 /** 628 * A specialized factory for creating {@link IntVector} value of the same 629 * shape, and a {@link Mask} and {@link Shuffle} values of the same shape 630 * and {@code int} element type. 631 * 632 * @param <S> the type of shape of this species 633 */ 634 public static abstract class IntSpecies<S extends Vector.Shape> extends Vector.Species<Integer, S> { 635 interface FOp { 636 int apply(int i); 637 } 638 639 abstract IntVector<S> op(FOp f); 640 641 abstract IntVector<S> op(Mask<Integer, S> m, FOp f); 642 643 // Factories 644 645 @Override 646 public IntVector<S> zero() { 647 return op(i -> 0); 648 } 649 650 /** 651 * Returns a vector where all lane elements are set to the primitive 652 * value {@code e}. 653 * 654 * @param e the value 655 * @return a vector of vector where all lane elements are set to 656 * the primitive value {@code e} 657 */ 658 public IntVector<S> broadcast(int e) { 659 return op(i -> e); 660 } 661 662 /** 663 * Returns a vector where the first lane element is set to the primtive 664 * value {@code e}, all other lane elements are set to the default 665 * value. 666 * 667 * @param e the value 668 * @return a vector where the first lane element is set to the primitive 669 * value {@code e} 670 */ 671 public IntVector<S> single(int e) { 672 return op(i -> i == 0 ? e : (int) 0); 673 } 674 675 /** 676 * Returns a vector where each lane element is set to a randomly 677 * generated primitive value. 678 * @@@ what are the properties of the random number generator? 679 * 680 * @return a vector where each lane elements is set to a randomly 681 * generated primitive value 682 */ 683 public IntVector<S> random() { 684 ThreadLocalRandom r = ThreadLocalRandom.current(); 685 return op(i -> r.nextInt()); 686 } 687 688 /** 689 * Returns a vector where each lane element is set to a given 690 * primitive value. 691 * <p> 692 * For each vector lane, where {@code N} is the vector lane index, the 693 * the primitive value at index {@code N} is placed into the resulting 694 * vector at lane index {@code N}. 695 * 696 * @@@ What should happen if es.length < this.length() ? use the default 697 * value or throw IndexOutOfBoundsException 698 * 699 * @param es the given primitive values 700 * @return a vector where each lane element is set to a given primitive 701 * value 702 */ 703 public IntVector<S> scalars(int... es) { 704 return op(i -> es[i]); 705 } 706 707 /** 708 * Loads a vector from an array starting at offset. 709 * <p> 710 * For each vector lane, where {@code N} is the vector lane index, the 711 * array element at index {@code i + N} is placed into the 712 * resulting vector at lane index {@code N}. 713 * 714 * @param a the array 715 * @param i the offset into the array 716 * @return the vector loaded from an array 717 * @throws IndexOutOfBoundsException if {@code i < 0}, or 718 * {@code i > a.length - this.length()} 719 */ 720 public IntVector<S> fromArray(int[] a, int i) { 721 return op(n -> a[i + n]); 722 } 723 724 /** 725 * Loads a vector from an array starting at offset and using a mask. 726 * <p> 727 * For each vector lane, where {@code N} is the vector lane index, 728 * if the mask lane at index {@code N} is set then the array element at 729 * index {@code i + N} is placed into the resulting vector at lane index 730 * {@code N}, otherwise the default element value is placed into the 731 * resulting vector at lane index {@code N}. 732 * 733 * @param a the array 734 * @param i the offset into the array 735 * @param m the mask 736 * @return the vector loaded from an array 737 * @throws IndexOutOfBoundsException if {@code i < 0}, or 738 * for any vector lane index {@code N} where the mask at lane {@code N} 739 * is set {@code i > a.length - N} 740 */ 741 public IntVector<S> fromArray(int[] a, int i, Mask<Integer, S> m) { 742 return op(m, n -> a[i + n]); 743 } 744 745 /** 746 * Loads a vector from an array using indexes obtained from an index 747 * map. 748 * <p> 749 * For each vector lane, where {@code N} is the vector lane index, the 750 * array element at index {@code i + indexMap[j + N]} is placed into the 751 * resulting vector at lane index {@code N}. 752 * 753 * @param a the array 754 * @param i the offset into the array, may be negative if relative 755 * indexes in the index map compensate to produce a value within the 756 * array bounds 757 * @param indexMap the index map 758 * @param j the offset into the index map 759 * @return the vector loaded from an array 760 * @throws IndexOutOfBoundsException if {@code j < 0}, or 761 * {@code j > indexMap.length - this.length()}, 762 * or for any vector lane index {@code N} the result of 763 * {@code i + indexMap[j + N]} is {@code < 0} or {@code >= a.length} 764 */ 765 public IntVector<S> fromArray(int[] a, int i, int[] indexMap, int j) { 766 return op(n -> a[i + indexMap[j + n]]); 767 } 768 769 /** 770 * Loads a vector from an array using indexes obtained from an index 771 * map and using a mask. 772 * <p> 773 * For each vector lane, where {@code N} is the vector lane index, 774 * if the mask lane at index {@code N} is set then the array element at 775 * index {@code i + indexMap[j + N]} is placed into the resulting vector 776 * at lane index {@code N}. 777 * 778 * @param a the array 779 * @param i the offset into the array, may be negative if relative 780 * indexes in the index map compensate to produce a value within the 781 * array bounds 782 * @param indexMap the index map 783 * @param j the offset into the index map 784 * @return the vector loaded from an array 785 * @throws IndexOutOfBoundsException if {@code j < 0}, or 786 * {@code j > indexMap.length - this.length()}, 787 * or for any vector lane index {@code N} where the mask at lane 788 * {@code N} is set the result of {@code i + indexMap[j + N]} is 789 * {@code < 0} or {@code >= a.length} 790 */ 791 public IntVector<S> fromArray(int[] a, int i, Mask<Integer, S> m, int[] indexMap, int j) { 792 return op(m, n -> a[i + indexMap[j + n]]); 793 } 794 795 @Override 796 public IntVector<S> fromByteArray(byte[] a, int ix) { 797 ByteBuffer bb = ByteBuffer.wrap(a, ix, a.length - ix); 798 return fromByteBuffer(bb); 799 } 800 801 @Override 802 public IntVector<S> fromByteArray(byte[] a, int ix, Mask<Integer, S> m) { 803 ByteBuffer bb = ByteBuffer.wrap(a, ix, a.length - ix); 804 return fromByteBuffer(bb, m); 805 } 806 807 @Override 808 public IntVector<S> fromByteBuffer(ByteBuffer bb) { 809 IntBuffer fb = bb.asIntBuffer(); 810 return op(i -> fb.get()); 811 } 812 813 @Override 814 public IntVector<S> fromByteBuffer(ByteBuffer bb, Mask<Integer, S> m) { 815 IntBuffer fb = bb.asIntBuffer(); 816 return op(i -> { 817 if(m.getElement(i)) 818 return fb.get(); 819 else { 820 fb.position(fb.position() + 1); 821 return (int) 0; 822 } 823 }); 824 } 825 826 @Override 827 public IntVector<S> fromByteBuffer(ByteBuffer bb, int ix) { 828 bb = bb.duplicate().position(ix); 829 IntBuffer fb = bb.asIntBuffer(); 830 return op(i -> fb.get(i)); 831 } 832 833 @Override 834 public IntVector<S> fromByteBuffer(ByteBuffer bb, int ix, Mask<Integer, S> m) { 835 bb = bb.duplicate().position(ix); 836 IntBuffer fb = bb.asIntBuffer(); 837 return op(m, i -> fb.get(i)); 838 } 839 840 @Override 841 public <F, T extends Shape> IntVector<S> reshape(Vector<F, T> o) { 842 int blen = Math.max(o.species().bitSize(), bitSize()) / Byte.SIZE; 843 ByteBuffer bb = ByteBuffer.allocate(blen).order(ByteOrder.nativeOrder()); 844 o.intoByteBuffer(bb, 0); 845 return fromByteBuffer(bb, 0); 846 } 847 848 @Override 849 @ForceInline 850 public <F> IntVector<S> rebracket(Vector<F, S> o) { 851 return reshape(o); 852 } 853 854 @Override 855 @ForceInline 856 public <T extends Shape> IntVector<S> resize(Vector<Integer, T> o) { 857 return reshape(o); 858 } 859 860 @Override 861 @SuppressWarnings("unchecked") 862 public <F, T extends Shape> IntVector<S> cast(Vector<F, T> v) { 863 // Allocate array of required size 864 int[] a = new int[length()]; 865 866 Class<?> vtype = v.species().elementType(); 867 int limit = Math.min(v.species().length(), length()); 868 if (vtype == byte.class) { 869 ByteVector<T> tv = (ByteVector<T>)v; 870 for (int i = 0; i < limit; i++) { 871 a[i] = (int) tv.get(i); 872 } 873 } else if (vtype == short.class) { 874 ShortVector<T> tv = (ShortVector<T>)v; 875 for (int i = 0; i < limit; i++) { 876 a[i] = (int) tv.get(i); 877 } 878 } else if (vtype == int.class) { 879 IntVector<T> tv = (IntVector<T>)v; 880 for (int i = 0; i < limit; i++) { 881 a[i] = (int) tv.get(i); 882 } 883 } else if (vtype == long.class){ 884 LongVector<T> tv = (LongVector<T>)v; 885 for (int i = 0; i < limit; i++) { 886 a[i] = (int) tv.get(i); 887 } 888 } else if (vtype == float.class){ 889 FloatVector<T> tv = (FloatVector<T>)v; 890 for (int i = 0; i < limit; i++) { 891 a[i] = (int) tv.get(i); 892 } 893 } else if (vtype == double.class){ 894 DoubleVector<T> tv = (DoubleVector<T>)v; 895 for (int i = 0; i < limit; i++) { 896 a[i] = (int) tv.get(i); 897 } 898 } else { 899 throw new UnsupportedOperationException("Bad lane type for casting."); 900 } 901 902 return scalars(a); 903 } 904 905 } 906 907 /** 908 * Finds the preferred species for an element type of {@code int}. 909 * <p> 910 * A preferred species is a species chosen by the platform that has a 911 * shape of maximal bit size. A preferred species for different element 912 * types will have the same shape, and therefore vectors, masks, and 913 * shuffles created from such species will be shape compatible. 914 * 915 * @return the preferred species for an element type of {@code int} 916 */ 917 @SuppressWarnings("unchecked") 918 public static IntSpecies<?> preferredSpeciesInstance() { 919 return (IntSpecies<?>) Vector.preferredSpeciesInstance(int.class); 920 } 921 922 /** 923 * Finds a species for an element type of {@code int} and shape. 924 * 925 * @param s the shape 926 * @param <S> the type of shape 927 * @return a species for an element type of {@code int} and shape 928 * @throws IllegalArgumentException if no such species exists for the shape 929 */ 930 @SuppressWarnings("unchecked") 931 public static <S extends Shape> IntSpecies<S> speciesInstance(S s) { 932 Objects.requireNonNull(s); 933 if (s == Shapes.S_64_BIT) { 934 return (IntSpecies<S>) Int64Vector.SPECIES; 935 } else if (s == Shapes.S_128_BIT) { 936 return (IntSpecies<S>) Int128Vector.SPECIES; 937 } else if (s == Shapes.S_256_BIT) { 938 return (IntSpecies<S>) Int256Vector.SPECIES; 939 } else if (s == Shapes.S_512_BIT) { 940 return (IntSpecies<S>) Int512Vector.SPECIES; 941 } else { 942 throw new IllegalArgumentException("Bad shape: " + s); 943 } 944 } 945 }