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