1 /*
   2  * Copyright (c) 2017, 2019, 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 import java.util.function.Function;
  29 import java.util.function.IntUnaryOperator;
  30 
  31 /**
  32  * Interface for managing all vectors of the same combination
  33  * of element type ({@code ETYPE}) and {@link VectorShape shape}.
  34  *
  35  * @apiNote
  36  * User code should not implement this interface.  A future release of
  37  * this type may restrict implementations to be members of the same
  38  * package.
  39  *
  40  * @implNote
  41  * The string representation of an instance of this interface will
  42  * be of the form "Species[ETYPE, VLENGTH, SHAPE]", where {@code
  43  * ETYPE} is the primitive {@linkplain #elementType() lane type},
  44  * {@code VLENGTH} is the {@linkplain #length() vector lane count}
  45  * associated with the species, and {@code SHAPE} is the {@linkplain
  46  * #vectorShape() vector shape} associated with the species.
  47  *
  48  * <p>Vector species objects can be stored in locals and parameters and as
  49  * {@code static final} constants, but storing them in other Java
  50  * fields or in array elements, while semantically valid, may incur
  51  * performance penalties.
  52  *
  53  * @param <E> the boxed element type for the vector element
  54  *        type ({@code ETYPE})
  55  */
  56 public interface VectorSpecies<E> {
  57     /**
  58      * Returns the primitive element type of vectors of this
  59      * species.
  60      *
  61      * @return the primitive element type ({@code ETYPE})
  62      */
  63     public abstract Class<E> elementType();
  64 
  65     /**
  66      * Returns the generic parameter type {@code E} corresponding
  67      * to the element type {@code ETYPE} of this species.
  68      *
  69      * @return the parameter type {@code E}
  70      */
  71     public abstract Class<E> genericElementType();
  72 
  73     /**
  74      * Returns the primitive array type {@code ETYPE[]},
  75      * which can carry packed lane values of vectors of
  76      * this species.
  77      *
  78      * @return the primitive array type {@code ETYPE[]}
  79      */
  80     public abstract Class<?> arrayType();
  81 
  82     /**
  83      * Returns the vector type of this species.
  84      * A vector is of this species if and only if
  85      * it is of the corresponding vector type.
  86      *
  87      * @return the vector type of this species
  88      */
  89     abstract Class<? extends Vector<E>> vectorType();
  90 
  91     /**
  92      * Returns the vector mask type for this species.
  93      *
  94      * @return the mask type
  95      */
  96     abstract Class<? extends VectorMask<E>> maskType();
  97 
  98     /**
  99      * Returns the lane size, in bits, of vectors of this
 100      * species.
 101      *
 102      * @return the element size, in bits
 103      */
 104     public abstract int elementSize();
 105 
 106     /**
 107      * Returns the shape of vectors produced by this
 108      * species.
 109      *
 110      * @return the shape of any vectors of this species
 111      */
 112     public abstract VectorShape vectorShape();
 113 
 114     /**
 115      * Returns the number of lanes in a vector of this species.
 116      *
 117      * @apiNote: This is also the number of lanes in a mask or
 118      * shuffle associated with a vector of this species.
 119      *
 120      * @return the number of vector lanes
 121      */
 122     public abstract int length();
 123 
 124     /**
 125      * Returns the total vector size, in bits, of any vector
 126      * of this species.
 127      * This is the same value as {@code this.vectorShape().vectorBitSize()}.
 128      *
 129      * @apiNote: This size may be distinct from the size in bits
 130      * of a mask or shuffle of this species.
 131      *
 132      * @return the total vector size, in bits
 133      */
 134     public abstract int vectorBitSize();
 135 
 136     /**
 137      * Returns the total vector size, in bytes, of any vector
 138      * of this species.
 139      * This is the same value as {@code this.vectorShape().vectorBitSize() / Byte.SIZE}.
 140      *
 141      * @apiNote: This size may be distinct from the size in bits
 142      * of a mask or shuffle of this species.
 143      *
 144      * @return the total vector size, in bytes
 145      */
 146     public abstract int vectorByteSize();
 147 
 148     /**
 149      * Loop control function which returns the largest multiple of
 150      * {@code VLENGTH} that is less than or equal to the given
 151      * {@code length} value.
 152      * Here, {@code VLENGTH} is the result of {@code this.length()},
 153      * and {@code length} is interpreted as a number of lanes.
 154      * The resulting value {@code R} satisfies this inequality:
 155      * <pre>{@code R <= length < R+VLENGTH}
 156      * </pre>
 157      * <p> Specifically, this method computes
 158      * {@code length - floorMod(length, VLENGTH)}, where
 159      * {@link Math#floorMod(int,int) floorMod} computes a remainder
 160      * value by rounding its quotient toward negative infinity.
 161      * As long as {@code VLENGTH} is a power of two, then the result
 162      * is also equal to {@code length & ~(VLENGTH - 1)}.
 163      *
 164      * @return the largest multiple of the vector length not greater
 165      *         than the given length
 166      * @throws IllegalArgumentException if the {@code length} is
 167                negative and the result would overflow to a positive value
 168      * @see Math#floorMod(int, int)
 169      */
 170     public abstract int loopBound(int length);
 171 
 172     /**
 173      * Checks that this species has the given element type,
 174      * and returns this species unchanged.
 175      * The effect is similar to this pseudocode:
 176      * {@code elementType == elementType()
 177      *        ? this
 178      *        : throw new ClassCastException()}.
 179      *
 180      * @param elementType the required lane type
 181      * @param <F> the boxed element type of the required lane type
 182      * @return the same species
 183      * @throws ClassCastException if the species has the wrong element type
 184      * @see Vector#check(Class)
 185      * @see Vector#check(VectorSpecies)
 186      */
 187     public abstract <F> VectorSpecies<F> check(Class<F> elementType);
 188 
 189     /**
 190      * Given this species and a second one, reports the net
 191      * expansion or contraction of a (potentially) resizing
 192      * {@linkplain Vector#reinterpretShape(VectorSpecies,int) reinterpretation cast}
 193      * or
 194      * {@link Vector#convertShape(VectorOperators.Conversion,VectorSpecies,int) lane-wise conversion}
 195      * from this species to the second.
 196      *
 197      * The sign and magnitude of the return value depends on the size
 198      * difference between the proposed input and output
 199      * <em>shapes</em>, and (optionally, if {@code lanewise} is true)
 200      * also on the size difference between the proposed input and
 201      * output <em>lanes</em>.
 202      *
 203      * <ul>
 204      * <li> First, a logical result size is determined.
 205      *
 206      * If {@code lanewise} is false, this size that of the input
 207      * {@code VSHAPE}.  If {@code lanewise} is true, the logical
 208      * result size is the product of the input {@code VLENGTH}
 209      * times the size of the <em>output</em> {@size ETYPE}.
 210      *
 211      * <li> Next, the logical result size is compared against
 212      * the size of the proposed output shape, to see how it
 213      * will fit.
 214      *
 215      * <li> If the logical result fits precisely in the
 216      * output shape, the return value is zero, signifying
 217      * no net expansion or contraction.
 218      *
 219      * <li> If the logical result would overflow the output shape, the
 220      * return value is the ratio (greater than one) of the logical
 221      * result size to the (smaller) output size.  This ratio can be
 222      * viewed as measuring the proportion of "dropped input bits"
 223      * which must be deleted from the input in order for the result to
 224      * fit in the output vector.  It is also the <em>part limit</em>,
 225      * a upper exclusive limit on the {@code part} parameter to a
 226      * method that would transform the input species to the output
 227      * species.
 228      * 
 229      * <li> If the logical result would drop into the output shape
 230      * with room to spare, the return value is a negative number whose
 231      * absolute value the ratio (greater than one) between the output
 232      * size and the (smaller) logical result size.  This ratio can be
 233      * viewed as measuring the proportion of "extra padding bits"
 234      * which must be added to the logical result to fill up the output
 235      * vector.  It is also the <em>part limit</em>, an exclusive lower
 236      * limit on the {@code part} parameter to a method that would
 237      * transform the input species to the output species.
 238      * 
 239      * </ul>
 240      * 
 241      * @param outputSpecies the proposed output species
 242      * @param lanewise whether to take lane sizes into account
 243      * @return an indication of the size change, as a signed ratio or zero
 244      *
 245      * @see Vector#reinterpretShape(VectorSpecies,int)
 246      * @see Vector#convertShape(VectorOperations.Conversion,VectorSpecies,int)
 247      */
 248     public abstract int partLimit(VectorSpecies<?> outputSpecies, boolean lanewise);
 249 
 250     // Factories
 251 
 252     /**
 253      * Finds a species with the given element type and the
 254      * same shape as this species.
 255      * Returns the same value as
 256      * {@code VectorSpecies.of(newType, this.vectorShape())}
 257      *
 258      * @param newType the new element type
 259      * @param <F> the boxed element type
 260      * @return a species for the new element type and the same shape
 261      * @throws IllegalArgumentException if no such species exists for the
 262      *         given combination of element type and shape
 263      *         or if the given type is not a valid {@code ETYPE}
 264      * @see #withShape(VectorShape)
 265      * @see VectorSpecies#of(Class, VectorShape)
 266      */
 267     public abstract <F> VectorSpecies<F> withLanes(Class<F> newType);
 268 
 269     /**
 270      * Finds a species with the given shape and the same
 271      * elementType as this species.
 272      * Returns the same value as
 273      * {@code VectorSpecies.of(this.elementType(), newShape)}
 274      *
 275      * @param shape the new shape
 276      * @return a species for the same element type and the new shape
 277      * @throws IllegalArgumentException if no such species exists for the
 278      *         given combination of element type and shape
 279      * @see #withLanes(Class)
 280      * @see VectorSpecies#of(Class, VectorShape)
 281      */
 282     public abstract VectorSpecies<E> withShape(VectorShape newShape);
 283 
 284     /**
 285      * Finds a species for an element type and shape.
 286      *
 287      * @param elementType the element type
 288      * @param shape the shape
 289      * @param <E> the boxed element type
 290      * @return a species for the given element type and shape
 291      * @throws IllegalArgumentException if no such species exists for the
 292      *         given combination of element type and shape
 293      *         or if the given type is not a valid {@code ETYPE}
 294      * @see withE(VectorShape)
 295      * @see withShape(VectorShape)
 296      */
 297     public static <E> VectorSpecies<E> of(Class<E> elementType, VectorShape shape) {
 298         LaneType laneType = LaneType.of(elementType);
 299         return AbstractSpecies.findSpecies(elementType, laneType, shape);
 300     }
 301 
 302     /**
 303      * Finds the largest vector species of the given element type.
 304      * <p>
 305      * The returned species is a species chosen by the platform that has a
 306      * shape with the largest possible bit-size for the given element type.
 307      * The underlying vector shape might not support other lane types
 308      * on some platforms, which may limit the applicability of
 309      * {@linkplain Vector#reinterpret(VectorSpecies) reinterpretation casts}.
 310      * Vector algorithms which require reinterpretation casts will
 311      * be more portable if they use the platform's
 312      * {@linkplain #ofPreferred(Class) preferred species}.
 313      *
 314      * @param etype the element type
 315      * @param <E> the boxed element type
 316      * @return a preferred species for an element type
 317      * @throws IllegalArgumentException if no such species exists for the
 318      *         element type
 319      *         or if the given type is not a valid {@code ETYPE}
 320      * @see VectorSpecies#ofPreferred(Class)
 321      */
 322     public static <E> VectorSpecies<E> ofLargestShape(Class<E> etype) {
 323         return VectorSpecies.of(etype, VectorShape.largestShapeFor(etype));
 324     }
 325 
 326     /**
 327      * Finds the species preferred by the current platform
 328      * for a given vector element type and the preferred shape.
 329      * This is the same value as
 330      * {@code VectorSpecies.of(etype, VectorShape.preferredShape())}.
 331      *
 332      * <p> This species is chosen by the platform so that it has the
 333      * largest possible shape that supports all lane element types.
 334      * This has the following implications:
 335      * <ul>
 336      * <li>The various preferred species for different element types
 337      * will have the same underlying shape.
 338      * <li>All vectors created from preferred species will have a
 339      * common bit-size and information capacity.
 340      * <li>{@linkplain Vector#reinterpret(VectorSpecies) Reinterpretation casts}.
 341      * between vectors of preferred species will neither truncate
 342      * lanes nor fill them with default values.
 343      * <li>For any particular element type, some platform might possibly
 344      * provide a {@linkplain #ofLargestShape(Class) larger vector shape}
 345      * that (as a trade-off) does not support all possible element types.
 346      * </ul>
 347      *
 348      * @implNote On many platforms there is no behavioral difference
 349      * between {@link #ofLargestShape(Class) ofLargestShape} and
 350      * {@code ofPreferred}, because the preferred shape is usually
 351      * also the largest available shape for every lane type.
 352      * Therefore, most vector algorithms will perform well without
 353      * {@code ofLargestShape}.
 354      *
 355      * @param etype the element type
 356      * @param <E> the boxed element type
 357      * @return a preferred species for this element type
 358      * @throws IllegalArgumentException if no such species exists for the
 359      *         element type
 360      *         or if the given type is not a valid {@code ETYPE}
 361      * @see Vector#reinterpretShape(VectorSpecies)
 362      * @see VectorShape#preferredShape()
 363      * @see VectorSpecies#ofLargestShape(Class)
 364      */
 365     public static <E> VectorSpecies<E> ofPreferred(Class<E> etype) {
 366         return of(etype, VectorShape.preferredShape());
 367     }
 368 
 369     /**
 370      * Returns the bit-size the given vector element type ({@code
 371      * ETYPE}).  The element type must be a valid {@code ETYPE}, not a
 372      * wrapper type or other object type.
 373      *
 374      * The element type argument must be a mirror for a valid vector
 375      * {@code ETYPE}, such as {@code byte.class}, {@code int.class},
 376      * or {@code double.class}.  The bit-size of such a type is the
 377      * {@code SIZE} constant for the corresponding wrapper class, such
 378      * as {@code Byte.SIZE}, or {@code Integer.SIZE}, or
 379      * {@code Double.SIZE}.
 380      *
 381      * @param elementType a vector element type (an {@code ETYPE})
 382      * @return the bit-size of {@code elementType}, such as 32 for {@code int.class}
 383      * @throws IllegalArgumentException
 384      *         if the given {@code elementType} argument is not
 385      *         a valid vector {@code ETYPE}
 386      */
 387     public static int elementSize(Class<?> elementType) {
 388         return LaneType.of(elementType).elementSize;
 389     }
 390 
 391     /// Convenience factories:
 392 
 393     /**
 394      * Returns a vector of this species
 395      * where all lane elements are set to
 396      * the default primitive value, {@code (ETYPE)0}.
 397      *
 398      * Equivalent to {@code IntVector.zero(this)}
 399      * or an equivalent {@code zero} method,
 400      * on the vector type corresponding to
 401      * this species.
 402      *
 403      * @return a zero vector of the given species
 404      * @see IntVector#zero(VectorSpecies)
 405      * @see FloatVector#zero(VectorSpecies)
 406      */
 407     public abstract Vector<E> zero();
 408 
 409     /**
 410      * Returns a vector of this species
 411      * where lane elements are initialized
 412      * from the given array at the given offset.
 413      * The array must be of the the correct {@code ETYPE}.
 414      *
 415      * Equivalent to
 416      * {@code IntVector.fromArray(this,a,offset)}
 417      * or an equivalent {@code fromArray} method,
 418      * on the vector type corresponding to
 419      * this species.
 420      * 
 421      * @param a an array of the {@code ETYPE} for this species
 422      * @param offset the index of the first lane value to load
 423      * @return a vector of the given species filled from the array
 424      * @throws IndexOutOfBoundsException
 425      *         if {@code offset+N < 0} or {@code offset+N >= a.length}
 426      *         for any lane {@code N} in the vector
 427      * @see IntVector#fromArray(VectorSpecies,int[],int)
 428      * @see FloatVector#fromArray(VectorSpecies,float[],int)
 429      */
 430     public abstract Vector<E> fromArray(Object a, int offset);
 431     // Defined when ETYPE is known.
 432 
 433     /**
 434      * Returns a vector of this species
 435      * where lane elements are initialized
 436      * from the given sequence of {@code long}s.
 437      * The {@code long} values must all be representable
 438      * by the {@code ETYPE} of this species.
 439      *
 440      * Equivalent to
 441      * {@code IntVector.fromArray(this,a,offset)}
 442      * or an equivalent {@code fromArray} method,
 443      * on the vector type corresponding to
 444      * this species, after the values are copied
 445      * (without loss of value or precision) to
 446      * an appropriately typed array.
 447      * 
 448      * @param values an array of values to load into the vector
 449      * @return a vector of the given species filled from the array
 450      * @throws IllegalArgumentException
 451      *         if {@code values.length != species.length()}
 452      *         or if any of the values cannot be represented
 453      *         by the {@code ETYPE} of this species
 454      * @see IntVector#fromArray(VectorSpecies,int[],int)
 455      * @see FloatVector#fromArray(VectorSpecies,float[],int)
 456      * @see #checkValue(long)
 457      */
 458     public abstract Vector<E> fromValues(long... values);
 459 
 460     /**
 461      * Returns a vector of this species
 462      * where lane elements are initialized
 463      * from the given byte array at the given offset.
 464      *
 465      * Equivalent to
 466      * {@code IntVector.fromByteArray(this,a,offset)}
 467      * or an equivalent {@code fromByteArray} method,
 468      * on the vector type corresponding to
 469      * this species.
 470      * 
 471      * @param a a byte array
 472      * @param offset the index of the first byte to load
 473      * @return a vector of the given species filled from the byte array
 474      * @throws IndexOutOfBoundsException
 475      *         if {@code offset+N*ESIZE < 0}
 476      *         or {@code offset+(N+1)*ESIZE > a.length}
 477      *         for any lane {@code N} in the vector
 478      * @see IntVector#fromByteArray(VectorSpecies,byte[],int)
 479      * @see FloatVector#fromByteArray(VectorSpecies,byte[],int)
 480      */
 481     public abstract Vector<E> fromByteArray(byte[] a, int offset);
 482 
 483     /**
 484      * Returns a mask of this species
 485      * where lane elements are initialized
 486      * from the given array at the given offset.
 487      *
 488      * Equivalent to
 489      * {@code VectorMask.fromArray(this,a,offset)}.
 490      * 
 491      * @param bits the {@code boolean} array
 492      * @param offset the offset into the array
 493      * @return the mask loaded from the {@code boolean} array
 494      * @throws IndexOutOfBoundsException
 495      *         if {@code offset+N < 0} or {@code offset+N >= a.length}
 496      *         for any lane {@code N} in the vector mask
 497      * @see VectorMask#fromArray(VectorSpecies,boolean[],int)
 498      */
 499     public abstract VectorMask<E> loadMask(boolean[] bits, int offset);
 500 
 501     /**
 502      * Returns a mask of this species,
 503      * where each lane is set or unset according to given
 504      * single boolean, which is broadcast to all lanes.
 505      *
 506      * @param bit the given mask bit to be replicated
 507      * @return a mask where each lane is set or unset according to
 508      *         the given bit
 509      * @see Vector#maskAll(boolean)
 510      */
 511     public abstract VectorMask<E> maskAll(boolean bit);
 512 
 513     /**
 514      * Returns a vector of the given species
 515      * where all lane elements are set to
 516      * the primitive value {@code e}.
 517      *
 518      * <p> This method returns the value of this expression:
 519      * {@code EVector.broadcast(this, (ETYPE)e)}, where
 520      * {@code EVector} is the vector class specific to the
 521      * the {@code ETYPE} of this species.
 522      * The {@code long} value must be accurately representable
 523      * by {@code ETYPE}, so that {@code e==(long)(ETYPE)e}.
 524      *
 525      * @param e the value to broadcast
 526      * @return a vector where all lane elements are set to
 527      *         the primitive value {@code e}
 528      * @throws IllegalArgumentException
 529      *         if the given {@code long} value cannot
 530      *         be represented by the vector species {@code ETYPE}
 531      * @see Vector#broadcast(long)
 532      * @see #checkValue(long)
 533      */
 534     public abstract Vector<E> broadcast(long e);
 535 
 536     /**
 537      * Checks that this species can represent the given element value,
 538      * and returns the value unchanged.
 539      *
 540      * The {@code long} value must be accurately representable
 541      * by the {@code ETYPE} of the vector species, so that
 542      * {@code e==(long)(ETYPE)e}.
 543      *
 544      * The effect is similar to this pseudocode:
 545      * {@code e == (long)(ETYPE)e
 546      *        ? e
 547      *        : throw new IllegalArgumentException()}.
 548      *
 549      * @param e the value to be checked
 550      * @return {@code e}
 551      * @throws IllegalArgumentException
 552      *         if the given {@code long} value cannot
 553      *         be represented by the vector species {@code ETYPE}
 554      * @see #broadcast(long)
 555      */
 556     public abstract long checkValue(long e);
 557 
 558     /**
 559      * Loads a shuffle for this species from
 560      * a series of source indexes.
 561      *
 562      * <p> For each shuffle lane, where {@code N} is the shuffle lane
 563      * index, the {@code N}th index value is validated
 564      * against the species {@code VLENGTH}, and (if invalid)
 565      * is partially wrapped to an exceptional index in the
 566      * range {@code [-VLENGTH..-1]}.
 567      *
 568      * @param sourceIndexes the source indexes which the shuffle will draw from
 569      * @param offset the offset into the array
 570      * @return a shuffle where each lane's source index is set to the given
 571      *         {@code int} value, partially wrapped if exceptional
 572      * @throws IndexOutOfBoundsException if {@code offset < 0}, or
 573      *         {@code offset > sourceIndexes.length - VLENGTH}
 574      * @see VectorShuffle#fromValues(VectorSpecies,int...)
 575      */
 576     public abstract VectorShuffle<E> shuffleFromValues(int... sourceIndexes);
 577 
 578     /**
 579      * Loads a shuffle for this species from
 580      * an {@code int} array starting at an offset.
 581      *
 582      * <p> For each shuffle lane, where {@code N} is the shuffle lane
 583      * index, the array element at index {@code i + N} is validated
 584      * against the species {@code VLENGTH}, and (if invalid)
 585      * is partially wrapped to an exceptional index in the
 586      * range {@code [-VLENGTH..-1]}.
 587      *
 588      * @param sourceIndexes the source indexes which the shuffle will draw from
 589      * @param offset the offset into the array
 590      * @return a shuffle where each lane's source index is set to the given
 591      *         {@code int} value, partially wrapped if exceptional
 592      * @throws IndexOutOfBoundsException if {@code offset < 0}, or
 593      *         {@code offset > sourceIndexes.length - VLENGTH}
 594      * @see VectorShuffle#fromArray(VectorSpecies,int[],int)
 595      */
 596     public abstract VectorShuffle<E> shuffleFromArray(int[] sourceIndexes, int offset);
 597 
 598     /**
 599      * Loads a shuffle for this species from
 600      * the successive values of an operator applied to
 601      * the range {@code [0..VLENGTH-1]}.
 602      *
 603      * <p> For each shuffle lane, where {@code N} is the shuffle lane
 604      * index, the {@code N}th index value is validated
 605      * against the species {@code VLENGTH}, and (if invalid)
 606      * is partially wrapped to an exceptional index in the
 607      * range {@code [-VLENGTH..-1]}.
 608      *
 609      * <p> Care should be taken to ensure {@code VectorShuffle} values
 610      * produced from this method are consumed as constants to ensure
 611      * optimal generation of code.  For example, shuffle values can be
 612      * held in {@code static final} fields or loop-invariant local variables.
 613      *
 614      * <p> This method behaves as if a shuffle is created from an array of
 615      * mapped indexes as follows:
 616      * <pre>{@code
 617      *   int[] a = new int[species.length()];
 618      *   for (int i = 0; i < a.length; i++) {
 619      *       a[i] = f.applyAsInt(i);
 620      *   }
 621      *   return VectorShuffle.fromArray(this, a, 0);
 622      * }</pre>
 623      *
 624      * @param f the lane index mapping function
 625      * @return a shuffle of mapped indexes
 626      * @see VectorShuffle#fromOp(VectorSpecies,IntUnaryOperator)
 627      */
 628     public abstract VectorShuffle<E> shuffleFromOp(IntUnaryOperator fn);
 629 
 630     /**
 631      * Loads a shuffle using source indexes set to sequential
 632      * values starting from {@code start} and stepping
 633      * by the given {@code step}.
 634      * <p>
 635      * This method returns the value of the expression
 636      * {@code VectorShuffle.fromOp(this, i -> start + i * step)}.
 637      *
 638      * @param start the starting value of the source index sequence
 639      * @param step the difference between adjacent source indexes 
 640      * @return a shuffle of sequential lane indexes
 641      * @see VectorShuffle#iota(VectorSpecies,int,int)
 642      */
 643     public abstract VectorShuffle<E> iotaShuffle(int start, int step);
 644 
 645     /**
 646      * Returns a string of the form "Species[ETYPE, VLENGTH, SHAPE]",
 647      * where {@code ETYPE} is the primitive {@linkplain #elementType()
 648      * lane type}, {@code VLENGTH} is the {@linkplain #length()
 649      * vector lane count} associated with the species, and {@code
 650      * SHAPE} is the {@linkplain #vectorShape() vector shape}
 651      * associated with the species.
 652      *
 653      * @return a string of the form "Species[ETYPE, VLENGTH, SHAPE]"
 654      */
 655     @Override
 656     public abstract String toString();
 657 
 658     /**
 659      * Indicates whether this species is identical to some other object.
 660      * Two species are identical only if they have the same shape
 661      * and same element type.
 662      *
 663      * @return whether this species is identical to some other object
 664      */
 665     @Override
 666     public abstract boolean equals(Object obj);
 667 
 668     /**
 669      * Returns a hash code value for the species,
 670      * based on the vector shape and element type.
 671      *
 672      * @return  a hash code value for this species
 673      */
 674     @Override
 675     public abstract int hashCode();
 676 
 677     // ==== JROSE NAME CHANGES ====
 678 
 679     // ADDED:
 680     // * genericElementType()-> E.class (interop)
 681     // * arrayType()-> ETYPE[].class (interop)
 682     // * withLanes(Class), withShape(VectorShape) strongly typed reinterpret casting
 683     // * static ofLargestShape(Class<E> etype) -> possibly non-preferred
 684     // * static preferredShape() -> common shape of all preferred species
 685     // * toString(), equals(Object), hashCode() (documented)
 686     // * elementSize(e) replaced bitSizeForVectorLength
 687     // * zero(), broadcast(long), from[Byte]Array(), loadMask() (convenience constructors)
 688     // * lanewise(op, [v], [m]), reduceLanesToLong(op, [m])
 689 
 690     /** Renamed to {@link #vectorShape()}. */
 691     @Deprecated
 692     public default VectorShape shape() { return vectorShape(); }
 693 
 694     /** Renamed to {@link #vectorBitSize()}. */
 695     @Deprecated
 696     public default int bitSize() { return vectorBitSize(); }
 697 
 698 }