/* * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have * questions. */ package jdk.incubator.vector; import jdk.internal.misc.Unsafe; 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 * Data (SIMD) computations leveraging vector hardware registers and vector * hardware instructions. Such SIMD computations exploit data parallelism to * perform the same operation on multiple data points simultaneously in * less time than it would ordinarily take to perform the same operation * sequentially on each data point. *

* A Vector represents an ordered immutable sequence of values of the same * element type {@code e} that is one of the following primitive types * {@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. * The combination of element type and shape determines a vector species, * represented by {@link jdk.incubator.vector.VectorSpecies}. *

* 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}, * inclusive, to length, exclusive) corresponds to the {@code N + 1}'th value in * the sequence. * Note: this arrangement * of Vector bit size, Vector length, element bit size, and lane element index * has no bearing on how a Vector instance and its sequence of elements may be * arranged in memory or represented as a value in a vector hardware register. *

* Vector declares a set of vector operations (methods) that are common to all * element types (such as addition). Sub-classes of Vector with a concrete * boxed element type declare further operations that are specific to that * element type (such as access to element values in lanes, logical operations * on values of integral elements types, or transcendental operations on values * of floating point element types). * There are six abstract sub-classes of Vector corresponding to the supported set * of element types, {@link ByteVector}, {@link ShortVector}, * {@link IntVector} {@link LongVector}, {@link FloatVector}, and * {@link DoubleVector}. Along with type-specific operations these classes * support creation of vector values (instances of Vector). * They expose static constants corresponding to the supported species, * and static methods on these types generally take a species as a parameter. * For example, * {@link jdk.incubator.vector.FloatVector#fromArray(VectorSpecies, float[], int) FloatVector.fromArray()} * creates and returns a float vector of the specified species, with elements * loaded from the specified float array. *

* 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. *

* Vector operations can be grouped into various categories and their behavior * generally specified as follows: *

* *

* If a vector operation does not belong to one of the above categories then * the operation explicitly specifies how it processes the lane elements of * input vectors, and where appropriate expresses the behavior using * pseudocode. * *

* 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. *

* Many vector operations provide an additional {@link jdk.incubator.vector.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. *

* For certain operation categories the mask accepting variants can be specified * in generic terms. If a lane of the mask is set then the scalar operation is * applied to corresponding lane elements, otherwise if a lane of a mask is not * set then a default scalar operation is applied and its result is placed into * the vector result at the same lane. The default operation is specified as follows: *

* Otherwise, the mask accepting variant of the operation explicitly specifies * how it processes the lane elements of input vectors, and where appropriate * expresses the behavior using pseudocode. * *

* For convenience, many vector operations of arity greater than one provide * an additional scalar-accepting variant (such as adding a constant scalar * value to all lanes of a vector). 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 appropriate vector {@code broadcast} operation, and * then the vector accepting vector operation is applied using the transformed * values. * *

* This is a value-based * class; use of identity-sensitive operations (including reference equality * ({@code ==}), identity hash code, or synchronization) on instances of * {@code Vector} may have unpredictable results and should be avoided. * * @param the boxed element type of elements in this vector */ public abstract class Vector { Vector() {} /** * Returns the species of this vector. * * @return the species of this vector */ public abstract VectorSpecies species(); /** * Returns the primitive element type of this vector. * * @return the primitive element type of this vector */ public Class elementType() { return species().elementType(); } /** * Returns the element size, in bits, of this vector. * * @return the element size, in bits, of this vector */ public int elementSize() { return species().elementSize(); } /** * 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 */ public int length() { return species().length(); } /** * Returns the total size, in bits, of this vector. * * @return the total size, in bits, of this vector */ public int bitSize() { return species().bitSize(); } //Arithmetic /** * Adds this vector to an input vector. *

* This is a lane-wise binary operation which applies the primitive addition operation * ({@code +}) to each lane. * * @param v the input vector * @return the result of adding this vector to the input vector */ public abstract Vector add(Vector v); /** * Adds this vector to an input vector, selecting lane elements * controlled by a mask. *

* This is a lane-wise binary operation which applies the primitive addition operation * ({@code +}) to each lane. * * @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 add(Vector v, VectorMask m); /** * Subtracts an input vector from this vector. *

* This is a lane-wise binary operation which applies the primitive subtraction * operation ({@code -}) to each lane. * * @param v the input vector * @return the result of subtracting the input vector from this vector */ public abstract Vector sub(Vector v); /** * Subtracts an input vector from this vector, selecting lane elements * controlled by a mask. *

* This is a lane-wise binary operation which applies the primitive subtraction * operation ({@code -}) to each lane. * * @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 sub(Vector v, VectorMask m); /** * Multiplies this vector with an input vector. *

* This is a lane-wise binary operation which applies the primitive multiplication * operation ({@code *}) to each lane. * * @param v the input vector * @return the result of multiplying this vector with the input vector */ public abstract Vector mul(Vector v); /** * Multiplies this vector with an input vector, selecting lane elements * controlled by a mask. *

* This is a lane-wise binary operation which applies the primitive multiplication * operation ({@code *}) to each lane. * * @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 mul(Vector v, VectorMask m); /** * Negates this vector. *

* This is a lane-wise unary operation which applies the primitive negation operation * ({@code -}) to each lane. * * @return the negation this vector */ public abstract Vector neg(); /** * Negates this vector, selecting lane elements controlled by a mask. *

* This is a lane-wise unary operation which applies the primitive negation operation * ({@code -}) to each lane. * * @param m the mask controlling lane selection * @return the negation this vector */ public abstract Vector neg(VectorMask m); // Maths from java.math /** * Returns the modulus of this vector. *

* This is a lane-wise unary operation which applies the operation * {@code (a) -> (a < 0) ? -a : a} to each lane. * * @return the modulus this vector */ public abstract Vector abs(); /** * Returns the modulus of this vector, selecting lane elements controlled by * a mask. *

* This is a lane-wise unary operation which applies the operation * {@code (a) -> (a < 0) ? -a : a} to each lane. * * @param m the mask controlling lane selection * @return the modulus this vector */ public abstract Vector abs(VectorMask m); /** * Returns the minimum of this vector and an input vector. *

* This is a lane-wise binary operation which applies the operation * {@code (a, b) -> a < b ? a : b} to each lane. * * @param v the input vector * @return the minimum of this vector and the input vector */ public abstract Vector min(Vector v); /** * Returns the minimum of this vector and an input vector, * selecting lane elements controlled by a mask. *

* This is a lane-wise binary operation which applies the operation * {@code (a, b) -> a < b ? a : b} to each lane. * * @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 min(Vector v, VectorMask m); /** * Returns the maximum of this vector and an input vector. *

* This is a lane-wise binary operation which applies the operation * {@code (a, b) -> a > b ? a : b} to each lane. * * @param v the input vector * @return the maximum of this vector and the input vector */ public abstract Vector max(Vector v); /** * Returns the maximum of this vector and an input vector, * selecting lane elements controlled by a mask. *

* This is a lane-wise binary operation which applies the operation * {@code (a, b) -> a > b ? a : b} to each lane. * * @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 max(Vector v, VectorMask m); // Comparisons /** * Tests if this vector is equal to an input vector. *

* This is a lane-wise binary test operation which applies the primitive equals * operation ({@code ==}) to each lane. * * @param v the input vector * @return the result mask of testing if this vector is equal to the input * vector */ public abstract VectorMask equal(Vector v); /** * Tests if this vector is not equal to an input vector. *

* This is a lane-wise binary test operation which applies the primitive not equals * operation ({@code !=}) to each lane. * * @param v the input vector * @return the result mask of testing if this vector is not equal to the * input vector */ public abstract VectorMask notEqual(Vector v); /** * Tests if this vector is less than an input vector. *

* This is a lane-wise binary test operation which applies the primitive less than * operation ({@code <}) to each lane. * * @param v the input vector * @return the mask result of testing if this vector is less than the input * vector */ public abstract VectorMask lessThan(Vector v); /** * Tests if this vector is less or equal to an input vector. *

* This is a lane-wise binary test operation which applies the primitive less than * or equal to operation ({@code <=}) to each lane. * * @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 lessThanEq(Vector v); /** * Tests if this vector is greater than an input vector. *

* This is a lane-wise binary test operation which applies the primitive greater than * operation ({@code >}) to each lane. * * @param v the input vector * @return the mask result of testing if this vector is greater than the * input vector */ public abstract VectorMask greaterThan(Vector v); /** * Tests if this vector is greater than or equal to an input vector. *

* This is a lane-wise binary test operation which applies the primitive greater than * or equal to operation ({@code >=}) to each lane. * * @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 greaterThanEq(Vector v); // Elemental shifting /** * Rotates left the lane elements of this vector by the given number of * lanes, {@code i}, modulus the vector length. *

* This is a cross-lane operation that permutes the lane elements of this * vector. * For each lane of the input vector, at lane index {@code N}, the lane * element is placed into the result vector at lane index * {@code (N + i) % length()}. * * @param i the number of lanes to rotate left * @return the result of rotating left lane elements of this vector by the * given number of lanes * @throws IllegalArgumentException if {@code i} is {@code < 0}. */ public abstract Vector rotateLanesLeft(int i); /** * Rotates right the lane elements of this vector by the given number of * lanes, {@code i}, modulus the vector length. *

* This is a cross-lane operation that permutes the lane elements of this * vector. * For each lane of the input vector, at lane index {@code N}, the lane * element is placed into the result vector at lane index * {@code (N + length() - (i % length())) % length()} * * @param i the number of lanes to rotate right * @return the result of rotating right lane elements of this vector by the * given number of lanes * @throws IllegalArgumentException if {@code i} is {@code < 0}. */ public abstract Vector rotateLanesRight(int i); /** * Shift left the lane elements of this vector by the given number of * lanes, {@code i}, modulus the vector length. *

* This is a cross-lane operation that permutes the lane elements of this * vector and behaves as if rotating left the lane elements by {@code i}, * and then the zero value is placed into the result vector at lane indexes * less than {@code i % length()}. * * @param i the number of lanes to shift left * @return the result of shifting left lane elements of this vector by the * given number of lanes * @throws IllegalArgumentException if {@code i} is {@code < 0}. */ public abstract Vector shiftLanesLeft(int i); /** * Shift right the lane elements of this vector by the given number of * lanes, {@code i}, modulus the vector length. *

* This is a cross-lane operation that permutes the lane elements of this * vector and behaves as if rotating right the lane elements by {@code i}, * and then the zero value is placed into the result vector at lane indexes * greater or equal to {@code length() - (i % length())}. * * @param i the number of lanes to shift right * @return the result of shifting right lane elements of this vector by the * given number of lanes * @throws IllegalArgumentException if {@code i} is {@code < 0}. */ public abstract Vector shiftLanesRight(int i); /** * Blends the lane elements of this vector with those of an input vector, * selecting lanes controlled by a mask. *

* For each lane of the mask, at lane index {@code N}, if the mask lane * is set then the lane element at {@code N} from the input vector is * selected and placed into the resulting vector at {@code N}, * otherwise the lane element at {@code N} from this vector is * selected and placed into the resulting vector at {@code N}. * * @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 blend(Vector v, VectorMask m); /** * Rearranges the lane elements of this vector selecting lane indexes * controlled by a shuffle. *

* This is a cross-lane operation that rearranges the lane elements of this * vector. * For each lane of the shuffle, at lane index {@code N} with lane * element {@code I}, the lane element at {@code I} from this vector is * selected and placed into the resulting vector at {@code N}. * * @param s the shuffle controlling lane index selection * @return the rearrangement of the lane elements of this vector */ public abstract Vector rearrange(VectorShuffle s); /** * Rearranges the lane elements of this vector and those of an input vector, * selecting lane indexes controlled by shuffles and a mask. *

* This is a cross-lane operation that rearranges the lane elements of this * vector and the input vector. This method behaves as if it rearranges * each vector with the corresponding shuffle and then blends the two * results with the mask: *

{@code
     * return this.rearrange(s1).blend(v.rearrange(s2), m);
     * }
* * @param v the input vector * @param s the shuffle controlling lane index selection of the input vector * if corresponding mask lanes are set, otherwise controlling lane * index selection of this vector * @param m the mask controlling shuffled lane selection * @return the rearrangement of lane elements of this vector and * those of an input vector */ public abstract Vector rearrange(Vector v, VectorShuffle s, VectorMask m); // Conversions /** * Converts this vector into a shuffle, creating a shuffle from vector * lane elements cast to {@code int} then logically AND'ed with the * shuffle length minus one. *

* This methods behaves as if it returns the result of creating a shuffle * given an array of the vector lane elements, as follows: *

{@code
     * $type$[] a = this.toArray();
     * int[] sa = new int[a.length];
     * for (int i = 0; i < a.length; i++) {
     *     sa[i] = (int) a[i];
     * }
     * return this.species().shuffleFromValues(sa);
     * }
* * @return a shuffle representation of this vector */ public abstract VectorShuffle toShuffle(); // Bitwise preserving /** * Transforms this vector to a vector of the given species of element type {@code F}. *

* The underlying bits of this vector are copied to the resulting * vector without modification, but those bits, before copying, may be * truncated if the this vector's bit size is greater than desired vector's bit * size, or appended to with zero bits if this vector's bit size is less * than desired vector's bit size. *

* The method behaves as if this vector is stored into a byte buffer * and then the desired vector is loaded from the byte buffer using * native byte ordering. The implication is that ByteBuffer reads bytes * and then composes them based on the byte ordering so the result * depends on this composition. *

* For example, on a system with ByteOrder.LITTLE_ENDIAN, loading from * byte array with values {0,1,2,3} and reshaping to int, leads to bytes * being composed in order 0x3 0x2 0x1 0x0 which is decimal value 50462976. * On a system with ByteOrder.BIG_ENDIAN, the value is instead 66051 because * bytes are composed in order 0x0 0x1 0x2 0x3. *

* The following pseudocode expresses the behavior: *

{@code
     * int bufferLen = Math.max(this.bitSize(), s.bitSize()) / Byte.SIZE;
     * ByteBuffer bb = ByteBuffer.allocate(bufferLen).order(ByteOrder.nativeOrder());
     * this.intoByteBuffer(bb, 0);
     * return $type$Vector.fromByteBuffer(s, bb, 0);
     * }
* * @param s species of desired vector * @param the boxed element type of the species * @return a vector transformed, by shape and element type, from this vector * @see Vector#reshape(VectorSpecies) * @see Vector#cast(VectorSpecies) */ public abstract Vector reinterpret(VectorSpecies s); @ForceInline @SuppressWarnings("unchecked") Vector defaultReinterpret(VectorSpecies 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(); if (stype == byte.class) { return (Vector) ByteVector.fromByteBuffer((ByteVector.ByteSpecies)s, bb, 0); } else if (stype == short.class) { return (Vector) ShortVector.fromByteBuffer((ShortVector.ShortSpecies)s, bb, 0); } else if (stype == int.class) { return (Vector) IntVector.fromByteBuffer((IntVector.IntSpecies)s, bb, 0); } else if (stype == long.class) { return (Vector) LongVector.fromByteBuffer((LongVector.LongSpecies)s, bb, 0); } else if (stype == float.class) { return (Vector) FloatVector.fromByteBuffer((FloatVector.FloatSpecies)s, bb, 0); } else if (stype == double.class) { return (Vector) DoubleVector.fromByteBuffer((DoubleVector.DoubleSpecies)s, bb, 0); } else { throw new UnsupportedOperationException("Bad lane type for reinterpret."); } } /** * Transforms this vector to a vector of same element type but different shape identified by species. *

* The lane elements of this vector are copied without * modification to the resulting vector, but those lane elements, before * copying, may be truncated if this vector's length is greater than the desired * vector's length, or appended to with default element values if this * vector's length is less than desired vector's length. *

* The method behaves as if this vector is stored into a byte array * and then the returned vector is loaded from the byte array. * The following pseudocode expresses the behavior: *

{@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);
     * }
* * @param s species of the desired vector * @return a vector transformed, by shape, from this vector * @see Vector#reinterpret(VectorSpecies) * @see Vector#cast(VectorSpecies) */ public abstract Vector reshape(VectorSpecies s); // Cast /** * Converts this vector to a vector of the given species element type {@code F}. *

* For each vector lane up to the length of this vector or * desired vector, which ever is the minimum, and where {@code N} is the * vector lane index, the element at index {@code N} of primitive type * {@code E} is converted, according to primitive conversion rules * specified by the Java Language Specification, to a value of primitive * type {@code F} and placed into the resulting vector at lane index * {@code N}. If desired vector's length is greater than this * vector's length then the default primitive value is placed into * subsequent lanes of the resulting vector. * * @param s species of the desired vector * @param the boxed element type of the species * @return a vector converted by shape and element type from this vector * @see Vector#reshape(VectorSpecies) * @see Vector#reinterpret(VectorSpecies) */ public abstract Vector cast(VectorSpecies s); //Array stores /** * Stores this vector into a byte array starting at an offset. *

* Bytes are extracted from primitive lane elements according to the * native byte order of the underlying platform. *

* This method behaves as it calls the * byte buffer, offset, and mask accepting * {@link #intoByteBuffer(ByteBuffer, int, VectorMask) method} as follows: *

{@code
     * return this.intoByteBuffer(ByteBuffer.wrap(a), i, this.maskAllTrue());
     * }
* * @param a the byte array * @param i the offset into the array * @return a vector loaded from a byte array * @throws IndexOutOfBoundsException if {@code i < 0} or * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)} */ public abstract void intoByteArray(byte[] a, int i); /** * Stores this vector into a byte array starting at an offset and using a mask. *

* Bytes are extracted from primitive lane elements according to the * native byte order of the underlying platform. *

* This method behaves as it calls the * byte buffer, offset, and mask accepting * {@link #intoByteBuffer(ByteBuffer, int, VectorMask) method} as follows: *

{@code
     * return this.intoByteBuffer(ByteBuffer.wrap(a), i, m);
     * }
* * @param a the byte array * @param i the offset into the array * @param m the mask controlling lane selection * @throws IndexOutOfBoundsException if the offset is {@code < 0}, * 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 m); /** * Stores this vector into a {@link ByteBuffer byte buffer} starting at an * offset into the byte buffer. *

* Bytes are extracted from primitive lane elements according to the * native byte order of the underlying platform. *

* This method behaves as if it calls the byte buffer, offset, and mask * accepting * {@link #intoByteBuffer(ByteBuffer, int, VectorMask)} method} as follows: *

{@code
     *   this.intoByteBuffer(b, i, this.maskAllTrue())
     * }
* * @param b the byte buffer * @param i the offset into the byte buffer * @throws IndexOutOfBoundsException if the offset is {@code < 0}, * or {@code > b.limit()}, * or if there are fewer than * {@code this.length() * this.elementSize() / Byte.SIZE} bytes * remaining in the byte buffer from the given offset */ public abstract void intoByteBuffer(ByteBuffer b, int i); /** * Stores this vector into a {@link ByteBuffer byte buffer} starting at an * offset into the byte buffer and using a mask. *

* This method behaves as if the byte buffer is viewed as a primitive * {@link java.nio.Buffer buffer} for the primitive element type, * according to the native byte order of the underlying platform, and * the lane elements of this vector are put into the buffer if the * corresponding mask lane is set. * The following pseudocode expresses the behavior, where * {@coce EBuffer} is the primitive buffer type, {@code e} is the * primitive element type, and {@code EVector} is the primitive * vector type for this vector: *

{@code
     * EBuffer eb = b.duplicate().
     *     order(ByteOrder.nativeOrder()).position(i).
     *     asEBuffer();
     * e[] es = ((EVector)this).toArray();
     * for (int n = 0; n < t.length; n++) {
     *     if (m.isSet(n)) {
     *         eb.put(n, es[n]);
     *     }
     * }
     * }
* * @param b the byte buffer * @param i the offset into the byte buffer * @param m the mask * @throws IndexOutOfBoundsException if the offset is {@code < 0}, * 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 m); /** * Find bit size based on element type and number of elements. * * @param c the element type * @param numElem number of lanes in the vector * @return size in bits for vector */ public static int bitSizeForVectorLength(Class c, int numElem) { if (c == float.class) { return Float.SIZE * numElem; } else if (c == double.class) { return Double.SIZE * numElem; } else if (c == byte.class) { return Byte.SIZE * numElem; } else if (c == short.class) { return Short.SIZE * numElem; } else if (c == int.class) { return Integer.SIZE * numElem; } else if (c == long.class) { return Long.SIZE * numElem; } else { throw new IllegalArgumentException("Bad vector type: " + c.getName()); } } /** * Returns a mask of same species as {@code this} vector and where each lane is set or unset according to given * {@code boolean} values. *

* This method behaves as if it returns the result of calling the static {@link VectorMask#fromValues(VectorSpecies, boolean...) fromValues()} * method in VectorMask as follows: *

 {@code
     *     return VectorMask.fromValues(this.species(), bits);
     * } 
* * @param bits the given {@code boolean} values * @return a mask where each lane is set or unset according to the given {@code boolean} value * @throws IndexOutOfBoundsException if {@code bits.length < this.species().length()} * @see VectorMask#fromValues(VectorSpecies, boolean...) */ @ForceInline public final VectorMask maskFromValues(boolean... bits) { return VectorMask.fromValues(this.species(), bits); } /** * Loads a mask of same species as {@code this} vector from a {@code boolean} array starting at an offset. *

* This method behaves as if it returns the result of calling the static {@link VectorMask#fromArray(VectorSpecies, boolean[], int) fromArray()} * method in VectorMask as follows: *

 {@code
     *     return VectorMask.fromArray(this.species(), bits, offset);
     * } 
* * @param bits the {@code boolean} array * @param offset the offset into the array * @return the mask loaded from a {@code boolean} array * @throws IndexOutOfBoundsException if {@code offset < 0}, or * {@code offset > bits.length - species.length()} * @see VectorMask#fromArray(VectorSpecies, boolean[], int) */ @ForceInline public final VectorMask maskFromArray(boolean[] bits, int offset) { return VectorMask.fromArray(this.species(), bits, offset); } /** * Returns a mask of same species as {@code this} vector and where all lanes are set. * * @return a mask where all lanes are set * @see VectorMask#maskAllTrue(VectorSpecies) */ @ForceInline public final VectorMask maskAllTrue() { return VectorMask.maskAllTrue(this.species()); } /** * Returns a mask of same species as {@code this} vector and where all lanes are unset. * * @return a mask where all lanes are unset * @see VectorMask#maskAllFalse(VectorSpecies) */ @ForceInline public final VectorMask maskAllFalse() { return VectorMask.maskAllFalse(this.species()); } /** * Returns a shuffle of same species as {@code this} vector and where each lane element is set to a given * {@code int} value logically AND'ed by the species length minus one. *

* This method behaves as if it returns the result of calling the static {@link VectorShuffle#fromValues(VectorSpecies, int...) fromValues()} * method in VectorShuffle as follows: *

 {@code
     *     return VectorShuffle.fromValues(this.species(), ixs);
     * } 
* * @param ixs the given {@code int} values * @return a shuffle where each lane element is set to a given * {@code int} value * @throws IndexOutOfBoundsException if the number of int values is * {@code < this.species().length()} * @see AbstractShuffle#fromValues(VectorSpecies, int...) */ @ForceInline public final VectorShuffle shuffleFromValues(int... ixs) { return VectorShuffle.fromValues(this.species(), ixs); } /** * Loads a shuffle of same species as {@code this} vector from an {@code int} array starting at an offset. *

* This method behaves as if it returns the result of calling the static {@link VectorShuffle#fromArray(VectorSpecies, int[], int) fromArray()} * method in VectorShuffle as follows: *

 {@code
     *     return VectorShuffle.fromArray(this.species(), ixs, offset);
     * } 
* * @param ixs the {@code int} array * @param offset the offset into the array * @return a shuffle loaded from the {@code int} array * @throws IndexOutOfBoundsException if {@code offset < 0}, or * {@code offset > ixs.length - this.species().length()} * @see AbstractShuffle#fromArray(VectorSpecies, int[], int) */ @ForceInline public final VectorShuffle shuffleFromArray(int[] ixs, int offset) { return VectorShuffle.fromArray(this.species(), ixs, offset); } /** * Returns a shuffle of same species as {@code this} vector of mapped indexes where each lane element is * the result of applying a mapping function to the corresponding lane * index. *

* This method behaves as if it returns the result of calling the static {@link VectorShuffle#shuffle(VectorSpecies, IntUnaryOperator) shuffle()} * method in VectorShuffle as follows: *

 {@code
     *     return AbstractShuffle.shuffle(this.species(), f);
     * } 
* * @param f the lane index mapping function * @return a shuffle of mapped indexes * @see AbstractShuffle#shuffle(VectorSpecies, IntUnaryOperator) */ @ForceInline public final VectorShuffle shuffle(IntUnaryOperator f) { return AbstractShuffle.shuffle(this.species(), f); } /** * Returns a shuffle of same species as {@code this} vector and where each lane element is the value of its * corresponding lane index. *

* This method behaves as if it returns the result of calling the static {@link VectorShuffle#shuffleIota(VectorSpecies) shuffleIota()} * method in VectorShuffle as follows: *

 {@code
     *     return VectorShuffle.shuffleIota(this.species());
     * } 
* * @return a shuffle of lane indexes * @see AbstractShuffle#shuffleIota(VectorSpecies) */ @ForceInline public final VectorShuffle shuffleIota() { return VectorShuffle.shuffleIota(this.species()); } /** * Returns a shuffle of same species as {@code this} vector and with lane elements set to sequential {@code int} * values starting from {@code start} and looping around species length. *

* This method behaves as if it returns the result of calling the static {@link VectorShuffle#shuffleIota(VectorSpecies, int) shuffleIota()} * method in VectorShuffle as follows: *

 {@code
     *     return VectorShuffle.shuffleIota(this.species(), start);
     * } 
* * @param start starting value of sequence * @return a shuffle of lane indexes * @see AbstractShuffle#shuffleIota(VectorSpecies, int) */ @ForceInline public final VectorShuffle shuffleIota(int start) { return VectorShuffle.shuffleIota(this.species(), start); } /** * Returns a shuffle of same species as {@code this} vector and with lane elements set to sequential {@code int} * values starting from {@code start} and looping around species length. *

* This method behaves as if it returns the result of calling the static {@link VectorShuffle#shuffleOffset(VectorSpecies, int) shuffleOffset()} * method in VectorShuffle as follows: *

 {@code
     *     return VectorShuffle.shuffleOffset(this.species(), start);
     * } 
* * @param start starting value of sequence * @return a shuffle of lane indexes * @see AbstractShuffle#shuffleOffset(VectorSpecies, int) */ @ForceInline public final VectorShuffle shuffleOffset(int start) { return VectorShuffle.shuffleOffset(this.species(), start); } }