< prev index next >

src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java

Print this page
rev 55589 : Species-phase2
rev 55590 : added missing javadocs, changed jtreg test
rev 55591 : XxxSpecies made package private
rev 55592 : Capitalized Species names


  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 java.nio.ByteBuffer;
  28 import java.nio.IntBuffer;
  29 import java.nio.ByteOrder;
  30 import java.util.Objects;
  31 import java.util.function.IntUnaryOperator;

  32 import java.util.concurrent.ThreadLocalRandom;
  33 
  34 import jdk.internal.misc.Unsafe;
  35 import jdk.internal.vm.annotation.ForceInline;
  36 import static jdk.incubator.vector.VectorIntrinsics.*;
  37 
  38 
  39 /**
  40  * A specialized {@link Vector} representing an ordered immutable sequence of
  41  * {@code int} values.
  42  */
  43 @SuppressWarnings("cast")
  44 public abstract class IntVector extends Vector<Integer> {
  45 
  46     IntVector() {}
  47 
  48     private static final int ARRAY_SHIFT = 31 - Integer.numberOfLeadingZeros(Unsafe.ARRAY_INT_INDEX_SCALE);
  49 
  50     // Unary operator
  51 


  93 
  94     interface FUnCon {
  95         void apply(int i, int a);
  96     }
  97 
  98     abstract void forEach(FUnCon f);
  99 
 100     abstract void forEach(Mask<Integer> m, FUnCon f);
 101 
 102     // Static factories
 103 
 104     /**
 105      * Returns a vector where all lane elements are set to the default
 106      * primitive value.
 107      *
 108      * @param species species of desired vector
 109      * @return a zero vector of given species
 110      */
 111     @ForceInline
 112     @SuppressWarnings("unchecked")
 113     public static IntVector zero(IntSpecies species) {
 114         return species.zero();


 115     }
 116 
 117     /**
 118      * Loads a vector from a byte array starting at an offset.
 119      * <p>
 120      * Bytes are composed into primitive lane elements according to the
 121      * native byte order of the underlying platform
 122      * <p>
 123      * This method behaves as if it returns the result of calling the
 124      * byte buffer, offset, and mask accepting
 125      * {@link #fromByteBuffer(IntSpecies, ByteBuffer, int, Mask) method} as follows:
 126      * <pre>{@code
 127      * return this.fromByteBuffer(ByteBuffer.wrap(a), i, this.maskAllTrue());
 128      * }</pre>
 129      *
 130      * @param species species of desired vector
 131      * @param a the byte array
 132      * @param ix the offset into the array
 133      * @return a vector loaded from a byte array
 134      * @throws IndexOutOfBoundsException if {@code i < 0} or
 135      * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)}
 136      */
 137     @ForceInline
 138     @SuppressWarnings("unchecked")
 139     public static IntVector fromByteArray(IntSpecies species, byte[] a, int ix) {
 140         Objects.requireNonNull(a);
 141         ix = VectorIntrinsics.checkIndex(ix, a.length, species.bitSize() / Byte.SIZE);
 142         return VectorIntrinsics.load((Class<IntVector>) species.boxType(), int.class, species.length(),
 143                                      a, ((long) ix) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
 144                                      a, ix, species,
 145                                      (c, idx, s) -> {
 146                                          ByteBuffer bbc = ByteBuffer.wrap(c, idx, a.length - idx).order(ByteOrder.nativeOrder());
 147                                          IntBuffer tb = bbc.asIntBuffer();
 148                                          return ((IntSpecies)s).op(i -> tb.get());
 149                                      });
 150     }
 151 
 152     /**
 153      * Loads a vector from a byte array starting at an offset and using a
 154      * mask.
 155      * <p>
 156      * Bytes are composed into primitive lane elements according to the
 157      * native byte order of the underlying platform.
 158      * <p>
 159      * This method behaves as if it returns the result of calling the
 160      * byte buffer, offset, and mask accepting
 161      * {@link #fromByteBuffer(IntSpecies, ByteBuffer, int, Mask) method} as follows:
 162      * <pre>{@code
 163      * return this.fromByteBuffer(ByteBuffer.wrap(a), i, m);
 164      * }</pre>
 165      *
 166      * @param species species of desired vector
 167      * @param a the byte array
 168      * @param ix the offset into the array
 169      * @param m the mask
 170      * @return a vector loaded from a byte array
 171      * @throws IndexOutOfBoundsException if {@code i < 0} or
 172      * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)}
 173      * @throws IndexOutOfBoundsException if the offset is {@code < 0},
 174      * or {@code > a.length},
 175      * for any vector lane index {@code N} where the mask at lane {@code N}
 176      * is set
 177      * {@code i >= a.length - (N * this.elementSize() / Byte.SIZE)}
 178      */
 179     @ForceInline
 180     public static IntVector fromByteArray(IntSpecies species, byte[] a, int ix, Mask<Integer> m) {
 181         return zero(species).blend(fromByteArray(species, a, ix), m);
 182     }
 183 
 184     /**
 185      * Loads a vector from an array starting at offset.
 186      * <p>
 187      * For each vector lane, where {@code N} is the vector lane index, the
 188      * array element at index {@code i + N} is placed into the
 189      * resulting vector at lane index {@code N}.
 190      *
 191      * @param species species of desired vector
 192      * @param a the array
 193      * @param i the offset into the array
 194      * @return the vector loaded from an array
 195      * @throws IndexOutOfBoundsException if {@code i < 0}, or
 196      * {@code i > a.length - this.length()}
 197      */
 198     @ForceInline
 199     @SuppressWarnings("unchecked")
 200     public static IntVector fromArray(IntSpecies species, int[] a, int i){
 201         Objects.requireNonNull(a);
 202         i = VectorIntrinsics.checkIndex(i, a.length, species.length());
 203         return VectorIntrinsics.load((Class<IntVector>) species.boxType(), int.class, species.length(),
 204                                      a, (((long) i) << ARRAY_SHIFT) + Unsafe.ARRAY_INT_BASE_OFFSET,
 205                                      a, i, species,
 206                                      (c, idx, s) -> ((IntSpecies)s).op(n -> c[idx + n]));
 207     }
 208 
 209 
 210     /**
 211      * Loads a vector from an array starting at offset and using a mask.
 212      * <p>
 213      * For each vector lane, where {@code N} is the vector lane index,
 214      * if the mask lane at index {@code N} is set then the array element at
 215      * index {@code i + N} is placed into the resulting vector at lane index
 216      * {@code N}, otherwise the default element value is placed into the
 217      * resulting vector at lane index {@code N}.
 218      *
 219      * @param species species of desired vector
 220      * @param a the array
 221      * @param i the offset into the array
 222      * @param m the mask
 223      * @return the vector loaded from an array
 224      * @throws IndexOutOfBoundsException if {@code i < 0}, or
 225      * for any vector lane index {@code N} where the mask at lane {@code N}
 226      * is set {@code i > a.length - N}
 227      */
 228     @ForceInline
 229     public static IntVector fromArray(IntSpecies species, int[] a, int i, Mask<Integer> m) {
 230         return zero(species).blend(fromArray(species, a, i), m);
 231     }
 232 
 233     /**
 234      * Loads a vector from an array using indexes obtained from an index
 235      * map.
 236      * <p>
 237      * For each vector lane, where {@code N} is the vector lane index, the
 238      * array element at index {@code i + indexMap[j + N]} is placed into the
 239      * resulting vector at lane index {@code N}.
 240      *
 241      * @param species species of desired vector
 242      * @param a the array
 243      * @param i the offset into the array, may be negative if relative
 244      * indexes in the index map compensate to produce a value within the
 245      * array bounds
 246      * @param indexMap the index map
 247      * @param j the offset into the index map
 248      * @return the vector loaded from an array
 249      * @throws IndexOutOfBoundsException if {@code j < 0}, or
 250      * {@code j > indexMap.length - this.length()},
 251      * or for any vector lane index {@code N} the result of
 252      * {@code i + indexMap[j + N]} is {@code < 0} or {@code >= a.length}
 253      */
 254     @ForceInline
 255     @SuppressWarnings("unchecked")
 256     public static IntVector fromArray(IntSpecies species, int[] a, int i, int[] indexMap, int j) {
 257         Objects.requireNonNull(a);
 258         Objects.requireNonNull(indexMap);
 259 
 260 
 261         // Index vector: vix[0:n] = k -> i + indexMap[j + i]
 262         IntVector vix = IntVector.fromArray(species.indexSpecies(), indexMap, j).add(i);
 263 
 264         vix = VectorIntrinsics.checkIndex(vix, a.length);
 265 
 266         return VectorIntrinsics.loadWithMap((Class<IntVector>) species.boxType(), int.class, species.length(),
 267                                             species.indexSpecies().vectorType(), a, Unsafe.ARRAY_INT_BASE_OFFSET, vix,
 268                                             a, i, indexMap, j, species,
 269                                            (c, idx, iMap, idy, s) -> ((IntSpecies)s).op(n -> c[idx + iMap[idy+n]]));

 270         }
 271 
 272     /**
 273      * Loads a vector from an array using indexes obtained from an index
 274      * map and using a mask.
 275      * <p>
 276      * For each vector lane, where {@code N} is the vector lane index,
 277      * if the mask lane at index {@code N} is set then the array element at
 278      * index {@code i + indexMap[j + N]} is placed into the resulting vector
 279      * at lane index {@code N}.
 280      *
 281      * @param species species of desired vector
 282      * @param a the array
 283      * @param i the offset into the array, may be negative if relative
 284      * indexes in the index map compensate to produce a value within the
 285      * array bounds
 286      * @param m the mask
 287      * @param indexMap the index map
 288      * @param j the offset into the index map
 289      * @return the vector loaded from an array
 290      * @throws IndexOutOfBoundsException if {@code j < 0}, or
 291      * {@code j > indexMap.length - this.length()},
 292      * or for any vector lane index {@code N} where the mask at lane
 293      * {@code N} is set the result of {@code i + indexMap[j + N]} is
 294      * {@code < 0} or {@code >= a.length}
 295      */
 296     @ForceInline
 297     @SuppressWarnings("unchecked")
 298     public static IntVector fromArray(IntSpecies species, int[] a, int i, Mask<Integer> m, int[] indexMap, int j) {
 299         // @@@ This can result in out of bounds errors for unset mask lanes
 300         return zero(species).blend(fromArray(species, a, i, indexMap, j), m);
 301     }
 302 
 303 
 304     /**
 305      * Loads a vector from a {@link ByteBuffer byte buffer} starting at an
 306      * offset into the byte buffer.
 307      * <p>
 308      * Bytes are composed into primitive lane elements according to the
 309      * native byte order of the underlying platform.
 310      * <p>
 311      * This method behaves as if it returns the result of calling the
 312      * byte buffer, offset, and mask accepting
 313      * {@link #fromByteBuffer(IntSpecies, ByteBuffer, int, Mask)} method} as follows:
 314      * <pre>{@code
 315      *   return this.fromByteBuffer(b, i, this.maskAllTrue())
 316      * }</pre>
 317      *
 318      * @param species species of desired vector
 319      * @param bb the byte buffer
 320      * @param ix the offset into the byte buffer
 321      * @return a vector loaded from a byte buffer
 322      * @throws IndexOutOfBoundsException if the offset is {@code < 0},
 323      * or {@code > b.limit()},
 324      * or if there are fewer than
 325      * {@code this.length() * this.elementSize() / Byte.SIZE} bytes
 326      * remaining in the byte buffer from the given offset
 327      */
 328     @ForceInline
 329     @SuppressWarnings("unchecked")
 330     public static IntVector fromByteBuffer(IntSpecies species, ByteBuffer bb, int ix) {
 331         if (bb.order() != ByteOrder.nativeOrder()) {
 332             throw new IllegalArgumentException();
 333         }
 334         ix = VectorIntrinsics.checkIndex(ix, bb.limit(), species.bitSize() / Byte.SIZE);
 335         return VectorIntrinsics.load((Class<IntVector>) species.boxType(), int.class, species.length(),
 336                                      U.getReference(bb, BYTE_BUFFER_HB), U.getLong(bb, BUFFER_ADDRESS) + ix,
 337                                      bb, ix, species,
 338                                      (c, idx, s) -> {
 339                                          ByteBuffer bbc = c.duplicate().position(idx).order(ByteOrder.nativeOrder());
 340                                          IntBuffer tb = bbc.asIntBuffer();
 341                                          return ((IntSpecies)s).op(i -> tb.get());
 342                                      });
 343     }
 344 
 345     /**
 346      * Loads a vector from a {@link ByteBuffer byte buffer} starting at an
 347      * offset into the byte buffer and using a mask.
 348      * <p>
 349      * This method behaves as if the byte buffer is viewed as a primitive
 350      * {@link java.nio.Buffer buffer} for the primitive element type,


 362      * e[] es = new e[this.length()];
 363      * for (int n = 0; n < t.length; n++) {
 364      *     if (m.isSet(n))
 365      *         es[n] = eb.get(n);
 366      * }
 367      * Vector<E> r = ((ESpecies<S>)this).fromArray(es, 0, m);
 368      * }</pre>
 369      *
 370      * @param species species of desired vector
 371      * @param bb the byte buffer
 372      * @param ix the offset into the byte buffer
 373      * @param m the mask
 374      * @return a vector loaded from a byte buffer
 375      * @throws IndexOutOfBoundsException if the offset is {@code < 0},
 376      * or {@code > b.limit()},
 377      * for any vector lane index {@code N} where the mask at lane {@code N}
 378      * is set
 379      * {@code i >= b.limit() - (N * this.elementSize() / Byte.SIZE)}
 380      */
 381     @ForceInline
 382     public static IntVector fromByteBuffer(IntSpecies species, ByteBuffer bb, int ix, Mask<Integer> m) {
 383         return zero(species).blend(fromByteBuffer(species, bb, ix), m);
 384     }
 385 
 386     /**










































































 387      * Returns a mask where each lane is set or unset according to given
 388      * {@code boolean} values
 389      * <p>
 390      * For each mask lane, where {@code N} is the mask lane index,
 391      * if the given {@code boolean} value at index {@code N} is {@code true}
 392      * then the mask lane at index {@code N} is set, otherwise it is unset.
 393      *
 394      * @param species mask species
 395      * @param bits the given {@code boolean} values
 396      * @return a mask where each lane is set or unset according to the given {@code boolean} value
 397      * @throws IndexOutOfBoundsException if {@code bits.length < species.length()}
 398      */
 399     @ForceInline
 400     public static Mask<Integer> maskFromValues(IntSpecies species, boolean... bits) {
 401         if (species.boxType() == IntMaxVector.class)
 402             return new IntMaxVector.IntMaxMask(bits);
 403         switch (species.bitSize()) {
 404             case 64: return new Int64Vector.Int64Mask(bits);
 405             case 128: return new Int128Vector.Int128Mask(bits);
 406             case 256: return new Int256Vector.Int256Mask(bits);
 407             case 512: return new Int512Vector.Int512Mask(bits);
 408             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 409         }
 410     }
 411 
 412     // @@@ This is a bad implementation -- makes lambdas capturing -- fix this
 413     static Mask<Integer> trueMask(IntSpecies species) {
 414         if (species.boxType() == IntMaxVector.class)
 415             return IntMaxVector.IntMaxMask.TRUE_MASK;
 416         switch (species.bitSize()) {
 417             case 64: return Int64Vector.Int64Mask.TRUE_MASK;
 418             case 128: return Int128Vector.Int128Mask.TRUE_MASK;
 419             case 256: return Int256Vector.Int256Mask.TRUE_MASK;
 420             case 512: return Int512Vector.Int512Mask.TRUE_MASK;
 421             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 422         }
 423     }
 424 
 425     static Mask<Integer> falseMask(IntSpecies species) {
 426         if (species.boxType() == IntMaxVector.class)
 427             return IntMaxVector.IntMaxMask.FALSE_MASK;
 428         switch (species.bitSize()) {
 429             case 64: return Int64Vector.Int64Mask.FALSE_MASK;
 430             case 128: return Int128Vector.Int128Mask.FALSE_MASK;
 431             case 256: return Int256Vector.Int256Mask.FALSE_MASK;
 432             case 512: return Int512Vector.Int512Mask.FALSE_MASK;
 433             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 434         }
 435     }
 436 
 437     /**
 438      * Loads a mask from a {@code boolean} array starting at an offset.
 439      * <p>
 440      * For each mask lane, where {@code N} is the mask lane index,
 441      * if the array element at index {@code ix + N} is {@code true} then the
 442      * mask lane at index {@code N} is set, otherwise it is unset.
 443      *
 444      * @param species mask species
 445      * @param bits the {@code boolean} array
 446      * @param ix the offset into the array
 447      * @return the mask loaded from a {@code boolean} array
 448      * @throws IndexOutOfBoundsException if {@code ix < 0}, or
 449      * {@code ix > bits.length - species.length()}
 450      */
 451     @ForceInline
 452     @SuppressWarnings("unchecked")
 453     public static Mask<Integer> maskFromArray(IntSpecies species, boolean[] bits, int ix) {
 454         Objects.requireNonNull(bits);
 455         ix = VectorIntrinsics.checkIndex(ix, bits.length, species.length());
 456         return VectorIntrinsics.load((Class<Mask<Integer>>) species.maskType(), int.class, species.length(),
 457                                      bits, (((long) ix) << ARRAY_SHIFT) + Unsafe.ARRAY_BOOLEAN_BASE_OFFSET,
 458                                      bits, ix, species,
 459                                      (c, idx, s) -> (Mask<Integer>) ((IntSpecies)s).opm(n -> c[idx + n]));
 460     }
 461 
 462     /**
 463      * Returns a mask where all lanes are set.
 464      *
 465      * @param species mask species
 466      * @return a mask where all lanes are set
 467      */
 468     @ForceInline
 469     @SuppressWarnings("unchecked")
 470     public static Mask<Integer> maskAllTrue(IntSpecies species) {
 471         return VectorIntrinsics.broadcastCoerced((Class<Mask<Integer>>) species.maskType(), int.class, species.length(),
 472                                                  (int)-1,  species,
 473                                                  ((z, s) -> trueMask((IntSpecies)s)));
 474     }
 475 
 476     /**
 477      * Returns a mask where all lanes are unset.
 478      *
 479      * @param species mask species
 480      * @return a mask where all lanes are unset
 481      */
 482     @ForceInline
 483     @SuppressWarnings("unchecked")
 484     public static Mask<Integer> maskAllFalse(IntSpecies species) {
 485         return VectorIntrinsics.broadcastCoerced((Class<Mask<Integer>>) species.maskType(), int.class, species.length(),
 486                                                  0, species, 
 487                                                  ((z, s) -> falseMask((IntSpecies)s)));
 488     }
 489 
 490     /**
 491      * Returns a shuffle of mapped indexes where each lane element is
 492      * the result of applying a mapping function to the corresponding lane
 493      * index.
 494      * <p>
 495      * Care should be taken to ensure Shuffle values produced from this
 496      * method are consumed as constants to ensure optimal generation of
 497      * code.  For example, values held in static final fields or values
 498      * held in loop constant local variables.
 499      * <p>
 500      * This method behaves as if a shuffle is created from an array of
 501      * mapped indexes as follows:
 502      * <pre>{@code
 503      *   int[] a = new int[species.length()];
 504      *   for (int i = 0; i < a.length; i++) {
 505      *       a[i] = f.applyAsInt(i);
 506      *   }
 507      *   return this.shuffleFromValues(a);
 508      * }</pre>
 509      *
 510      * @param species shuffle species
 511      * @param f the lane index mapping function
 512      * @return a shuffle of mapped indexes
 513      */
 514     @ForceInline
 515     public static Shuffle<Integer> shuffle(IntSpecies species, IntUnaryOperator f) {
 516         if (species.boxType() == IntMaxVector.class)
 517             return new IntMaxVector.IntMaxShuffle(f);
 518         switch (species.bitSize()) {
 519             case 64: return new Int64Vector.Int64Shuffle(f);
 520             case 128: return new Int128Vector.Int128Shuffle(f);
 521             case 256: return new Int256Vector.Int256Shuffle(f);
 522             case 512: return new Int512Vector.Int512Shuffle(f);
 523             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 524         }
 525     }
 526 
 527     /**
 528      * Returns a shuffle where each lane element is the value of its
 529      * corresponding lane index.
 530      * <p>
 531      * This method behaves as if a shuffle is created from an identity
 532      * index mapping function as follows:
 533      * <pre>{@code
 534      *   return this.shuffle(i -> i);
 535      * }</pre>
 536      *
 537      * @param species shuffle species
 538      * @return a shuffle of lane indexes
 539      */
 540     @ForceInline
 541     public static Shuffle<Integer> shuffleIota(IntSpecies species) {
 542         if (species.boxType() == IntMaxVector.class)
 543             return new IntMaxVector.IntMaxShuffle(AbstractShuffle.IDENTITY);
 544         switch (species.bitSize()) {
 545             case 64: return new Int64Vector.Int64Shuffle(AbstractShuffle.IDENTITY);
 546             case 128: return new Int128Vector.Int128Shuffle(AbstractShuffle.IDENTITY);
 547             case 256: return new Int256Vector.Int256Shuffle(AbstractShuffle.IDENTITY);
 548             case 512: return new Int512Vector.Int512Shuffle(AbstractShuffle.IDENTITY);
 549             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 550         }
 551     }
 552 
 553     /**
 554      * Returns a shuffle where each lane element is set to a given
 555      * {@code int} value logically AND'ed by the species length minus one.
 556      * <p>
 557      * For each shuffle lane, where {@code N} is the shuffle lane index, the
 558      * the {@code int} value at index {@code N} logically AND'ed by
 559      * {@code species.length() - 1} is placed into the resulting shuffle at
 560      * lane index {@code N}.
 561      *
 562      * @param species shuffle species
 563      * @param ixs the given {@code int} values
 564      * @return a shuffle where each lane element is set to a given
 565      * {@code int} value
 566      * @throws IndexOutOfBoundsException if the number of int values is
 567      * {@code < species.length()}
 568      */
 569     @ForceInline
 570     public static Shuffle<Integer> shuffleFromValues(IntSpecies species, int... ixs) {
 571         if (species.boxType() == IntMaxVector.class)
 572             return new IntMaxVector.IntMaxShuffle(ixs);
 573         switch (species.bitSize()) {
 574             case 64: return new Int64Vector.Int64Shuffle(ixs);
 575             case 128: return new Int128Vector.Int128Shuffle(ixs);
 576             case 256: return new Int256Vector.Int256Shuffle(ixs);
 577             case 512: return new Int512Vector.Int512Shuffle(ixs);
 578             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 579         }
 580     }
 581 
 582     /**
 583      * Loads a shuffle from an {@code int} array starting at an offset.
 584      * <p>
 585      * For each shuffle lane, where {@code N} is the shuffle lane index, the
 586      * array element at index {@code i + N} logically AND'ed by
 587      * {@code species.length() - 1} is placed into the resulting shuffle at lane
 588      * index {@code N}.
 589      *
 590      * @param species shuffle species
 591      * @param ixs the {@code int} array
 592      * @param i the offset into the array
 593      * @return a shuffle loaded from the {@code int} array
 594      * @throws IndexOutOfBoundsException if {@code i < 0}, or
 595      * {@code i > a.length - species.length()}
 596      */
 597     @ForceInline
 598     public static Shuffle<Integer> shuffleFromArray(IntSpecies species, int[] ixs, int i) {
 599         if (species.boxType() == IntMaxVector.class)
 600             return new IntMaxVector.IntMaxShuffle(ixs, i);
 601         switch (species.bitSize()) {
 602             case 64: return new Int64Vector.Int64Shuffle(ixs, i);
 603             case 128: return new Int128Vector.Int128Shuffle(ixs, i);
 604             case 256: return new Int256Vector.Int256Shuffle(ixs, i);
 605             case 512: return new Int512Vector.Int512Shuffle(ixs, i);
 606             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 607         }
 608     }
 609 
 610 
 611     // Ops
 612 
 613     @Override
 614     public abstract IntVector add(Vector<Integer> v);
 615 
 616     /**
 617      * Adds this vector to the broadcast of an input scalar.
 618      * <p>
 619      * This is a vector binary operation where the primitive addition operation
 620      * ({@code +}) is applied to lane elements.
 621      *
 622      * @param s the input scalar
 623      * @return the result of adding this vector to the broadcast of an input
 624      * scalar
 625      */
 626     public abstract IntVector add(int s);
 627 
 628     @Override
 629     public abstract IntVector add(Vector<Integer> v, Mask<Integer> m);
 630 


1602      * index {@code N} is stored into the array at index
1603      * {@code i + indexMap[j + N]}.
1604      *
1605      * @param a the array
1606      * @param i the offset into the array, may be negative if relative
1607      * indexes in the index map compensate to produce a value within the
1608      * array bounds
1609      * @param m the mask
1610      * @param indexMap the index map
1611      * @param j the offset into the index map
1612      * @throws IndexOutOfBoundsException if {@code j < 0}, or
1613      * {@code j > indexMap.length - this.length()},
1614      * or for any vector lane index {@code N} where the mask at lane
1615      * {@code N} is set the result of {@code i + indexMap[j + N]} is
1616      * {@code < 0} or {@code >= a.length}
1617      */
1618     public abstract void intoArray(int[] a, int i, Mask<Integer> m, int[] indexMap, int j);
1619     // Species
1620 
1621     @Override
1622     public abstract IntSpecies species();
1623 
1624     /**
1625      * Class representing {@link IntVector}'s of the same {@link Vector.Shape Shape}.
1626      */
1627     public static abstract class IntSpecies extends Vector.Species<Integer> {













1628         interface FOp {
1629             int apply(int i);
1630         }
1631 
1632         abstract IntVector op(FOp f);
1633 
1634         abstract IntVector op(Mask<Integer> m, FOp f);
1635 
1636         interface FOpm {
1637             boolean apply(int i);
1638         }
1639 
1640         abstract Mask<Integer> opm(FOpm f);
1641 
1642         abstract IntVector.IntSpecies indexSpecies();
1643 
1644 
1645         // Factories
1646 
1647         @Override
1648         public abstract IntVector zero();
1649 
1650         /**
1651          * Returns a vector where all lane elements are set to the primitive
1652          * value {@code e}.
1653          *
1654          * @param e the value
1655          * @return a vector of vector where all lane elements are set to
1656          * the primitive value {@code e}
1657          */
1658         public abstract IntVector broadcast(int e);
1659 
1660         /**
1661          * Returns a vector where the first lane element is set to the primtive
1662          * value {@code e}, all other lane elements are set to the default
1663          * value.
1664          *
1665          * @param e the value
1666          * @return a vector where the first lane element is set to the primitive
1667          * value {@code e}
1668          */
1669         @ForceInline
1670         public final IntVector single(int e) {
1671             return zero().with(0, e);
1672         }
1673 
1674         /**
1675          * Returns a vector where each lane element is set to a randomly
1676          * generated primitive value.
1677          *
1678          * The semantics are equivalent to calling
1679          * {@code (int)ThreadLocalRandom#nextInt()}.
1680          *
1681          * @return a vector where each lane elements is set to a randomly
1682          * generated primitive value
1683          */
1684         public IntVector random() {
1685             ThreadLocalRandom r = ThreadLocalRandom.current();
1686             return op(i -> r.nextInt());
1687         }
1688 
1689         /**
1690          * Returns a vector where each lane element is set to a given
1691          * primitive value.
1692          * <p>
1693          * For each vector lane, where {@code N} is the vector lane index, the
1694          * the primitive value at index {@code N} is placed into the resulting
1695          * vector at lane index {@code N}.
1696          *
1697          * @param es the given primitive values
1698          * @return a vector where each lane element is set to a given primitive
1699          * value
1700          * @throws IndexOutOfBoundsException if {@code es.length < this.length()}
1701          */
1702         public abstract IntVector scalars(int... es);
1703     }
1704 
1705     /**
1706      * Finds the preferred species for an element type of {@code int}.
1707      * <p>
1708      * A preferred species is a species chosen by the platform that has a
1709      * shape of maximal bit size.  A preferred species for different element
1710      * types will have the same shape, and therefore vectors, masks, and
1711      * shuffles created from such species will be shape compatible.
1712      *
1713      * @return the preferred species for an element type of {@code int}
1714      */
1715     @SuppressWarnings("unchecked")
1716     public static IntSpecies preferredSpecies() {
1717         return (IntSpecies) Species.ofPreferred(int.class);
1718     }
1719 
1720     /**
1721      * Finds a species for an element type of {@code int} and shape.
1722      *
1723      * @param s the shape
1724      * @return a species for an element type of {@code int} and shape
1725      * @throws IllegalArgumentException if no such species exists for the shape
1726      */
1727     @SuppressWarnings("unchecked")
1728     public static IntSpecies species(Vector.Shape s) {
1729         Objects.requireNonNull(s);
1730         switch (s) {
1731             case S_64_BIT: return Int64Vector.SPECIES;
1732             case S_128_BIT: return Int128Vector.SPECIES;
1733             case S_256_BIT: return Int256Vector.SPECIES;
1734             case S_512_BIT: return Int512Vector.SPECIES;
1735             case S_Max_BIT: return IntMaxVector.SPECIES;
1736             default: throw new IllegalArgumentException("Bad shape: " + s);
1737         }
1738     }


























1739 }


  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 java.nio.ByteBuffer;
  28 import java.nio.IntBuffer;
  29 import java.nio.ByteOrder;
  30 import java.util.Objects;
  31 import java.util.function.IntUnaryOperator;
  32 import java.util.function.Function;
  33 import java.util.concurrent.ThreadLocalRandom;
  34 
  35 import jdk.internal.misc.Unsafe;
  36 import jdk.internal.vm.annotation.ForceInline;
  37 import static jdk.incubator.vector.VectorIntrinsics.*;
  38 
  39 
  40 /**
  41  * A specialized {@link Vector} representing an ordered immutable sequence of
  42  * {@code int} values.
  43  */
  44 @SuppressWarnings("cast")
  45 public abstract class IntVector extends Vector<Integer> {
  46 
  47     IntVector() {}
  48 
  49     private static final int ARRAY_SHIFT = 31 - Integer.numberOfLeadingZeros(Unsafe.ARRAY_INT_INDEX_SCALE);
  50 
  51     // Unary operator
  52 


  94 
  95     interface FUnCon {
  96         void apply(int i, int a);
  97     }
  98 
  99     abstract void forEach(FUnCon f);
 100 
 101     abstract void forEach(Mask<Integer> m, FUnCon f);
 102 
 103     // Static factories
 104 
 105     /**
 106      * Returns a vector where all lane elements are set to the default
 107      * primitive value.
 108      *
 109      * @param species species of desired vector
 110      * @return a zero vector of given species
 111      */
 112     @ForceInline
 113     @SuppressWarnings("unchecked")
 114     public static IntVector zero(Species<Integer> species) {
 115         return VectorIntrinsics.broadcastCoerced((Class<IntVector>) species.boxType(), int.class, species.length(),
 116                                                  0, species,
 117                                                  ((bits, s) -> ((IntSpecies)s).op(i -> (int)bits)));
 118     }
 119 
 120     /**
 121      * Loads a vector from a byte array starting at an offset.
 122      * <p>
 123      * Bytes are composed into primitive lane elements according to the
 124      * native byte order of the underlying platform
 125      * <p>
 126      * This method behaves as if it returns the result of calling the
 127      * byte buffer, offset, and mask accepting
 128      * {@link #fromByteBuffer(Species<Integer>, ByteBuffer, int, Mask) method} as follows:
 129      * <pre>{@code
 130      * return this.fromByteBuffer(ByteBuffer.wrap(a), i, this.maskAllTrue());
 131      * }</pre>
 132      *
 133      * @param species species of desired vector
 134      * @param a the byte array
 135      * @param ix the offset into the array
 136      * @return a vector loaded from a byte array
 137      * @throws IndexOutOfBoundsException if {@code i < 0} or
 138      * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)}
 139      */
 140     @ForceInline
 141     @SuppressWarnings("unchecked")
 142     public static IntVector fromByteArray(Species<Integer> species, byte[] a, int ix) {
 143         Objects.requireNonNull(a);
 144         ix = VectorIntrinsics.checkIndex(ix, a.length, species.bitSize() / Byte.SIZE);
 145         return VectorIntrinsics.load((Class<IntVector>) species.boxType(), int.class, species.length(),
 146                                      a, ((long) ix) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
 147                                      a, ix, species,
 148                                      (c, idx, s) -> {
 149                                          ByteBuffer bbc = ByteBuffer.wrap(c, idx, a.length - idx).order(ByteOrder.nativeOrder());
 150                                          IntBuffer tb = bbc.asIntBuffer();
 151                                          return ((IntSpecies)s).op(i -> tb.get());
 152                                      });
 153     }
 154 
 155     /**
 156      * Loads a vector from a byte array starting at an offset and using a
 157      * mask.
 158      * <p>
 159      * Bytes are composed into primitive lane elements according to the
 160      * native byte order of the underlying platform.
 161      * <p>
 162      * This method behaves as if it returns the result of calling the
 163      * byte buffer, offset, and mask accepting
 164      * {@link #fromByteBuffer(Species<Integer>, ByteBuffer, int, Mask) method} as follows:
 165      * <pre>{@code
 166      * return this.fromByteBuffer(ByteBuffer.wrap(a), i, m);
 167      * }</pre>
 168      *
 169      * @param species species of desired vector
 170      * @param a the byte array
 171      * @param ix the offset into the array
 172      * @param m the mask
 173      * @return a vector loaded from a byte array
 174      * @throws IndexOutOfBoundsException if {@code i < 0} or
 175      * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)}
 176      * @throws IndexOutOfBoundsException if the offset is {@code < 0},
 177      * or {@code > a.length},
 178      * for any vector lane index {@code N} where the mask at lane {@code N}
 179      * is set
 180      * {@code i >= a.length - (N * this.elementSize() / Byte.SIZE)}
 181      */
 182     @ForceInline
 183     public static IntVector fromByteArray(Species<Integer> species, byte[] a, int ix, Mask<Integer> m) {
 184         return zero(species).blend(fromByteArray(species, a, ix), m);
 185     }
 186 
 187     /**
 188      * Loads a vector from an array starting at offset.
 189      * <p>
 190      * For each vector lane, where {@code N} is the vector lane index, the
 191      * array element at index {@code i + N} is placed into the
 192      * resulting vector at lane index {@code N}.
 193      *
 194      * @param species species of desired vector
 195      * @param a the array
 196      * @param i the offset into the array
 197      * @return the vector loaded from an array
 198      * @throws IndexOutOfBoundsException if {@code i < 0}, or
 199      * {@code i > a.length - this.length()}
 200      */
 201     @ForceInline
 202     @SuppressWarnings("unchecked")
 203     public static IntVector fromArray(Species<Integer> species, int[] a, int i){
 204         Objects.requireNonNull(a);
 205         i = VectorIntrinsics.checkIndex(i, a.length, species.length());
 206         return VectorIntrinsics.load((Class<IntVector>) species.boxType(), int.class, species.length(),
 207                                      a, (((long) i) << ARRAY_SHIFT) + Unsafe.ARRAY_INT_BASE_OFFSET,
 208                                      a, i, species,
 209                                      (c, idx, s) -> ((IntSpecies)s).op(n -> c[idx + n]));
 210     }
 211 
 212 
 213     /**
 214      * Loads a vector from an array starting at offset and using a mask.
 215      * <p>
 216      * For each vector lane, where {@code N} is the vector lane index,
 217      * if the mask lane at index {@code N} is set then the array element at
 218      * index {@code i + N} is placed into the resulting vector at lane index
 219      * {@code N}, otherwise the default element value is placed into the
 220      * resulting vector at lane index {@code N}.
 221      *
 222      * @param species species of desired vector
 223      * @param a the array
 224      * @param i the offset into the array
 225      * @param m the mask
 226      * @return the vector loaded from an array
 227      * @throws IndexOutOfBoundsException if {@code i < 0}, or
 228      * for any vector lane index {@code N} where the mask at lane {@code N}
 229      * is set {@code i > a.length - N}
 230      */
 231     @ForceInline
 232     public static IntVector fromArray(Species<Integer> species, int[] a, int i, Mask<Integer> m) {
 233         return zero(species).blend(fromArray(species, a, i), m);
 234     }
 235 
 236     /**
 237      * Loads a vector from an array using indexes obtained from an index
 238      * map.
 239      * <p>
 240      * For each vector lane, where {@code N} is the vector lane index, the
 241      * array element at index {@code i + indexMap[j + N]} is placed into the
 242      * resulting vector at lane index {@code N}.
 243      *
 244      * @param species species of desired vector
 245      * @param a the array
 246      * @param i the offset into the array, may be negative if relative
 247      * indexes in the index map compensate to produce a value within the
 248      * array bounds
 249      * @param indexMap the index map
 250      * @param j the offset into the index map
 251      * @return the vector loaded from an array
 252      * @throws IndexOutOfBoundsException if {@code j < 0}, or
 253      * {@code j > indexMap.length - this.length()},
 254      * or for any vector lane index {@code N} the result of
 255      * {@code i + indexMap[j + N]} is {@code < 0} or {@code >= a.length}
 256      */
 257     @ForceInline
 258     @SuppressWarnings("unchecked")
 259     public static IntVector fromArray(Species<Integer> species, int[] a, int i, int[] indexMap, int j) {
 260         Objects.requireNonNull(a);
 261         Objects.requireNonNull(indexMap);
 262 
 263 
 264         // Index vector: vix[0:n] = k -> i + indexMap[j + k]
 265         IntVector vix = IntVector.fromArray(IntVector.species(species.indexShape()), indexMap, j).add(i);
 266 
 267         vix = VectorIntrinsics.checkIndex(vix, a.length);
 268 
 269         return VectorIntrinsics.loadWithMap((Class<IntVector>) species.boxType(), int.class, species.length(),
 270                                             IntVector.species(species.indexShape()).boxType(), a, Unsafe.ARRAY_INT_BASE_OFFSET, vix,
 271                                             a, i, indexMap, j, species,
 272                                             (int[] c, int idx, int[] iMap, int idy, Species<Integer> s) ->
 273                                                 ((IntSpecies)s).op(n -> c[idx + iMap[idy+n]]));
 274         }
 275 
 276     /**
 277      * Loads a vector from an array using indexes obtained from an index
 278      * map and using a mask.
 279      * <p>
 280      * For each vector lane, where {@code N} is the vector lane index,
 281      * if the mask lane at index {@code N} is set then the array element at
 282      * index {@code i + indexMap[j + N]} is placed into the resulting vector
 283      * at lane index {@code N}.
 284      *
 285      * @param species species of desired vector
 286      * @param a the array
 287      * @param i the offset into the array, may be negative if relative
 288      * indexes in the index map compensate to produce a value within the
 289      * array bounds
 290      * @param m the mask
 291      * @param indexMap the index map
 292      * @param j the offset into the index map
 293      * @return the vector loaded from an array
 294      * @throws IndexOutOfBoundsException if {@code j < 0}, or
 295      * {@code j > indexMap.length - this.length()},
 296      * or for any vector lane index {@code N} where the mask at lane
 297      * {@code N} is set the result of {@code i + indexMap[j + N]} is
 298      * {@code < 0} or {@code >= a.length}
 299      */
 300     @ForceInline
 301     @SuppressWarnings("unchecked")
 302     public static IntVector fromArray(Species<Integer> species, int[] a, int i, Mask<Integer> m, int[] indexMap, int j) {
 303         // @@@ This can result in out of bounds errors for unset mask lanes
 304         return zero(species).blend(fromArray(species, a, i, indexMap, j), m);
 305     }
 306 
 307 
 308     /**
 309      * Loads a vector from a {@link ByteBuffer byte buffer} starting at an
 310      * offset into the byte buffer.
 311      * <p>
 312      * Bytes are composed into primitive lane elements according to the
 313      * native byte order of the underlying platform.
 314      * <p>
 315      * This method behaves as if it returns the result of calling the
 316      * byte buffer, offset, and mask accepting
 317      * {@link #fromByteBuffer(Species<Integer>, ByteBuffer, int, Mask)} method} as follows:
 318      * <pre>{@code
 319      *   return this.fromByteBuffer(b, i, this.maskAllTrue())
 320      * }</pre>
 321      *
 322      * @param species species of desired vector
 323      * @param bb the byte buffer
 324      * @param ix the offset into the byte buffer
 325      * @return a vector loaded from a byte buffer
 326      * @throws IndexOutOfBoundsException if the offset is {@code < 0},
 327      * or {@code > b.limit()},
 328      * or if there are fewer than
 329      * {@code this.length() * this.elementSize() / Byte.SIZE} bytes
 330      * remaining in the byte buffer from the given offset
 331      */
 332     @ForceInline
 333     @SuppressWarnings("unchecked")
 334     public static IntVector fromByteBuffer(Species<Integer> species, ByteBuffer bb, int ix) {
 335         if (bb.order() != ByteOrder.nativeOrder()) {
 336             throw new IllegalArgumentException();
 337         }
 338         ix = VectorIntrinsics.checkIndex(ix, bb.limit(), species.bitSize() / Byte.SIZE);
 339         return VectorIntrinsics.load((Class<IntVector>) species.boxType(), int.class, species.length(),
 340                                      U.getReference(bb, BYTE_BUFFER_HB), U.getLong(bb, BUFFER_ADDRESS) + ix,
 341                                      bb, ix, species,
 342                                      (c, idx, s) -> {
 343                                          ByteBuffer bbc = c.duplicate().position(idx).order(ByteOrder.nativeOrder());
 344                                          IntBuffer tb = bbc.asIntBuffer();
 345                                          return ((IntSpecies)s).op(i -> tb.get());
 346                                      });
 347     }
 348 
 349     /**
 350      * Loads a vector from a {@link ByteBuffer byte buffer} starting at an
 351      * offset into the byte buffer and using a mask.
 352      * <p>
 353      * This method behaves as if the byte buffer is viewed as a primitive
 354      * {@link java.nio.Buffer buffer} for the primitive element type,


 366      * e[] es = new e[this.length()];
 367      * for (int n = 0; n < t.length; n++) {
 368      *     if (m.isSet(n))
 369      *         es[n] = eb.get(n);
 370      * }
 371      * Vector<E> r = ((ESpecies<S>)this).fromArray(es, 0, m);
 372      * }</pre>
 373      *
 374      * @param species species of desired vector
 375      * @param bb the byte buffer
 376      * @param ix the offset into the byte buffer
 377      * @param m the mask
 378      * @return a vector loaded from a byte buffer
 379      * @throws IndexOutOfBoundsException if the offset is {@code < 0},
 380      * or {@code > b.limit()},
 381      * for any vector lane index {@code N} where the mask at lane {@code N}
 382      * is set
 383      * {@code i >= b.limit() - (N * this.elementSize() / Byte.SIZE)}
 384      */
 385     @ForceInline
 386     public static IntVector fromByteBuffer(Species<Integer> species, ByteBuffer bb, int ix, Mask<Integer> m) {
 387         return zero(species).blend(fromByteBuffer(species, bb, ix), m);
 388     }
 389 
 390     /**
 391      * Returns a vector where all lane elements are set to the primitive
 392      * value {@code e}.
 393      *
 394      * @param s species of the desired vector
 395      * @param e the value
 396      * @return a vector of vector where all lane elements are set to
 397      * the primitive value {@code e}
 398      */
 399     @ForceInline
 400     @SuppressWarnings("unchecked")
 401     public static IntVector broadcast(Species<Integer> s, int e) {
 402         return VectorIntrinsics.broadcastCoerced(
 403             (Class<IntVector>) s.boxType(), int.class, s.length(),
 404             e, s,
 405             ((bits, sp) -> ((IntSpecies)sp).op(i -> (int)bits)));
 406     }
 407 
 408     /**
 409      * Returns a vector where each lane element is set to a given
 410      * primitive value.
 411      * <p>
 412      * For each vector lane, where {@code N} is the vector lane index, the
 413      * the primitive value at index {@code N} is placed into the resulting
 414      * vector at lane index {@code N}.
 415      *
 416      * @param s species of the desired vector
 417      * @param es the given primitive values
 418      * @return a vector where each lane element is set to a given primitive
 419      * value
 420      * @throws IndexOutOfBoundsException if {@code es.length < this.length()}
 421      */
 422     @ForceInline
 423     @SuppressWarnings("unchecked")
 424     public static IntVector scalars(Species<Integer> s, int... es) {
 425         Objects.requireNonNull(es);
 426         int ix = VectorIntrinsics.checkIndex(0, es.length, s.length());
 427         return VectorIntrinsics.load((Class<IntVector>) s.boxType(), int.class, s.length(),
 428                                      es, Unsafe.ARRAY_INT_BASE_OFFSET,
 429                                      es, ix, s,
 430                                      (c, idx, sp) -> ((IntSpecies)sp).op(n -> c[idx + n]));
 431     }
 432 
 433     /**
 434      * Returns a vector where the first lane element is set to the primtive
 435      * value {@code e}, all other lane elements are set to the default
 436      * value.
 437      *
 438      * @param s species of the desired vector
 439      * @param e the value
 440      * @return a vector where the first lane element is set to the primitive
 441      * value {@code e}
 442      */
 443     @ForceInline
 444     public static final IntVector single(Species<Integer> s, int e) {
 445         return zero(s).with(0, e);
 446     }
 447 
 448     /**
 449      * Returns a vector where each lane element is set to a randomly
 450      * generated primitive value.
 451      *
 452      * The semantics are equivalent to calling
 453      * {@link ThreadLocalRandom#nextInt()}
 454      *
 455      * @param s species of the desired vector
 456      * @return a vector where each lane elements is set to a randomly
 457      * generated primitive value
 458      */
 459     public static IntVector random(Species<Integer> s) {
 460         ThreadLocalRandom r = ThreadLocalRandom.current();
 461         return ((IntSpecies)s).op(i -> r.nextInt());
 462     }
 463 
 464     /**
 465      * Returns a mask where each lane is set or unset according to given
 466      * {@code boolean} values
 467      * <p>
 468      * For each mask lane, where {@code N} is the mask lane index,
 469      * if the given {@code boolean} value at index {@code N} is {@code true}
 470      * then the mask lane at index {@code N} is set, otherwise it is unset.
 471      *
 472      * @param species mask species
 473      * @param bits the given {@code boolean} values
 474      * @return a mask where each lane is set or unset according to the given {@code boolean} value
 475      * @throws IndexOutOfBoundsException if {@code bits.length < species.length()}
 476      */
 477     @ForceInline
 478     public static Mask<Integer> maskFromValues(Species<Integer> species, boolean... bits) {
 479         if (species.boxType() == IntMaxVector.class)
 480             return new IntMaxVector.IntMaxMask(bits);
 481         switch (species.bitSize()) {
 482             case 64: return new Int64Vector.Int64Mask(bits);
 483             case 128: return new Int128Vector.Int128Mask(bits);
 484             case 256: return new Int256Vector.Int256Mask(bits);
 485             case 512: return new Int512Vector.Int512Mask(bits);
 486             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 487         }
 488     }
 489 
 490     // @@@ This is a bad implementation -- makes lambdas capturing -- fix this
 491     static Mask<Integer> trueMask(Species<Integer> species) {
 492         if (species.boxType() == IntMaxVector.class)
 493             return IntMaxVector.IntMaxMask.TRUE_MASK;
 494         switch (species.bitSize()) {
 495             case 64: return Int64Vector.Int64Mask.TRUE_MASK;
 496             case 128: return Int128Vector.Int128Mask.TRUE_MASK;
 497             case 256: return Int256Vector.Int256Mask.TRUE_MASK;
 498             case 512: return Int512Vector.Int512Mask.TRUE_MASK;
 499             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 500         }
 501     }
 502 
 503     static Mask<Integer> falseMask(Species<Integer> species) {
 504         if (species.boxType() == IntMaxVector.class)
 505             return IntMaxVector.IntMaxMask.FALSE_MASK;
 506         switch (species.bitSize()) {
 507             case 64: return Int64Vector.Int64Mask.FALSE_MASK;
 508             case 128: return Int128Vector.Int128Mask.FALSE_MASK;
 509             case 256: return Int256Vector.Int256Mask.FALSE_MASK;
 510             case 512: return Int512Vector.Int512Mask.FALSE_MASK;
 511             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 512         }
 513     }
 514 
 515     /**
 516      * Loads a mask from a {@code boolean} array starting at an offset.
 517      * <p>
 518      * For each mask lane, where {@code N} is the mask lane index,
 519      * if the array element at index {@code ix + N} is {@code true} then the
 520      * mask lane at index {@code N} is set, otherwise it is unset.
 521      *
 522      * @param species mask species
 523      * @param bits the {@code boolean} array
 524      * @param ix the offset into the array
 525      * @return the mask loaded from a {@code boolean} array
 526      * @throws IndexOutOfBoundsException if {@code ix < 0}, or
 527      * {@code ix > bits.length - species.length()}
 528      */
 529     @ForceInline
 530     @SuppressWarnings("unchecked")
 531     public static Mask<Integer> maskFromArray(Species<Integer> species, boolean[] bits, int ix) {
 532         Objects.requireNonNull(bits);
 533         ix = VectorIntrinsics.checkIndex(ix, bits.length, species.length());
 534         return VectorIntrinsics.load((Class<Mask<Integer>>) species.maskType(), int.class, species.length(),
 535                                      bits, (((long) ix) << ARRAY_SHIFT) + Unsafe.ARRAY_BOOLEAN_BASE_OFFSET,
 536                                      bits, ix, species,
 537                                      (c, idx, s) -> (Mask<Integer>) ((IntSpecies)s).opm(n -> c[idx + n]));
 538     }
 539 
 540     /**
 541      * Returns a mask where all lanes are set.
 542      *
 543      * @param species mask species
 544      * @return a mask where all lanes are set
 545      */
 546     @ForceInline
 547     @SuppressWarnings("unchecked")
 548     public static Mask<Integer> maskAllTrue(Species<Integer> species) {
 549         return VectorIntrinsics.broadcastCoerced((Class<Mask<Integer>>) species.maskType(), int.class, species.length(),
 550                                                  (int)-1,  species,
 551                                                  ((z, s) -> trueMask(s)));
 552     }
 553 
 554     /**
 555      * Returns a mask where all lanes are unset.
 556      *
 557      * @param species mask species
 558      * @return a mask where all lanes are unset
 559      */
 560     @ForceInline
 561     @SuppressWarnings("unchecked")
 562     public static Mask<Integer> maskAllFalse(Species<Integer> species) {
 563         return VectorIntrinsics.broadcastCoerced((Class<Mask<Integer>>) species.maskType(), int.class, species.length(),
 564                                                  0, species, 
 565                                                  ((z, s) -> falseMask(s)));
 566     }
 567 
 568     /**
 569      * Returns a shuffle of mapped indexes where each lane element is
 570      * the result of applying a mapping function to the corresponding lane
 571      * index.
 572      * <p>
 573      * Care should be taken to ensure Shuffle values produced from this
 574      * method are consumed as constants to ensure optimal generation of
 575      * code.  For example, values held in static final fields or values
 576      * held in loop constant local variables.
 577      * <p>
 578      * This method behaves as if a shuffle is created from an array of
 579      * mapped indexes as follows:
 580      * <pre>{@code
 581      *   int[] a = new int[species.length()];
 582      *   for (int i = 0; i < a.length; i++) {
 583      *       a[i] = f.applyAsInt(i);
 584      *   }
 585      *   return this.shuffleFromValues(a);
 586      * }</pre>
 587      *
 588      * @param species shuffle species
 589      * @param f the lane index mapping function
 590      * @return a shuffle of mapped indexes
 591      */
 592     @ForceInline
 593     public static Shuffle<Integer> shuffle(Species<Integer> species, IntUnaryOperator f) {
 594         if (species.boxType() == IntMaxVector.class)
 595             return new IntMaxVector.IntMaxShuffle(f);
 596         switch (species.bitSize()) {
 597             case 64: return new Int64Vector.Int64Shuffle(f);
 598             case 128: return new Int128Vector.Int128Shuffle(f);
 599             case 256: return new Int256Vector.Int256Shuffle(f);
 600             case 512: return new Int512Vector.Int512Shuffle(f);
 601             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 602         }
 603     }
 604 
 605     /**
 606      * Returns a shuffle where each lane element is the value of its
 607      * corresponding lane index.
 608      * <p>
 609      * This method behaves as if a shuffle is created from an identity
 610      * index mapping function as follows:
 611      * <pre>{@code
 612      *   return this.shuffle(i -> i);
 613      * }</pre>
 614      *
 615      * @param species shuffle species
 616      * @return a shuffle of lane indexes
 617      */
 618     @ForceInline
 619     public static Shuffle<Integer> shuffleIota(Species<Integer> species) {
 620         if (species.boxType() == IntMaxVector.class)
 621             return new IntMaxVector.IntMaxShuffle(AbstractShuffle.IDENTITY);
 622         switch (species.bitSize()) {
 623             case 64: return new Int64Vector.Int64Shuffle(AbstractShuffle.IDENTITY);
 624             case 128: return new Int128Vector.Int128Shuffle(AbstractShuffle.IDENTITY);
 625             case 256: return new Int256Vector.Int256Shuffle(AbstractShuffle.IDENTITY);
 626             case 512: return new Int512Vector.Int512Shuffle(AbstractShuffle.IDENTITY);
 627             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 628         }
 629     }
 630 
 631     /**
 632      * Returns a shuffle where each lane element is set to a given
 633      * {@code int} value logically AND'ed by the species length minus one.
 634      * <p>
 635      * For each shuffle lane, where {@code N} is the shuffle lane index, the
 636      * the {@code int} value at index {@code N} logically AND'ed by
 637      * {@code species.length() - 1} is placed into the resulting shuffle at
 638      * lane index {@code N}.
 639      *
 640      * @param species shuffle species
 641      * @param ixs the given {@code int} values
 642      * @return a shuffle where each lane element is set to a given
 643      * {@code int} value
 644      * @throws IndexOutOfBoundsException if the number of int values is
 645      * {@code < species.length()}
 646      */
 647     @ForceInline
 648     public static Shuffle<Integer> shuffleFromValues(Species<Integer> species, int... ixs) {
 649         if (species.boxType() == IntMaxVector.class)
 650             return new IntMaxVector.IntMaxShuffle(ixs);
 651         switch (species.bitSize()) {
 652             case 64: return new Int64Vector.Int64Shuffle(ixs);
 653             case 128: return new Int128Vector.Int128Shuffle(ixs);
 654             case 256: return new Int256Vector.Int256Shuffle(ixs);
 655             case 512: return new Int512Vector.Int512Shuffle(ixs);
 656             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 657         }
 658     }
 659 
 660     /**
 661      * Loads a shuffle from an {@code int} array starting at an offset.
 662      * <p>
 663      * For each shuffle lane, where {@code N} is the shuffle lane index, the
 664      * array element at index {@code i + N} logically AND'ed by
 665      * {@code species.length() - 1} is placed into the resulting shuffle at lane
 666      * index {@code N}.
 667      *
 668      * @param species shuffle species
 669      * @param ixs the {@code int} array
 670      * @param i the offset into the array
 671      * @return a shuffle loaded from the {@code int} array
 672      * @throws IndexOutOfBoundsException if {@code i < 0}, or
 673      * {@code i > a.length - species.length()}
 674      */
 675     @ForceInline
 676     public static Shuffle<Integer> shuffleFromArray(Species<Integer> species, int[] ixs, int i) {
 677         if (species.boxType() == IntMaxVector.class)
 678             return new IntMaxVector.IntMaxShuffle(ixs, i);
 679         switch (species.bitSize()) {
 680             case 64: return new Int64Vector.Int64Shuffle(ixs, i);
 681             case 128: return new Int128Vector.Int128Shuffle(ixs, i);
 682             case 256: return new Int256Vector.Int256Shuffle(ixs, i);
 683             case 512: return new Int512Vector.Int512Shuffle(ixs, i);
 684             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 685         }
 686     }
 687 

 688     // Ops
 689 
 690     @Override
 691     public abstract IntVector add(Vector<Integer> v);
 692 
 693     /**
 694      * Adds this vector to the broadcast of an input scalar.
 695      * <p>
 696      * This is a vector binary operation where the primitive addition operation
 697      * ({@code +}) is applied to lane elements.
 698      *
 699      * @param s the input scalar
 700      * @return the result of adding this vector to the broadcast of an input
 701      * scalar
 702      */
 703     public abstract IntVector add(int s);
 704 
 705     @Override
 706     public abstract IntVector add(Vector<Integer> v, Mask<Integer> m);
 707 


1679      * index {@code N} is stored into the array at index
1680      * {@code i + indexMap[j + N]}.
1681      *
1682      * @param a the array
1683      * @param i the offset into the array, may be negative if relative
1684      * indexes in the index map compensate to produce a value within the
1685      * array bounds
1686      * @param m the mask
1687      * @param indexMap the index map
1688      * @param j the offset into the index map
1689      * @throws IndexOutOfBoundsException if {@code j < 0}, or
1690      * {@code j > indexMap.length - this.length()},
1691      * or for any vector lane index {@code N} where the mask at lane
1692      * {@code N} is set the result of {@code i + indexMap[j + N]} is
1693      * {@code < 0} or {@code >= a.length}
1694      */
1695     public abstract void intoArray(int[] a, int i, Mask<Integer> m, int[] indexMap, int j);
1696     // Species
1697 
1698     @Override
1699     public abstract Species<Integer> species();
1700 
1701     /**
1702      * Class representing {@link IntVector}'s of the same {@link Vector.Shape Shape}.
1703      */
1704     static final class IntSpecies extends Vector.AbstractSpecies<Integer> {
1705         final Function<int[], IntVector> vectorFactory;
1706         final Function<boolean[], Vector.Mask<Integer>> maskFactory;
1707 
1708         private IntSpecies(Vector.Shape shape,
1709                           Class<?> boxType,
1710                           Class<?> maskType,
1711                           Function<int[], IntVector> vectorFactory,
1712                           Function<boolean[], Vector.Mask<Integer>> maskFactory) {
1713             super(shape, int.class, Integer.SIZE, boxType, maskType);
1714             this.vectorFactory = vectorFactory;
1715             this.maskFactory = maskFactory;
1716         }
1717 
1718         interface FOp {
1719             int apply(int i);
1720         }
1721 




1722         interface FOpm {
1723             boolean apply(int i);
1724         }
1725 
1726         IntVector op(FOp f) {
1727             int[] res = new int[length()];
1728             for (int i = 0; i < length(); i++) {
1729                 res[i] = f.apply(i);
1730             }
1731             return vectorFactory.apply(res);


























1732         }
1733 
1734         IntVector op(Vector.Mask<Integer> o, FOp f) {
1735             int[] res = new int[length()];
1736             boolean[] mbits = ((AbstractMask<Integer>)o).getBits();
1737             for (int i = 0; i < length(); i++) {
1738                 if (mbits[i]) {
1739                     res[i] = f.apply(i);
1740                 }
1741             }
1742             return vectorFactory.apply(res);




1743         }
1744 
1745         Vector.Mask<Integer> opm(IntVector.IntSpecies.FOpm f) {
1746             boolean[] res = new boolean[length()];
1747             for (int i = 0; i < length(); i++) {
1748                 res[i] = (boolean)f.apply(i);
1749             }
1750             return maskFactory.apply(res);
1751         }







1752     }
1753 
1754     /**
1755      * Finds the preferred species for an element type of {@code int}.
1756      * <p>
1757      * A preferred species is a species chosen by the platform that has a
1758      * shape of maximal bit size.  A preferred species for different element
1759      * types will have the same shape, and therefore vectors, masks, and
1760      * shuffles created from such species will be shape compatible.
1761      *
1762      * @return the preferred species for an element type of {@code int}
1763      */
1764     private static IntSpecies preferredSpecies() {

1765         return (IntSpecies) Species.ofPreferred(int.class);
1766     }
1767 
1768     /**
1769      * Finds a species for an element type of {@code int} and shape.
1770      *
1771      * @param s the shape
1772      * @return a species for an element type of {@code int} and shape
1773      * @throws IllegalArgumentException if no such species exists for the shape
1774      */
1775     static IntSpecies species(Vector.Shape s) {

1776         Objects.requireNonNull(s);
1777         switch (s) {
1778             case S_64_BIT: return (IntSpecies) SPECIES_64;
1779             case S_128_BIT: return (IntSpecies) SPECIES_128;
1780             case S_256_BIT: return (IntSpecies) SPECIES_256;
1781             case S_512_BIT: return (IntSpecies) SPECIES_512;
1782             case S_Max_BIT: return (IntSpecies) SPECIES_MAX;
1783             default: throw new IllegalArgumentException("Bad shape: " + s);
1784         }
1785     }
1786 
1787     /** Species representing {@link IntVector}s of {@link Vector.Shape#S_64_BIT Shape.S_64_BIT}. */
1788     public static final Species<Integer> SPECIES_64 = new IntSpecies(Shape.S_64_BIT, Int64Vector.class, Int64Vector.Int64Mask.class,
1789                                                                      Int64Vector::new, Int64Vector.Int64Mask::new);
1790 
1791     /** Species representing {@link IntVector}s of {@link Vector.Shape#S_128_BIT Shape.S_128_BIT}. */
1792     public static final Species<Integer> SPECIES_128 = new IntSpecies(Shape.S_128_BIT, Int128Vector.class, Int128Vector.Int128Mask.class,
1793                                                                       Int128Vector::new, Int128Vector.Int128Mask::new);
1794 
1795     /** Species representing {@link IntVector}s of {@link Vector.Shape#S_256_BIT Shape.S_256_BIT}. */
1796     public static final Species<Integer> SPECIES_256 = new IntSpecies(Shape.S_256_BIT, Int256Vector.class, Int256Vector.Int256Mask.class,
1797                                                                       Int256Vector::new, Int256Vector.Int256Mask::new);
1798 
1799     /** Species representing {@link IntVector}s of {@link Vector.Shape#S_512_BIT Shape.S_512_BIT}. */
1800     public static final Species<Integer> SPECIES_512 = new IntSpecies(Shape.S_512_BIT, Int512Vector.class, Int512Vector.Int512Mask.class,
1801                                                                       Int512Vector::new, Int512Vector.Int512Mask::new);
1802 
1803     /** Species representing {@link IntVector}s of {@link Vector.Shape#S_Max_BIT Shape.S_Max_BIT}. */
1804     public static final Species<Integer> SPECIES_MAX = new IntSpecies(Shape.S_Max_BIT, IntMaxVector.class, IntMaxVector.IntMaxMask.class,
1805                                                                       IntMaxVector::new, IntMaxVector.IntMaxMask::new);
1806 
1807     /**
1808      * Preferred species for {@link IntVector}s.
1809      * A preferred species is a species of maximal bit size for the platform.
1810      */
1811     public static final Species<Integer> SPECIES_PREFERRED = (Species<Integer>) preferredSpecies();
1812 }
< prev index next >