< prev index next >

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

Print this page
rev 54658 : refactored mask and shuffle creation methods, moved classes to top-level

*** 28,38 **** --- 28,42 ---- import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.annotation.Stable; import java.nio.ByteBuffer; import java.nio.ByteOrder; + import java.util.Objects; + import java.util.function.Function; import java.util.function.IntUnaryOperator; + import java.util.function.UnaryOperator; + import jdk.incubator.vector.*; /** * A {@code Vector} is designed for use in computations that can be transformed * by a runtime compiler, on supported hardware, to Single Instruction Multiple
*** 47,57 **** * {@code byte}, {@code short}, {@code int}, {@code long}, {@code float}, or * {@code double}). The type variable {@code E} corresponds to the boxed * element type, specifically the class that wraps a value of {@code e} in an * object (such the {@code Integer} class that wraps a value of {@code int}}. * A Vector has a {@link #shape() shape} {@code S}, extending type ! * {@link Shape}, that governs the total {@link #bitSize() size} in bits * of the sequence of values. * <p> * The number of values in the sequence is referred to as the Vector * {@link #length() length}. The length also corresponds to the number of * Vector lanes. The lane element at lane index {@code N} (from {@code 0}, --- 51,61 ---- * {@code byte}, {@code short}, {@code int}, {@code long}, {@code float}, or * {@code double}). The type variable {@code E} corresponds to the boxed * element type, specifically the class that wraps a value of {@code e} in an * object (such the {@code Integer} class that wraps a value of {@code int}}. * A Vector has a {@link #shape() shape} {@code S}, extending type ! * {@link VectorShape}, that governs the total {@link #bitSize() size} in bits * of the sequence of values. * <p> * The number of values in the sequence is referred to as the Vector * {@link #length() length}. The length also corresponds to the number of * Vector lanes. The lane element at lane index {@code N} (from {@code 0},
*** 72,89 **** * of element types, {@link ByteVector}, {@link ShortVector}, * {@link IntVector} {@link LongVector}, {@link FloatVector}, and * {@link DoubleVector}. * <p> * Vector values, instances of Vector, are created from a special kind of ! * factory called a {@link Species}. A Species has an * element type and shape and creates Vector values of the same element type * and shape. ! * A species can be {@link Species#of(Class, Shape)} obtained} given an element * type and shape, or a preferred species can be ! * {@link Species#ofPreferred(Class)} obtained} given just an element type where the most * optimal shape is selected for the current platform. It is recommended that ! * Species instances be held in {@code static final} fields for optimal creation * and usage of Vector values by the runtime compiler. * <p> * Vector operations can be grouped into various categories and their behaviour * generally specified as follows: * <ul> --- 76,93 ---- * of element types, {@link ByteVector}, {@link ShortVector}, * {@link IntVector} {@link LongVector}, {@link FloatVector}, and * {@link DoubleVector}. * <p> * Vector values, instances of Vector, are created from a special kind of ! * factory called a {@link VectorSpecies}. A VectorSpecies has an * element type and shape and creates Vector values of the same element type * and shape. ! * A species can be {@link VectorSpecies#of(Class, VectorShape)} obtained} given an element * type and shape, or a preferred species can be ! * {@link VectorSpecies#ofPreferred(Class)} obtained} given just an element type where the most * optimal shape is selected for the current platform. It is recommended that ! * VectorSpecies instances be held in {@code static final} fields for optimal creation * and usage of Vector values by the runtime compiler. * <p> * Vector operations can be grouped into various categories and their behaviour * generally specified as follows: * <ul>
*** 175,185 **** * EVector<S> b = ...; * boolean[] ar = new boolean[a.length()]; * for (int i = 0; i < a.length(); i++) { * ar[i] = scalar_binary_test_op(a.get(i), b.get(i)); * } ! * Mask<E> r = a.species().maskFromArray(ar, 0); * }</pre> * * Unless otherwise specified the two input vectors and result mask will have * the same element type and shape. * --- 179,189 ---- * EVector<S> b = ...; * boolean[] ar = new boolean[a.length()]; * for (int i = 0; i < a.length(); i++) { * ar[i] = scalar_binary_test_op(a.get(i), b.get(i)); * } ! * VectorMask<E> r = a.species().maskFromArray(ar, 0); * }</pre> * * Unless otherwise specified the two input vectors and result mask will have * the same element type and shape. *
*** 189,200 **** * the scalar operation is applied to elements taken from input vectors at the * same lane, and if appropriate applied to the result vector at the same lane. * A further category of operation is a cross-lane vector operation where lane * access is defined by the arguments to the operation. Cross-lane operations * generally rearrange lane elements, for example by permutation (commonly ! * controlled by a {@link Shuffle}) or by blending (commonly controlled by a ! * {@link Mask}). Such an operation explicitly specifies how it rearranges lane * elements. * </ul> * * If a vector operation is represented as an instance method then first input * vector corresponds to {@code this} vector and subsequent input vectors are --- 193,204 ---- * the scalar operation is applied to elements taken from input vectors at the * same lane, and if appropriate applied to the result vector at the same lane. * A further category of operation is a cross-lane vector operation where lane * access is defined by the arguments to the operation. Cross-lane operations * generally rearrange lane elements, for example by permutation (commonly ! * controlled by a {@link VectorShuffle}) or by blending (commonly controlled by a ! * {@link VectorMask}). Such an operation explicitly specifies how it rearranges lane * elements. * </ul> * * If a vector operation is represented as an instance method then first input * vector corresponds to {@code this} vector and subsequent input vectors are
*** 205,215 **** * the operation explicitly specifies how it processes the lane elements of * input vectors, and where appropriate expresses the behaviour using * pseudocode. * * <p> ! * Many vector operations provide an additional {@link Mask mask} accepting * variant. * The mask controls which lanes are selected for application of the scalar * operation. Masks are a key component for the support of control flow in * vector computations. * <p> --- 209,219 ---- * the operation explicitly specifies how it processes the lane elements of * input vectors, and where appropriate expresses the behaviour using * pseudocode. * * <p> ! * Many vector operations provide an additional {@link VectorMask mask} accepting * variant. * The mask controls which lanes are selected for application of the scalar * operation. Masks are a key component for the support of control flow in * vector computations. * <p>
*** 238,248 **** * For convenience many vector operations, of arity greater than one, provide * an additional scalar accepting variant. This variant accepts compatible * scalar values instead of vectors for the second and subsequent input vectors, * if any. * Unless otherwise specified the scalar variant behaves as if each scalar value ! * is transformed to a vector using the vector Species * {@code broadcast} operation, and * then the vector accepting vector operation is applied using the transformed * values. * * <p> --- 242,252 ---- * For convenience many vector operations, of arity greater than one, provide * an additional scalar accepting variant. This variant accepts compatible * scalar values instead of vectors for the second and subsequent input vectors, * if any. * Unless otherwise specified the scalar variant behaves as if each scalar value ! * is transformed to a vector using the vector species * {@code broadcast} operation, and * then the vector accepting vector operation is applied using the transformed * values. * * <p>
*** 260,270 **** /** * Returns the species of this vector. * * @return the species of this vector */ ! public abstract Species<E> species(); /** * Returns the primitive element type of this vector. * * @return the primitive element type of this vector --- 264,274 ---- /** * Returns the species of this vector. * * @return the species of this vector */ ! public abstract VectorSpecies<E> species(); /** * Returns the primitive element type of this vector. * * @return the primitive element type of this vector
*** 281,291 **** /** * Returns the shape of this vector. * * @return the shape of this vector */ ! public Shape shape() { return species().shape(); } /** * Returns the number of vector lanes (the length). * * @return the number of vector lanes --- 285,295 ---- /** * Returns the shape of this vector. * * @return the shape of this vector */ ! public VectorShape shape() { return species().shape(); } /** * Returns the number of vector lanes (the length). * * @return the number of vector lanes
*** 321,331 **** * * @param v the input vector * @param m the mask controlling lane selection * @return the result of adding this vector to the given vector */ ! public abstract Vector<E> add(Vector<E> v, Mask<E> m); /** * Subtracts an input vector from this vector. * <p> * This is a vector binary operation where the primitive subtraction --- 325,335 ---- * * @param v the input vector * @param m the mask controlling lane selection * @return the result of adding this vector to the given vector */ ! public abstract Vector<E> add(Vector<E> v, VectorMask<E> m); /** * Subtracts an input vector from this vector. * <p> * This is a vector binary operation where the primitive subtraction
*** 345,355 **** * * @param v the input vector * @param m the mask controlling lane selection * @return the result of subtracting the input vector from this vector */ ! public abstract Vector<E> sub(Vector<E> v, Mask<E> m); /** * Multiplies this vector with an input vector. * <p> * This is a vector binary operation where the primitive multiplication --- 349,359 ---- * * @param v the input vector * @param m the mask controlling lane selection * @return the result of subtracting the input vector from this vector */ ! public abstract Vector<E> sub(Vector<E> v, VectorMask<E> m); /** * Multiplies this vector with an input vector. * <p> * This is a vector binary operation where the primitive multiplication
*** 369,379 **** * * @param v the input vector * @param m the mask controlling lane selection * @return the result of multiplying this vector with the input vector */ ! public abstract Vector<E> mul(Vector<E> v, Mask<E> m); /** * Negates this vector. * <p> * This is a vector unary operation where the primitive negation operation --- 373,383 ---- * * @param v the input vector * @param m the mask controlling lane selection * @return the result of multiplying this vector with the input vector */ ! public abstract Vector<E> mul(Vector<E> v, VectorMask<E> m); /** * Negates this vector. * <p> * This is a vector unary operation where the primitive negation operation
*** 390,400 **** * ({@code -})is applied to lane elements. * * @param m the mask controlling lane selection * @return the negation this vector */ ! public abstract Vector<E> neg(Mask<E> m); // Maths from java.math /** * Returns the modulus of this vector. --- 394,404 ---- * ({@code -})is applied to lane elements. * * @param m the mask controlling lane selection * @return the negation this vector */ ! public abstract Vector<E> neg(VectorMask<E> m); // Maths from java.math /** * Returns the modulus of this vector.
*** 414,424 **** * {@code (a) -> (a < 0) ? -a : a} is applied to lane elements. * * @param m the mask controlling lane selection * @return the modulus this vector */ ! public abstract Vector<E> abs(Mask<E> m); /** * Returns the minimum of this vector and an input vector. * <p> * This is a vector binary operation where the operation --- 418,428 ---- * {@code (a) -> (a < 0) ? -a : a} is applied to lane elements. * * @param m the mask controlling lane selection * @return the modulus this vector */ ! public abstract Vector<E> abs(VectorMask<E> m); /** * Returns the minimum of this vector and an input vector. * <p> * This is a vector binary operation where the operation
*** 438,448 **** * * @param v the input vector * @param m the mask controlling lane selection * @return the minimum of this vector and the input vector */ ! public abstract Vector<E> min(Vector<E> v, Mask<E> m); /** * Returns the maximum of this vector and an input vector. * <p> * This is a vector binary operation where the operation --- 442,452 ---- * * @param v the input vector * @param m the mask controlling lane selection * @return the minimum of this vector and the input vector */ ! public abstract Vector<E> min(Vector<E> v, VectorMask<E> m); /** * Returns the maximum of this vector and an input vector. * <p> * This is a vector binary operation where the operation
*** 462,472 **** * * @param v the input vector * @param m the mask controlling lane selection * @return the maximum of this vector and the input vector */ ! public abstract Vector<E> max(Vector<E> v, Mask<E> m); // Comparisons /** * Tests if this vector is equal to an input vector. --- 466,476 ---- * * @param v the input vector * @param m the mask controlling lane selection * @return the maximum of this vector and the input vector */ ! public abstract Vector<E> max(Vector<E> v, VectorMask<E> m); // Comparisons /** * Tests if this vector is equal to an input vector.
*** 476,486 **** * * @param v the input vector * @return the result mask of testing if this vector is equal to the input * vector */ ! public abstract Mask<E> equal(Vector<E> v); /** * Tests if this vector is not equal to an input vector. * <p> * This is a vector binary test operation where the primitive not equals --- 480,490 ---- * * @param v the input vector * @return the result mask of testing if this vector is equal to the input * vector */ ! public abstract VectorMask<E> equal(Vector<E> v); /** * Tests if this vector is not equal to an input vector. * <p> * This is a vector binary test operation where the primitive not equals
*** 488,498 **** * * @param v the input vector * @return the result mask of testing if this vector is not equal to the * input vector */ ! public abstract Mask<E> notEqual(Vector<E> v); /** * Tests if this vector is less than an input vector. * <p> * This is a vector binary test operation where the primitive less than --- 492,502 ---- * * @param v the input vector * @return the result mask of testing if this vector is not equal to the * input vector */ ! public abstract VectorMask<E> notEqual(Vector<E> v); /** * Tests if this vector is less than an input vector. * <p> * This is a vector binary test operation where the primitive less than
*** 500,510 **** * * @param v the input vector * @return the mask result of testing if this vector is less than the input * vector */ ! public abstract Mask<E> lessThan(Vector<E> v); /** * Tests if this vector is less or equal to an input vector. * <p> * This is a vector binary test operation where the primitive less than --- 504,514 ---- * * @param v the input vector * @return the mask result of testing if this vector is less than the input * vector */ ! public abstract VectorMask<E> lessThan(Vector<E> v); /** * Tests if this vector is less or equal to an input vector. * <p> * This is a vector binary test operation where the primitive less than
*** 512,522 **** * * @param v the input vector * @return the mask result of testing if this vector is less than or equal * to the input vector */ ! public abstract Mask<E> lessThanEq(Vector<E> v); /** * Tests if this vector is greater than an input vector. * <p> * This is a vector binary test operation where the primitive greater than --- 516,526 ---- * * @param v the input vector * @return the mask result of testing if this vector is less than or equal * to the input vector */ ! public abstract VectorMask<E> lessThanEq(Vector<E> v); /** * Tests if this vector is greater than an input vector. * <p> * This is a vector binary test operation where the primitive greater than
*** 524,534 **** * * @param v the input vector * @return the mask result of testing if this vector is greater than the * input vector */ ! public abstract Mask<E> greaterThan(Vector<E> v); /** * Tests if this vector is greater than or equal to an input vector. * <p> * This is a vector binary test operation where the primitive greater than --- 528,538 ---- * * @param v the input vector * @return the mask result of testing if this vector is greater than the * input vector */ ! public abstract VectorMask<E> greaterThan(Vector<E> v); /** * Tests if this vector is greater than or equal to an input vector. * <p> * This is a vector binary test operation where the primitive greater than
*** 536,546 **** * * @param v the input vector * @return the mask result of testing if this vector is greater than or * equal to the given vector */ ! public abstract Mask<E> greaterThanEq(Vector<E> v); // Elemental shifting /** * Rotates left the lane elements of this vector by the given number of --- 540,550 ---- * * @param v the input vector * @return the mask result of testing if this vector is greater than or * equal to the given vector */ ! public abstract VectorMask<E> greaterThanEq(Vector<E> v); // Elemental shifting /** * Rotates left the lane elements of this vector by the given number of
*** 617,627 **** * @param v the input vector * @param m the mask controlling lane selection * @return the result of blending the lane elements of this vector with * those of an input vector */ ! public abstract Vector<E> blend(Vector<E> v, Mask<E> m); /** * Rearranges the lane elements of this vector and those of an input vector, * selecting lane indexes controlled by shuffles and a mask. * <p> --- 621,631 ---- * @param v the input vector * @param m the mask controlling lane selection * @return the result of blending the lane elements of this vector with * those of an input vector */ ! public abstract Vector<E> blend(Vector<E> v, VectorMask<E> m); /** * Rearranges the lane elements of this vector and those of an input vector, * selecting lane indexes controlled by shuffles and a mask. * <p>
*** 642,652 **** * those of an input vector */ @ForceInline // rearrange public abstract Vector<E> rearrange(Vector<E> v, ! Shuffle<E> s, Mask<E> m); /** * Rearranges the lane elements of this vector selecting lane indexes * controlled by a shuffle. * <p> --- 646,656 ---- * those of an input vector */ @ForceInline // rearrange public abstract Vector<E> rearrange(Vector<E> v, ! VectorShuffle<E> s, VectorMask<E> m); /** * Rearranges the lane elements of this vector selecting lane indexes * controlled by a shuffle. * <p>
*** 658,668 **** * * @param s the shuffle controlling lane index selection * @return the rearrangement of the lane elements of this vector */ // rearrange ! public abstract Vector<E> rearrange(Shuffle<E> s); // Conversions /** --- 662,672 ---- * * @param s the shuffle controlling lane index selection * @return the rearrangement of the lane elements of this vector */ // rearrange ! public abstract Vector<E> rearrange(VectorShuffle<E> s); // Conversions /**
*** 681,691 **** * return this.species().shuffleFromValues(sa); * }</pre> * * @return a shuffle representation of this vector */ ! public abstract Shuffle<E> toShuffle(); // Bitwise preserving /** * Transforms this vector to a vector of the given species of element type {@code F}. --- 685,695 ---- * return this.species().shuffleFromValues(sa); * }</pre> * * @return a shuffle representation of this vector */ ! public abstract VectorShuffle<E> toShuffle(); // Bitwise preserving /** * Transforms this vector to a vector of the given species of element type {@code F}.
*** 711,733 **** * The following pseudocode expresses the behaviour: * <pre>{@code * int blen = Math.max(this.bitSize(), s.bitSize()) / Byte.SIZE; * ByteBuffer bb = ByteBuffer.allocate(blen).order(ByteOrder.nativeOrder()); * this.intoByteBuffer(bb, 0); ! * return s.fromByteBuffer(bb, 0); * }</pre> * * @param s species of desired vector * @param <F> the boxed element type of the species * @return a vector transformed, by shape and element type, from this vector */ @ForceInline ! public abstract <F> Vector<F> reinterpret(Species<F> s); @ForceInline @SuppressWarnings("unchecked") ! <F> Vector<F> defaultReinterpret(Species<F> s) { int blen = Math.max(s.bitSize(), this.species().bitSize()) / Byte.SIZE; ByteBuffer bb = ByteBuffer.allocate(blen).order(ByteOrder.nativeOrder()); this.intoByteBuffer(bb, 0); Class<?> stype = s.elementType(); --- 715,737 ---- * The following pseudocode expresses the behaviour: * <pre>{@code * int blen = Math.max(this.bitSize(), s.bitSize()) / Byte.SIZE; * ByteBuffer bb = ByteBuffer.allocate(blen).order(ByteOrder.nativeOrder()); * this.intoByteBuffer(bb, 0); ! * return $type$Vector.fromByteBuffer(s, bb, 0); * }</pre> * * @param s species of desired vector * @param <F> the boxed element type of the species * @return a vector transformed, by shape and element type, from this vector */ @ForceInline ! public abstract <F> Vector<F> reinterpret(VectorSpecies<F> s); @ForceInline @SuppressWarnings("unchecked") ! <F> Vector<F> defaultReinterpret(VectorSpecies<F> s) { int blen = Math.max(s.bitSize(), this.species().bitSize()) / Byte.SIZE; ByteBuffer bb = ByteBuffer.allocate(blen).order(ByteOrder.nativeOrder()); this.intoByteBuffer(bb, 0); Class<?> stype = s.elementType();
*** 762,778 **** * The following pseudocode expresses the behaviour: * <pre>{@code * int alen = Math.max(this.bitSize(), s.bitSize()) / Byte.SIZE; * byte[] a = new byte[alen]; * this.intoByteArray(a, 0); ! * return s.fromByteArray(a, 0); * }</pre> * * @param s species of the desired vector * @return a vector transformed, by shape, from this vector */ ! public abstract Vector<E> reshape(Species<E> s); // Cast /** * Converts this vector to a vector of the given species element type {@code F}. --- 766,782 ---- * The following pseudocode expresses the behaviour: * <pre>{@code * int alen = Math.max(this.bitSize(), s.bitSize()) / Byte.SIZE; * byte[] a = new byte[alen]; * this.intoByteArray(a, 0); ! * return $type$Vector.fromByteArray(s, a, 0); * }</pre> * * @param s species of the desired vector * @return a vector transformed, by shape, from this vector */ ! public abstract Vector<E> reshape(VectorSpecies<E> s); // Cast /** * Converts this vector to a vector of the given species element type {@code F}.
*** 789,799 **** * * @param s species of the desired vector * @param <F> the boxed element type of the species * @return a vector converted by shape and element type from this vector */ ! public abstract <F> Vector<F> cast(Species<F> s); //Array stores /** * Stores this vector into a byte array starting at an offset. --- 793,803 ---- * * @param s species of the desired vector * @param <F> the boxed element type of the species * @return a vector converted by shape and element type from this vector */ ! public abstract <F> Vector<F> cast(VectorSpecies<F> s); //Array stores /** * Stores this vector into a byte array starting at an offset.
*** 801,811 **** * Bytes are extracted from primitive lane elements according to the * native byte order of the underlying platform. * <p> * This method behaves as it calls the * byte buffer, offset, and mask accepting ! * {@link #intoByteBuffer(ByteBuffer, int, Mask) method} as follows: * <pre>{@code * return this.intoByteBuffer(ByteBuffer.wrap(a), i, this.maskAllTrue()); * }</pre> * * @param a the byte array --- 805,815 ---- * Bytes are extracted from primitive lane elements according to the * native byte order of the underlying platform. * <p> * This method behaves as it calls the * byte buffer, offset, and mask accepting ! * {@link #intoByteBuffer(ByteBuffer, int, VectorMask) method} as follows: * <pre>{@code * return this.intoByteBuffer(ByteBuffer.wrap(a), i, this.maskAllTrue()); * }</pre> * * @param a the byte array
*** 822,832 **** * Bytes are extracted from primitive lane elements according to the * native byte order of the underlying platform. * <p> * This method behaves as it calls the * byte buffer, offset, and mask accepting ! * {@link #intoByteBuffer(ByteBuffer, int, Mask) method} as follows: * <pre>{@code * return this.intoByteBuffer(ByteBuffer.wrap(a), i, m); * }</pre> * * @param a the byte array --- 826,836 ---- * Bytes are extracted from primitive lane elements according to the * native byte order of the underlying platform. * <p> * This method behaves as it calls the * byte buffer, offset, and mask accepting ! * {@link #intoByteBuffer(ByteBuffer, int, VectorMask) method} as follows: * <pre>{@code * return this.intoByteBuffer(ByteBuffer.wrap(a), i, m); * }</pre> * * @param a the byte array
*** 836,857 **** * or {@code > a.length}, * for any vector lane index {@code N} where the mask at lane {@code N} * is set * {@code i >= a.length - (N * this.elementSize() / Byte.SIZE)} */ ! public abstract void intoByteArray(byte[] a, int i, Mask<E> m); /** * Stores this vector into a {@link ByteBuffer byte buffer} starting at an * offset into the byte buffer. * <p> * Bytes are extracted from primitive lane elements according to the * native byte order of the underlying platform. * <p> * This method behaves as if it calls the byte buffer, offset, and mask * accepting ! * {@link #intoByteBuffer(ByteBuffer, int, Mask)} method} as follows: * <pre>{@code * this.intoByteBuffer(b, i, this.maskAllTrue()) * }</pre> * * @param b the byte buffer --- 840,861 ---- * or {@code > a.length}, * for any vector lane index {@code N} where the mask at lane {@code N} * is set * {@code i >= a.length - (N * this.elementSize() / Byte.SIZE)} */ ! public abstract void intoByteArray(byte[] a, int i, VectorMask<E> m); /** * Stores this vector into a {@link ByteBuffer byte buffer} starting at an * offset into the byte buffer. * <p> * Bytes are extracted from primitive lane elements according to the * native byte order of the underlying platform. * <p> * This method behaves as if it calls the byte buffer, offset, and mask * accepting ! * {@link #intoByteBuffer(ByteBuffer, int, VectorMask)} method} as follows: * <pre>{@code * this.intoByteBuffer(b, i, this.maskAllTrue()) * }</pre> * * @param b the byte buffer
*** 896,1549 **** * or {@code > b.limit()}, * for any vector lane index {@code N} where the mask at lane {@code N} * is set * {@code i >= b.limit() - (N * this.elementSize() / Byte.SIZE)} bytes */ ! public abstract void intoByteBuffer(ByteBuffer b, int i, Mask<E> m); ! ! ! /** ! * A {@code Shape} governs the total size, in bits, of a ! * {@link Vector}, {@link Mask}, or {@link Shuffle}. The shape in ! * combination with the element type together govern the number of lanes. ! */ ! public enum Shape { ! /** Shape of length 64 bits */ ! S_64_BIT(64), ! /** Shape of length 128 bits */ ! S_128_BIT(128), ! /** Shape of length 256 bits */ ! S_256_BIT(256), ! /** Shape of length 512 bits */ ! S_512_BIT(512), ! /** Shape of maximum length supported on the platform */ ! S_Max_BIT(Unsafe.getUnsafe().getMaxVectorSize(byte.class) * 8); ! ! @Stable ! final int bitSize; ! ! Shape(int bitSize) { ! this.bitSize = bitSize; ! } ! ! /** ! * Returns the size, in bits, of this shape. ! * ! * @return the size, in bits, of this shape. ! */ ! public int bitSize() { ! return bitSize; ! } ! ! /** ! * Return the number of lanes of a vector of this shape and whose element ! * type is of the provided species ! * ! * @param s the species describing the element type ! * @return the number of lanes ! */ ! int length(Species<?> s) { ! return bitSize() / s.elementSize(); ! } ! ! /** ! * Finds appropriate shape depending on bitsize. ! * ! * @param bitSize the size in bits ! * @return the shape corresponding to bitsize ! * @see #bitSize ! */ ! public static Shape forBitSize(int bitSize) { ! switch (bitSize) { ! case 64: ! return Shape.S_64_BIT; ! case 128: ! return Shape.S_128_BIT; ! case 256: ! return Shape.S_256_BIT; ! case 512: ! return Shape.S_512_BIT; ! default: ! if ((bitSize > 0) && (bitSize <= 2048) && (bitSize % 128 == 0)) { ! return Shape.S_Max_BIT; ! } else { ! throw new IllegalArgumentException("Bad vector bit size: " + bitSize); ! } ! } ! } ! } ! ! ! /** ! * Class representing vectors of same element type, {@code E} and {@link Vector.Shape Shape}. ! * ! * @param <E> the boxed element type of this species ! */ ! public static abstract class Species<E> { ! Species() {} ! ! /** ! * Returns the primitive element type of vectors produced by this ! * species. ! * ! * @return the primitive element type ! */ ! public abstract Class<E> elementType(); ! ! /** ! * Returns the vector box type for this species ! * ! * @return the box type ! */ ! abstract Class<?> boxType(); ! ! /** ! * Returns the vector mask type for this species ! * ! * @return the box type ! */ ! abstract Class<?> maskType(); ! ! /** ! * Returns the element size, in bits, of vectors produced by this ! * species. ! * ! * @return the element size, in bits ! */ ! public abstract int elementSize(); ! ! /** ! * Returns the shape of masks, shuffles, and vectors produced by this ! * species. ! * ! * @return the primitive element type ! */ ! public abstract Shape shape(); ! ! /** ! * Returns the shape of the corresponding index species ! * @return the shape ! */ ! @ForceInline ! public abstract Shape indexShape(); ! ! /** ! * Returns the mask, shuffe, or vector lanes produced by this species. ! * ! * @return the the number of lanes ! */ ! public int length() { return shape().length(this); } ! ! /** ! * Returns the total vector size, in bits, of vectors produced by this ! * species. ! * ! * @return the total vector size, in bits ! */ ! public int bitSize() { return shape().bitSize(); } ! ! // Factory ! ! /** ! * Finds a species for an element type and shape. ! * ! * @param c the element type ! * @param s the shape ! * @param <E> the boxed element type ! * @return a species for an element type and shape ! * @throws IllegalArgumentException if no such species exists for the ! * element type and/or shape ! */ ! @SuppressWarnings("unchecked") ! public static <E> Vector.Species<E> of(Class<E> c, Shape s) { ! if (c == float.class) { ! return (Vector.Species<E>) FloatVector.species(s); ! } ! else if (c == double.class) { ! return (Vector.Species<E>) DoubleVector.species(s); ! } ! else if (c == byte.class) { ! return (Vector.Species<E>) ByteVector.species(s); ! } ! else if (c == short.class) { ! return (Vector.Species<E>) ShortVector.species(s); ! } ! else if (c == int.class) { ! return (Vector.Species<E>) IntVector.species(s); ! } ! else if (c == long.class) { ! return (Vector.Species<E>) LongVector.species(s); ! } ! else { ! throw new IllegalArgumentException("Bad vector element type: " + c.getName()); ! } ! } ! ! /** ! * Finds a preferred species for an element type. ! * <p> ! * A preferred species is a species chosen by the platform that has a ! * shape of maximal bit size. A preferred species for different element ! * types will have the same shape, and therefore vectors created from ! * such species will be shape compatible. ! * ! * @param c the element type ! * @param <E> the boxed element type ! * @return a preferred species for an element type ! * @throws IllegalArgumentException if no such species exists for the ! * element type ! */ ! public static <E> Vector.Species<E> ofPreferred(Class<E> c) { ! Unsafe u = Unsafe.getUnsafe(); ! ! int vectorLength = u.getMaxVectorSize(c); ! int vectorBitSize = bitSizeForVectorLength(c, vectorLength); ! Shape s = Shape.forBitSize(vectorBitSize); ! return Species.of(c, s); ! } ! } ! ! abstract static class AbstractSpecies<E> extends Vector.Species<E> { ! @Stable ! protected final Vector.Shape shape; ! @Stable ! protected final Class<E> elementType; ! @Stable ! protected final int elementSize; ! @Stable ! protected final Class<?> boxType; ! @Stable ! protected final Class<?> maskType; ! @Stable ! protected final Shape indexShape; ! ! AbstractSpecies(Vector.Shape shape, Class<E> elementType, int elementSize, Class<?> boxType, Class<?> maskType) { ! this.shape = shape; ! this.elementType = elementType; ! this.elementSize = elementSize; ! this.boxType = boxType; ! this.maskType = maskType; ! ! if (boxType == Long64Vector.class || boxType == Double64Vector.class) { ! indexShape = Vector.Shape.S_64_BIT; ! } ! else { ! int bitSize = Vector.bitSizeForVectorLength(int.class, shape.bitSize() / elementSize); ! indexShape = Vector.Shape.forBitSize(bitSize); ! } ! } ! ! @Override ! @ForceInline ! public int bitSize() { ! return shape.bitSize(); ! } ! ! @Override ! @ForceInline ! public int length() { ! return shape.bitSize() / elementSize; ! } ! ! @Override ! @ForceInline ! public Class<E> elementType() { ! return elementType; ! } ! ! @Override ! @ForceInline ! public Class<?> boxType() { ! return boxType; ! } ! ! @Override ! @ForceInline ! public Class<?> maskType() { ! return maskType; ! } ! ! @Override ! @ForceInline ! public int elementSize() { ! return elementSize; ! } ! ! @Override ! @ForceInline ! public Vector.Shape shape() { ! return shape; ! } ! ! @Override ! @ForceInline ! public Vector.Shape indexShape() { return indexShape; } ! ! @Override ! public String toString() { ! return new StringBuilder("Shape[") ! .append(bitSize()).append(" bits, ") ! .append(length()).append(" ").append(elementType.getSimpleName()).append("s x ") ! .append(elementSize()).append(" bits") ! .append("]") ! .toString(); ! } ! } ! ! /** ! * A {@code Mask} represents an ordered immutable sequence of {@code boolean} ! * values. A Mask can be used with a mask accepting vector operation to ! * control the selection and operation of lane elements of input vectors. ! * <p> ! * The number of values in the sequence is referred to as the Mask ! * {@link #length() length}. The length also corresponds to the number of ! * Mask lanes. The lane element at lane index {@code N} (from {@code 0}, ! * inclusive, to length, exclusive) corresponds to the {@code N + 1}'th ! * value in the sequence. ! * A Mask and Vector of the same element type and shape have the same number ! * of lanes. ! * <p> ! * A lane is said to be <em>set</em> if the lane element is {@code true}, ! * otherwise a lane is said to be <em>unset</em> if the lane element is ! * {@code false}. ! * <p> ! * Mask declares a limited set of unary, binary and reductive mask ! * operations. ! * <ul> ! * <li> ! * A mask unary operation (1-ary) operates on one input mask to produce a ! * result mask. ! * For each lane of the input mask the ! * lane element is operated on using the specified scalar unary operation and ! * the boolean result is placed into the mask result at the same lane. ! * The following pseudocode expresses the behaviour of this operation category: ! * ! * <pre>{@code ! * Mask<E> a = ...; ! * boolean[] ar = new boolean[a.length()]; ! * for (int i = 0; i < a.length(); i++) { ! * ar[i] = boolean_unary_op(a.isSet(i)); ! * } ! * Mask<E> r = a.species().maskFromArray(ar, 0); ! * }</pre> ! * ! * <li> ! * A mask binary operation (2-ary) operates on two input ! * masks to produce a result mask. ! * For each lane of the two input masks, ! * a and b say, the corresponding lane elements from a and b are operated on ! * using the specified scalar binary operation and the boolean result is placed ! * into the mask result at the same lane. ! * The following pseudocode expresses the behaviour of this operation category: ! * ! * <pre>{@code ! * Mask<E> a = ...; ! * Mask<E> b = ...; ! * boolean[] ar = new boolean[a.length()]; ! * for (int i = 0; i < a.length(); i++) { ! * ar[i] = scalar_binary_op(a.isSet(i), b.isSet(i)); ! * } ! * Mask<E> r = a.species().maskFromArray(ar, 0); ! * }</pre> ! * ! * </ul> ! * @param <E> the boxed element type of this mask ! */ ! public static abstract class Mask<E> { ! Mask() {} ! ! /** ! * Returns the species of this mask. ! * ! * @return the species of this mask ! */ ! public abstract Species<E> species(); ! ! /** ! * Returns the number of mask lanes (the length). ! * ! * @return the number of mask lanes ! */ ! public int length() { return species().length(); } ! ! /** ! * Converts this mask to a mask of the given species shape of element type {@code F}. ! * <p> ! * For each mask lane, where {@code N} is the lane index, if the ! * mask lane at index {@code N} is set, then the mask lane at index ! * {@code N} of the resulting mask is set, otherwise that mask lane is ! * not set. ! * ! * @param s the species of the desired mask ! * @param <F> the boxed element type of the species ! * @return a mask converted by shape and element type ! * @throws IllegalArgumentException if this mask length and the species ! * length differ ! */ ! public abstract <F> Mask<F> cast(Species<F> s); ! ! /** ! * Returns the lane elements of this mask packed into a {@code long} ! * value for at most the first 64 lane elements. ! * <p> ! * The lane elements are packed in the order of least significant bit ! * to most significant bit. ! * For each mask lane where {@code N} is the mask lane index, if the ! * mask lane is set then the {@code N}'th bit is set to one in the ! * resulting {@code long} value, otherwise the {@code N}'th bit is set ! * to zero. ! * ! * @return the lane elements of this mask packed into a {@code long} ! * value. ! */ ! public abstract long toLong(); ! ! /** ! * Returns an {@code boolean} array containing the lane elements of this ! * mask. ! * <p> ! * This method behaves as if it {@link #intoArray(boolean[], int)} stores} ! * this mask into an allocated array and returns that array as ! * follows: ! * <pre>{@code ! * boolean[] a = new boolean[this.length()]; ! * this.intoArray(a, 0); ! * return a; ! * }</pre> ! * ! * @return an array containing the the lane elements of this vector ! */ ! public abstract boolean[] toArray(); ! ! /** ! * Stores this mask into a {@code boolean} array starting at offset. ! * <p> ! * For each mask lane, where {@code N} is the mask lane index, ! * the lane element at index {@code N} is stored into the array at index ! * {@code i + N}. ! * ! * @param a the array ! * @param i the offset into the array ! * @throws IndexOutOfBoundsException if {@code i < 0}, or ! * {@code i > a.length - this.length()} ! */ ! public abstract void intoArray(boolean[] a, int i); ! ! /** ! * Returns {@code true} if any of the mask lanes are set. ! * ! * @return {@code true} if any of the mask lanes are set, otherwise ! * {@code false}. ! */ ! public abstract boolean anyTrue(); ! ! /** ! * Returns {@code true} if all of the mask lanes are set. ! * ! * @return {@code true} if all of the mask lanes are set, otherwise ! * {@code false}. ! */ ! public abstract boolean allTrue(); ! ! /** ! * Returns the number of mask lanes that are set. ! * ! * @return the number of mask lanes that are set. ! */ ! public abstract int trueCount(); ! ! /** ! * Logically ands this mask with an input mask. ! * <p> ! * This is a mask binary operation where the logical and operation ! * ({@code &&} is applied to lane elements. ! * ! * @param o the input mask ! * @return the result of logically and'ing this mask with an input mask ! */ ! public abstract Mask<E> and(Mask<E> o); ! ! /** ! * Logically ors this mask with an input mask. ! * <p> ! * This is a mask binary operation where the logical or operation ! * ({@code ||} is applied to lane elements. ! * ! * @param o the input mask ! * @return the result of logically or'ing this mask with an input mask ! */ ! public abstract Mask<E> or(Mask<E> o); ! ! /** ! * Logically negates this mask. ! * <p> ! * This is a mask unary operation where the logical not operation ! * ({@code !} is applied to lane elements. ! * ! * @return the result of logically negating this mask. ! */ ! public abstract Mask<E> not(); ! ! /** ! * Returns a vector representation of this mask. ! * <p> ! * For each mask lane, where {@code N} is the mask lane index, ! * if the mask lane is set then an element value whose most significant ! * bit is set is placed into the resulting vector at lane index ! * {@code N}, otherwise the default element value is placed into the ! * resulting vector at lane index {@code N}. ! * ! * @return a vector representation of this mask. ! */ ! public abstract Vector<E> toVector(); ! ! /** ! * Tests if the lane at index {@code i} is set ! * @param i the lane index ! * ! * @return true if the lane at index {@code i} is set, otherwise false ! */ ! public abstract boolean getElement(int i); ! ! /** ! * Tests if the lane at index {@code i} is set ! * @param i the lane index ! * @return true if the lane at index {@code i} is set, otherwise false ! * @see #getElement ! */ ! public boolean isSet(int i) { ! return getElement(i); ! } ! } ! ! /** ! * A {@code Shuffle} represents an ordered immutable sequence of ! * {@code int} values. A Shuffle can be used with a shuffle accepting ! * vector operation to control the rearrangement of lane elements of input ! * vectors ! * <p> ! * The number of values in the sequence is referred to as the Shuffle ! * {@link #length() length}. The length also corresponds to the number of ! * Shuffle lanes. The lane element at lane index {@code N} (from {@code 0}, ! * inclusive, to length, exclusive) corresponds to the {@code N + 1}'th ! * value in the sequence. ! * A Shuffle and Vector of the same element type and shape have the same ! * number of lanes. ! * <p> ! * A Shuffle describes how a lane element of a vector may cross lanes from ! * its lane index, {@code i} say, to another lane index whose value is the ! * Shuffle's lane element at lane index {@code i}. Shuffle lane elements ! * will be in the range of {@code 0} (inclusive) to the shuffle length ! * (exclusive), and therefore cannot induce out of bounds errors when ! * used with vectors operations and vectors of the same length. ! * ! * @param <E> the boxed element type of this mask ! */ ! public static abstract class Shuffle<E> { ! Shuffle() {} ! ! /** ! * Returns the species of this shuffle. ! * ! * @return the species of this shuffle ! */ ! public abstract Species<E> species(); ! ! /** ! * Returns the number of shuffle lanes (the length). ! * ! * @return the number of shuffle lanes ! */ ! public int length() { return species().length(); } ! ! /** ! * Converts this shuffle to a shuffle of the given species of element type {@code F}. ! * <p> ! * For each shuffle lane, where {@code N} is the lane index, the ! * shuffle element at index {@code N} is placed, unmodified, into the ! * resulting shuffle at index {@code N}. ! * ! * @param species species of desired shuffle ! * @param <F> the boxed element type of the species ! * @return a shuffle converted by shape and element type ! * @throws IllegalArgumentException if this shuffle length and the ! * species length differ ! */ ! public abstract <F> Shuffle<F> cast(Species<F> species); ! ! /** ! * Returns an {@code int} array containing the lane elements of this ! * shuffle. ! * <p> ! * This method behaves as if it {@link #intoArray(int[], int)} stores} ! * this shuffle into an allocated array and returns that array as ! * follows: ! * <pre>{@code ! * int[] a = new int[this.length()]; ! * this.intoArray(a, 0); ! * return a; ! * }</pre> ! * ! * @return an array containing the the lane elements of this vector ! */ ! public abstract int[] toArray(); ! ! /** ! * Stores this shuffle into an {@code int} array starting at offset. ! * <p> ! * For each shuffle lane, where {@code N} is the shuffle lane index, ! * the lane element at index {@code N} is stored into the array at index ! * {@code i + N}. ! * ! * @param a the array ! * @param i the offset into the array ! * @throws IndexOutOfBoundsException if {@code i < 0}, or ! * {@code i > a.length - this.length()} ! */ ! public abstract void intoArray(int[] a, int i); ! ! /** ! * Converts this shuffle into a vector, creating a vector from shuffle ! * lane elements (int values) cast to the vector element type. ! * <p> ! * This method behaves as if it returns the result of creating a ! * vector given an {@code int} array obtained from this shuffle's ! * lane elements, as follows: ! * <pre>{@code ! * int[] sa = this.toArray(); ! * $type$[] va = new $type$[a.length]; ! * for (int i = 0; i < a.length; i++) { ! * va[i] = ($type$) sa[i]; ! * } ! * return this.species().fromArray(va, 0); ! * }</pre> ! * ! * @return a vector representation of this shuffle ! */ ! public abstract Vector<E> toVector(); ! ! /** ! * Gets the {@code int} lane element at lane index {@code i} ! * ! * @param i the lane index ! * @return the {@code int} lane element at lane index {@code i} ! */ ! public int getElement(int i) { return toArray()[i]; } ! ! /** ! * Rearranges the lane elements of this shuffle selecting lane indexes ! * controlled by another shuffle. ! * <p> ! * For each lane of the shuffle, at lane index {@code N} with lane ! * element {@code I}, the lane element at {@code I} from this shuffle is ! * selected and placed into the resulting shuffle at {@code N}. ! * ! * @param s the shuffle controlling lane index selection ! * @return the rearrangement of the lane elements of this shuffle ! */ ! public abstract Shuffle<E> rearrange(Shuffle<E> s); ! } /** * Find bit size based on element type and number of elements. * * @param c the element type --- 900,910 ---- * or {@code > b.limit()}, * for any vector lane index {@code N} where the mask at lane {@code N} * is set * {@code i >= b.limit() - (N * this.elementSize() / Byte.SIZE)} bytes */ ! public abstract void intoByteBuffer(ByteBuffer b, int i, VectorMask<E> m); /** * Find bit size based on element type and number of elements. * * @param c the element type
< prev index next >