8266317: Vector API enhancements

Co-authored-by: Paul Sandoz <psandoz@openjdk.org>
Co-authored-by: Sandhya Viswanathan <sviswanathan@openjdk.org>
Reviewed-by: jbhateja, vlivanov
This commit is contained in:
Paul Sandoz 2021-06-03 15:16:58 +00:00
parent eb385c0de2
commit 5982cfc856
121 changed files with 9631 additions and 736 deletions

View file

@ -834,6 +834,14 @@ final class Byte128Vector extends ByteVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final
ByteVector fromBooleanArray0(boolean[] a, int offset) {
return super.fromBooleanArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -866,6 +866,14 @@ final class Byte256Vector extends ByteVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final
ByteVector fromBooleanArray0(boolean[] a, int offset) {
return super.fromBooleanArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -930,6 +930,14 @@ final class Byte512Vector extends ByteVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final
ByteVector fromBooleanArray0(boolean[] a, int offset) {
return super.fromBooleanArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -818,6 +818,14 @@ final class Byte64Vector extends ByteVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final
ByteVector fromBooleanArray0(boolean[] a, int offset) {
return super.fromBooleanArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -804,6 +804,14 @@ final class ByteMaxVector extends ByteVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final
ByteVector fromBooleanArray0(boolean[] a, int offset) {
return super.fromBooleanArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -379,20 +379,6 @@ public abstract class ByteVector extends AbstractVector<Byte> {
return maskFactory(bits);
}
/*package-private*/
@ForceInline
static boolean doBinTest(int cond, byte a, byte b) {
switch (cond) {
case BT_eq: return a == b;
case BT_ne: return a != b;
case BT_lt: return a < b;
case BT_le: return a <= b;
case BT_gt: return a > b;
case BT_ge: return a >= b;
}
throw new AssertionError(Integer.toHexString(cond));
}
/*package-private*/
@Override
abstract ByteSpecies vspecies();
@ -1767,17 +1753,20 @@ public abstract class ByteVector extends AbstractVector<Byte> {
}
@ForceInline
private static
boolean compareWithOp(int cond, byte a, byte b) {
switch (cond) {
case BT_eq: return a == b;
case BT_ne: return a != b;
case BT_lt: return a < b;
case BT_le: return a <= b;
case BT_gt: return a > b;
case BT_ge: return a >= b;
}
throw new AssertionError();
private static boolean compareWithOp(int cond, byte a, byte b) {
return switch (cond) {
case BT_eq -> a == b;
case BT_ne -> a != b;
case BT_lt -> a < b;
case BT_le -> a <= b;
case BT_gt -> a > b;
case BT_ge -> a >= b;
case BT_ult -> Byte.compareUnsigned(a, b) < 0;
case BT_ule -> Byte.compareUnsigned(a, b) <= 0;
case BT_ugt -> Byte.compareUnsigned(a, b) > 0;
case BT_uge -> Byte.compareUnsigned(a, b) >= 0;
default -> throw new AssertionError();
};
}
/**
@ -2835,6 +2824,165 @@ public abstract class ByteVector extends AbstractVector<Byte> {
return vsp.vOp(m, n -> a[offset + indexMap[mapOffset + n]]);
}
/**
* Loads a vector from an array of type {@code boolean[]}
* starting at an offset.
* For each vector lane, where {@code N} is the vector lane index, the
* array element at index {@code offset + N}
* is first converted to a {@code byte} value and then
* placed into the resulting vector at lane index {@code N}.
* <p>
* A {@code boolean} value is converted to a {@code byte} value by applying the
* expression {@code (byte) (b ? 1 : 0)}, where {@code b} is the {@code boolean} value.
*
* @param species species of desired vector
* @param a the array
* @param offset the offset into the array
* @return the vector loaded from an array
* @throws IndexOutOfBoundsException
* if {@code offset+N < 0} or {@code offset+N >= a.length}
* for any lane {@code N} in the vector
*/
@ForceInline
public static
ByteVector fromBooleanArray(VectorSpecies<Byte> species,
boolean[] a, int offset) {
offset = checkFromIndexSize(offset, species.length(), a.length);
ByteSpecies vsp = (ByteSpecies) species;
return vsp.dummyVector().fromBooleanArray0(a, offset);
}
/**
* Loads a vector from an array of type {@code boolean[]}
* starting at an offset and using a mask.
* Lanes where the mask is unset are filled with the default
* value of {@code byte} (zero).
* For each vector lane, where {@code N} is the vector lane index,
* if the mask lane at index {@code N} is set then the array element at
* index {@code offset + N}
* is first converted to a {@code byte} value and then
* 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}.
* <p>
* A {@code boolean} value is converted to a {@code byte} value by applying the
* expression {@code (byte) (b ? 1 : 0)}, where {@code b} is the {@code boolean} value.
*
* @param species species of desired vector
* @param a the array
* @param offset the offset into the array
* @param m the mask controlling lane selection
* @return the vector loaded from an array
* @throws IndexOutOfBoundsException
* if {@code offset+N < 0} or {@code offset+N >= a.length}
* for any lane {@code N} in the vector
* where the mask is set
*/
@ForceInline
public static
ByteVector fromBooleanArray(VectorSpecies<Byte> species,
boolean[] a, int offset,
VectorMask<Byte> m) {
ByteSpecies vsp = (ByteSpecies) species;
if (offset >= 0 && offset <= (a.length - species.length())) {
ByteVector zero = vsp.zero();
return zero.blend(zero.fromBooleanArray0(a, offset), m);
}
// FIXME: optimize
checkMaskFromIndexSize(offset, vsp, m, 1, a.length);
return vsp.vOp(m, i -> (byte) (a[offset + i] ? 1 : 0));
}
/**
* Gathers a new vector composed of elements from an array of type
* {@code boolean[]},
* using indexes obtained by adding a fixed {@code offset} to a
* series of secondary offsets from an <em>index map</em>.
* The index map is a contiguous sequence of {@code VLENGTH}
* elements in a second array of {@code int}s, starting at a given
* {@code mapOffset}.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* the lane is loaded from the expression
* {@code (byte) (a[f(N)] ? 1 : 0)}, where {@code f(N)} is the
* index mapping expression
* {@code offset + indexMap[mapOffset + N]]}.
*
* @param species species of desired vector
* @param a the array
* @param offset the offset into the array, may be negative if relative
* indexes in the index map compensate to produce a value within the
* array bounds
* @param indexMap the index map
* @param mapOffset the offset into the index map
* @return the vector loaded from the indexed elements of the array
* @throws IndexOutOfBoundsException
* if {@code mapOffset+N < 0}
* or if {@code mapOffset+N >= indexMap.length},
* or if {@code f(N)=offset+indexMap[mapOffset+N]}
* is an invalid index into {@code a},
* for any lane {@code N} in the vector
* @see ByteVector#toIntArray()
*/
@ForceInline
public static
ByteVector fromBooleanArray(VectorSpecies<Byte> species,
boolean[] a, int offset,
int[] indexMap, int mapOffset) {
// FIXME: optimize
ByteSpecies vsp = (ByteSpecies) species;
return vsp.vOp(n -> (byte) (a[offset + indexMap[mapOffset + n]] ? 1 : 0));
}
/**
* Gathers a new vector composed of elements from an array of type
* {@code boolean[]},
* under the control of a mask, and
* using indexes obtained by adding a fixed {@code offset} to a
* series of secondary offsets from an <em>index map</em>.
* The index map is a contiguous sequence of {@code VLENGTH}
* elements in a second array of {@code int}s, starting at a given
* {@code mapOffset}.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* if the lane is set in the mask,
* the lane is loaded from the expression
* {@code (byte) (a[f(N)] ? 1 : 0)}, where {@code f(N)} is the
* index mapping expression
* {@code offset + indexMap[mapOffset + N]]}.
* Unset lanes in the resulting vector are set to zero.
*
* @param species species of desired vector
* @param a the array
* @param offset the offset into the array, may be negative if relative
* indexes in the index map compensate to produce a value within the
* array bounds
* @param indexMap the index map
* @param mapOffset the offset into the index map
* @param m the mask controlling lane selection
* @return the vector loaded from the indexed elements of the array
* @throws IndexOutOfBoundsException
* if {@code mapOffset+N < 0}
* or if {@code mapOffset+N >= indexMap.length},
* or if {@code f(N)=offset+indexMap[mapOffset+N]}
* is an invalid index into {@code a},
* for any lane {@code N} in the vector
* where the mask is set
* @see ByteVector#toIntArray()
*/
@ForceInline
public static
ByteVector fromBooleanArray(VectorSpecies<Byte> species,
boolean[] a, int offset,
int[] indexMap, int mapOffset,
VectorMask<Byte> m) {
// FIXME: optimize
ByteSpecies vsp = (ByteSpecies) species;
return vsp.vOp(m, n -> (byte) (a[offset + indexMap[mapOffset + n]] ? 1 : 0));
}
/**
* Loads a vector from a {@linkplain ByteBuffer byte buffer}
* starting at an offset into the byte buffer.
@ -2961,7 +3109,7 @@ public abstract class ByteVector extends AbstractVector<Byte> {
}
/**
* Stores this vector into an array of {@code byte}
* Stores this vector into an array of type {@code byte[]}
* starting at offset and using a mask.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
@ -3077,6 +3225,174 @@ public abstract class ByteVector extends AbstractVector<Byte> {
});
}
/**
* Stores this vector into an array of type {@code boolean[]}
* starting at an offset.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* the lane element at index {@code N}
* is first converted to a {@code boolean} value and then
* stored into the array element {@code a[offset+N]}.
* <p>
* A {@code byte} value is converted to a {@code boolean} value by applying the
* expression {@code (b & 1) != 0} where {@code b} is the byte value.
*
* @param a the array
* @param offset the offset into the array
* @throws IndexOutOfBoundsException
* if {@code offset+N < 0} or {@code offset+N >= a.length}
* for any lane {@code N} in the vector
*/
@ForceInline
public final
void intoBooleanArray(boolean[] a, int offset) {
offset = checkFromIndexSize(offset, length(), a.length);
ByteSpecies vsp = vspecies();
ByteVector normalized = this.and((byte) 1);
VectorSupport.store(
vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
a, booleanArrayAddress(a, offset),
normalized,
a, offset,
(arr, off, v)
-> v.stOp(arr, off,
(arr_, off_, i, e) -> arr_[off_ + i] = (e & 1) != 0));
}
/**
* Stores this vector into an array of type {@code boolean[]}
* starting at offset and using a mask.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* the lane element at index {@code N}
* is first converted to a {@code boolean} value and then
* stored into the array element {@code a[offset+N]}.
* If the mask lane at {@code N} is unset then the corresponding
* array element {@code a[offset+N]} is left unchanged.
* <p>
* A {@code byte} value is converted to a {@code boolean} value by applying the
* expression {@code (b & 1) != 0} where {@code b} is the byte value.
* <p>
* Array range checking is done for lanes where the mask is set.
* Lanes where the mask is unset are not stored and do not need
* to correspond to legitimate elements of {@code a}.
* That is, unset lanes may correspond to array indexes less than
* zero or beyond the end of the array.
*
* @param a the array
* @param offset the offset into the array
* @param m the mask controlling lane storage
* @throws IndexOutOfBoundsException
* if {@code offset+N < 0} or {@code offset+N >= a.length}
* for any lane {@code N} in the vector
* where the mask is set
*/
@ForceInline
public final
void intoBooleanArray(boolean[] a, int offset,
VectorMask<Byte> m) {
if (m.allTrue()) {
intoBooleanArray(a, offset);
} else {
// FIXME: optimize
ByteSpecies vsp = vspecies();
checkMaskFromIndexSize(offset, vsp, m, 1, a.length);
stOp(a, offset, m, (arr, off, i, e) -> arr[off+i] = (e & 1) != 0);
}
}
/**
* Scatters this vector into an array of type {@code boolean[]}
* using indexes obtained by adding a fixed {@code offset} to a
* series of secondary offsets from an <em>index map</em>.
* The index map is a contiguous sequence of {@code VLENGTH}
* elements in a second array of {@code int}s, starting at a given
* {@code mapOffset}.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* the lane element at index {@code N}
* is first converted to a {@code boolean} value and then
* stored into the array
* element {@code a[f(N)]}, where {@code f(N)} is the
* index mapping expression
* {@code offset + indexMap[mapOffset + N]]}.
* <p>
* A {@code byte} value is converted to a {@code boolean} value by applying the
* expression {@code (b & 1) != 0} where {@code b} is the byte value.
*
* @param a the array
* @param offset an offset to combine with the index map offsets
* @param indexMap the index map
* @param mapOffset the offset into the index map
* @throws IndexOutOfBoundsException
* if {@code mapOffset+N < 0}
* or if {@code mapOffset+N >= indexMap.length},
* or if {@code f(N)=offset+indexMap[mapOffset+N]}
* is an invalid index into {@code a},
* for any lane {@code N} in the vector
* @see ByteVector#toIntArray()
*/
@ForceInline
public final
void intoBooleanArray(boolean[] a, int offset,
int[] indexMap, int mapOffset) {
// FIXME: optimize
stOp(a, offset,
(arr, off, i, e) -> {
int j = indexMap[mapOffset + i];
arr[off + j] = (e & 1) != 0;
});
}
/**
* Scatters this vector into an array of type {@code boolean[]},
* under the control of a mask, and
* using indexes obtained by adding a fixed {@code offset} to a
* series of secondary offsets from an <em>index map</em>.
* The index map is a contiguous sequence of {@code VLENGTH}
* elements in a second array of {@code int}s, starting at a given
* {@code mapOffset}.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* if the mask lane at index {@code N} is set then
* the lane element at index {@code N}
* is first converted to a {@code boolean} value and then
* stored into the array
* element {@code a[f(N)]}, where {@code f(N)} is the
* index mapping expression
* {@code offset + indexMap[mapOffset + N]]}.
* <p>
* A {@code byte} value is converted to a {@code boolean} value by applying the
* expression {@code (b & 1) != 0} where {@code b} is the byte value.
*
* @param a the array
* @param offset an offset to combine with the index map offsets
* @param indexMap the index map
* @param mapOffset the offset into the index map
* @param m the mask
* @throws IndexOutOfBoundsException
* if {@code mapOffset+N < 0}
* or if {@code mapOffset+N >= indexMap.length},
* or if {@code f(N)=offset+indexMap[mapOffset+N]}
* is an invalid index into {@code a},
* for any lane {@code N} in the vector
* where the mask is set
* @see ByteVector#toIntArray()
*/
@ForceInline
public final
void intoBooleanArray(boolean[] a, int offset,
int[] indexMap, int mapOffset,
VectorMask<Byte> m) {
// FIXME: optimize
stOp(a, offset, m,
(arr, off, i, e) -> {
int j = indexMap[mapOffset + i];
arr[off + j] = (e & 1) != 0;
});
}
/**
* {@inheritDoc} <!--workaround-->
*/
@ -3183,6 +3499,22 @@ public abstract class ByteVector extends AbstractVector<Byte> {
(arr_, off_, i) -> arr_[off_ + i]));
}
/*package-private*/
abstract
ByteVector fromBooleanArray0(boolean[] a, int offset);
@ForceInline
final
ByteVector fromBooleanArray0Template(boolean[] a, int offset) {
ByteSpecies vsp = vspecies();
return VectorSupport.load(
vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
a, booleanArrayAddress(a, offset),
a, offset, vsp,
(arr, off, s) -> s.ldOp(arr, off,
(arr_, off_, i) -> (byte) (arr_[off_ + i] ? 1 : 0)));
}
@Override
abstract
ByteVector fromByteArray0(byte[] a, int offset);
@ -3313,6 +3645,17 @@ public abstract class ByteVector extends AbstractVector<Byte> {
return ARRAY_BASE + (((long)index) << ARRAY_SHIFT);
}
static final int ARRAY_BOOLEAN_SHIFT =
31 - Integer.numberOfLeadingZeros(Unsafe.ARRAY_BOOLEAN_INDEX_SCALE);
static final long ARRAY_BOOLEAN_BASE =
Unsafe.ARRAY_BOOLEAN_BASE_OFFSET;
@ForceInline
static long booleanArrayAddress(boolean[] a, int index) {
return ARRAY_BOOLEAN_BASE + (((long)index) << ARRAY_BOOLEAN_SHIFT);
}
@ForceInline
static long byteArrayAddress(byte[] a, int index) {
return Unsafe.ARRAY_BYTE_BASE_OFFSET + index;

View file

@ -802,6 +802,8 @@ final class Double128Vector extends DoubleVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -806,6 +806,8 @@ final class Double256Vector extends DoubleVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -814,6 +814,8 @@ final class Double512Vector extends DoubleVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -800,6 +800,8 @@ final class Double64Vector extends DoubleVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -799,6 +799,8 @@ final class DoubleMaxVector extends DoubleVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -379,20 +379,6 @@ public abstract class DoubleVector extends AbstractVector<Double> {
return maskFactory(bits);
}
/*package-private*/
@ForceInline
static boolean doBinTest(int cond, double a, double b) {
switch (cond) {
case BT_eq: return a == b;
case BT_ne: return a != b;
case BT_lt: return a < b;
case BT_le: return a <= b;
case BT_gt: return a > b;
case BT_ge: return a >= b;
}
throw new AssertionError(Integer.toHexString(cond));
}
/*package-private*/
@Override
abstract DoubleSpecies vspecies();
@ -1680,17 +1666,16 @@ public abstract class DoubleVector extends AbstractVector<Double> {
}
@ForceInline
private static
boolean compareWithOp(int cond, double a, double b) {
switch (cond) {
case BT_eq: return a == b;
case BT_ne: return a != b;
case BT_lt: return a < b;
case BT_le: return a <= b;
case BT_gt: return a > b;
case BT_ge: return a >= b;
}
throw new AssertionError();
private static boolean compareWithOp(int cond, double a, double b) {
return switch (cond) {
case BT_eq -> a == b;
case BT_ne -> a != b;
case BT_lt -> a < b;
case BT_le -> a <= b;
case BT_gt -> a > b;
case BT_ge -> a >= b;
default -> throw new AssertionError();
};
}
/**
@ -2742,6 +2727,8 @@ public abstract class DoubleVector extends AbstractVector<Double> {
}
}
/**
* Loads a vector from a {@linkplain ByteBuffer byte buffer}
* starting at an offset into the byte buffer.
@ -2874,7 +2861,7 @@ public abstract class DoubleVector extends AbstractVector<Double> {
}
/**
* Stores this vector into an array of {@code double}
* Stores this vector into an array of type {@code double[]}
* starting at offset and using a mask.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
@ -3031,6 +3018,8 @@ public abstract class DoubleVector extends AbstractVector<Double> {
}
}
/**
* {@inheritDoc} <!--workaround-->
*/
@ -3137,6 +3126,8 @@ public abstract class DoubleVector extends AbstractVector<Double> {
(arr_, off_, i) -> arr_[off_ + i]));
}
@Override
abstract
DoubleVector fromByteArray0(byte[] a, int offset);
@ -3272,6 +3263,8 @@ public abstract class DoubleVector extends AbstractVector<Double> {
return ARRAY_BASE + (((long)index) << ARRAY_SHIFT);
}
@ForceInline
static long byteArrayAddress(byte[] a, int index) {
return Unsafe.ARRAY_BYTE_BASE_OFFSET + index;

View file

@ -806,6 +806,8 @@ final class Float128Vector extends FloatVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -814,6 +814,8 @@ final class Float256Vector extends FloatVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -830,6 +830,8 @@ final class Float512Vector extends FloatVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -802,6 +802,8 @@ final class Float64Vector extends FloatVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -799,6 +799,8 @@ final class FloatMaxVector extends FloatVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -379,20 +379,6 @@ public abstract class FloatVector extends AbstractVector<Float> {
return maskFactory(bits);
}
/*package-private*/
@ForceInline
static boolean doBinTest(int cond, float a, float b) {
switch (cond) {
case BT_eq: return a == b;
case BT_ne: return a != b;
case BT_lt: return a < b;
case BT_le: return a <= b;
case BT_gt: return a > b;
case BT_ge: return a >= b;
}
throw new AssertionError(Integer.toHexString(cond));
}
/*package-private*/
@Override
abstract FloatSpecies vspecies();
@ -1692,17 +1678,16 @@ public abstract class FloatVector extends AbstractVector<Float> {
}
@ForceInline
private static
boolean compareWithOp(int cond, float a, float b) {
switch (cond) {
case BT_eq: return a == b;
case BT_ne: return a != b;
case BT_lt: return a < b;
case BT_le: return a <= b;
case BT_gt: return a > b;
case BT_ge: return a >= b;
}
throw new AssertionError();
private static boolean compareWithOp(int cond, float a, float b) {
return switch (cond) {
case BT_eq -> a == b;
case BT_ne -> a != b;
case BT_lt -> a < b;
case BT_le -> a <= b;
case BT_gt -> a > b;
case BT_ge -> a >= b;
default -> throw new AssertionError();
};
}
/**
@ -2748,6 +2733,8 @@ public abstract class FloatVector extends AbstractVector<Float> {
}
}
/**
* Loads a vector from a {@linkplain ByteBuffer byte buffer}
* starting at an offset into the byte buffer.
@ -2880,7 +2867,7 @@ public abstract class FloatVector extends AbstractVector<Float> {
}
/**
* Stores this vector into an array of {@code float}
* Stores this vector into an array of type {@code float[]}
* starting at offset and using a mask.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
@ -3018,6 +3005,8 @@ public abstract class FloatVector extends AbstractVector<Float> {
}
}
/**
* {@inheritDoc} <!--workaround-->
*/
@ -3124,6 +3113,8 @@ public abstract class FloatVector extends AbstractVector<Float> {
(arr_, off_, i) -> arr_[off_ + i]));
}
@Override
abstract
FloatVector fromByteArray0(byte[] a, int offset);
@ -3259,6 +3250,8 @@ public abstract class FloatVector extends AbstractVector<Float> {
return ARRAY_BASE + (((long)index) << ARRAY_SHIFT);
}
@ForceInline
static long byteArrayAddress(byte[] a, int index) {
return Unsafe.ARRAY_BYTE_BASE_OFFSET + index;

View file

@ -810,6 +810,8 @@ final class Int128Vector extends IntVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -818,6 +818,8 @@ final class Int256Vector extends IntVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -834,6 +834,8 @@ final class Int512Vector extends IntVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -806,6 +806,8 @@ final class Int64Vector extends IntVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -815,6 +815,8 @@ final class IntMaxVector extends IntVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -379,20 +379,6 @@ public abstract class IntVector extends AbstractVector<Integer> {
return maskFactory(bits);
}
/*package-private*/
@ForceInline
static boolean doBinTest(int cond, int a, int b) {
switch (cond) {
case BT_eq: return a == b;
case BT_ne: return a != b;
case BT_lt: return a < b;
case BT_le: return a <= b;
case BT_gt: return a > b;
case BT_ge: return a >= b;
}
throw new AssertionError(Integer.toHexString(cond));
}
/*package-private*/
@Override
abstract IntSpecies vspecies();
@ -1766,17 +1752,20 @@ public abstract class IntVector extends AbstractVector<Integer> {
}
@ForceInline
private static
boolean compareWithOp(int cond, int a, int b) {
switch (cond) {
case BT_eq: return a == b;
case BT_ne: return a != b;
case BT_lt: return a < b;
case BT_le: return a <= b;
case BT_gt: return a > b;
case BT_ge: return a >= b;
}
throw new AssertionError();
private static boolean compareWithOp(int cond, int a, int b) {
return switch (cond) {
case BT_eq -> a == b;
case BT_ne -> a != b;
case BT_lt -> a < b;
case BT_le -> a <= b;
case BT_gt -> a > b;
case BT_ge -> a >= b;
case BT_ult -> Integer.compareUnsigned(a, b) < 0;
case BT_ule -> Integer.compareUnsigned(a, b) <= 0;
case BT_ugt -> Integer.compareUnsigned(a, b) > 0;
case BT_uge -> Integer.compareUnsigned(a, b) >= 0;
default -> throw new AssertionError();
};
}
/**
@ -2851,6 +2840,8 @@ public abstract class IntVector extends AbstractVector<Integer> {
}
}
/**
* Loads a vector from a {@linkplain ByteBuffer byte buffer}
* starting at an offset into the byte buffer.
@ -2983,7 +2974,7 @@ public abstract class IntVector extends AbstractVector<Integer> {
}
/**
* Stores this vector into an array of {@code int}
* Stores this vector into an array of type {@code int[]}
* starting at offset and using a mask.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
@ -3121,6 +3112,8 @@ public abstract class IntVector extends AbstractVector<Integer> {
}
}
/**
* {@inheritDoc} <!--workaround-->
*/
@ -3227,6 +3220,8 @@ public abstract class IntVector extends AbstractVector<Integer> {
(arr_, off_, i) -> arr_[off_ + i]));
}
@Override
abstract
IntVector fromByteArray0(byte[] a, int offset);
@ -3362,6 +3357,8 @@ public abstract class IntVector extends AbstractVector<Integer> {
return ARRAY_BASE + (((long)index) << ARRAY_SHIFT);
}
@ForceInline
static long byteArrayAddress(byte[] a, int index) {
return Unsafe.ARRAY_BYTE_BASE_OFFSET + index;

View file

@ -796,6 +796,8 @@ final class Long128Vector extends LongVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -800,6 +800,8 @@ final class Long256Vector extends LongVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -808,6 +808,8 @@ final class Long512Vector extends LongVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -794,6 +794,8 @@ final class Long64Vector extends LongVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -794,6 +794,8 @@ final class LongMaxVector extends LongVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -379,20 +379,6 @@ public abstract class LongVector extends AbstractVector<Long> {
return maskFactory(bits);
}
/*package-private*/
@ForceInline
static boolean doBinTest(int cond, long a, long b) {
switch (cond) {
case BT_eq: return a == b;
case BT_ne: return a != b;
case BT_lt: return a < b;
case BT_le: return a <= b;
case BT_gt: return a > b;
case BT_ge: return a >= b;
}
throw new AssertionError(Integer.toHexString(cond));
}
/*package-private*/
@Override
abstract LongSpecies vspecies();
@ -1684,17 +1670,20 @@ public abstract class LongVector extends AbstractVector<Long> {
}
@ForceInline
private static
boolean compareWithOp(int cond, long a, long b) {
switch (cond) {
case BT_eq: return a == b;
case BT_ne: return a != b;
case BT_lt: return a < b;
case BT_le: return a <= b;
case BT_gt: return a > b;
case BT_ge: return a >= b;
}
throw new AssertionError();
private static boolean compareWithOp(int cond, long a, long b) {
return switch (cond) {
case BT_eq -> a == b;
case BT_ne -> a != b;
case BT_lt -> a < b;
case BT_le -> a <= b;
case BT_gt -> a > b;
case BT_ge -> a >= b;
case BT_ult -> Long.compareUnsigned(a, b) < 0;
case BT_ule -> Long.compareUnsigned(a, b) <= 0;
case BT_ugt -> Long.compareUnsigned(a, b) > 0;
case BT_uge -> Long.compareUnsigned(a, b) >= 0;
default -> throw new AssertionError();
};
}
/**
@ -2735,6 +2724,8 @@ public abstract class LongVector extends AbstractVector<Long> {
}
}
/**
* Loads a vector from a {@linkplain ByteBuffer byte buffer}
* starting at an offset into the byte buffer.
@ -2867,7 +2858,7 @@ public abstract class LongVector extends AbstractVector<Long> {
}
/**
* Stores this vector into an array of {@code long}
* Stores this vector into an array of type {@code long[]}
* starting at offset and using a mask.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
@ -3024,6 +3015,8 @@ public abstract class LongVector extends AbstractVector<Long> {
}
}
/**
* {@inheritDoc} <!--workaround-->
*/
@ -3130,6 +3123,8 @@ public abstract class LongVector extends AbstractVector<Long> {
(arr_, off_, i) -> arr_[off_ + i]));
}
@Override
abstract
LongVector fromByteArray0(byte[] a, int offset);
@ -3265,6 +3260,8 @@ public abstract class LongVector extends AbstractVector<Long> {
return ARRAY_BASE + (((long)index) << ARRAY_SHIFT);
}
@ForceInline
static long byteArrayAddress(byte[] a, int index) {
return Unsafe.ARRAY_BYTE_BASE_OFFSET + index;

View file

@ -818,6 +818,14 @@ final class Short128Vector extends ShortVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final
ShortVector fromCharArray0(char[] a, int offset) {
return super.fromCharArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -834,6 +834,14 @@ final class Short256Vector extends ShortVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final
ShortVector fromCharArray0(char[] a, int offset) {
return super.fromCharArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -866,6 +866,14 @@ final class Short512Vector extends ShortVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final
ShortVector fromCharArray0(char[] a, int offset) {
return super.fromCharArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -810,6 +810,14 @@ final class Short64Vector extends ShortVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final
ShortVector fromCharArray0(char[] a, int offset) {
return super.fromCharArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -804,6 +804,14 @@ final class ShortMaxVector extends ShortVector {
return super.fromArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final
ShortVector fromCharArray0(char[] a, int offset) {
return super.fromCharArray0Template(a, offset); // specialize
}
@ForceInline
@Override
final

View file

@ -379,20 +379,6 @@ public abstract class ShortVector extends AbstractVector<Short> {
return maskFactory(bits);
}
/*package-private*/
@ForceInline
static boolean doBinTest(int cond, short a, short b) {
switch (cond) {
case BT_eq: return a == b;
case BT_ne: return a != b;
case BT_lt: return a < b;
case BT_le: return a <= b;
case BT_gt: return a > b;
case BT_ge: return a >= b;
}
throw new AssertionError(Integer.toHexString(cond));
}
/*package-private*/
@Override
abstract ShortSpecies vspecies();
@ -1767,17 +1753,20 @@ public abstract class ShortVector extends AbstractVector<Short> {
}
@ForceInline
private static
boolean compareWithOp(int cond, short a, short b) {
switch (cond) {
case BT_eq: return a == b;
case BT_ne: return a != b;
case BT_lt: return a < b;
case BT_le: return a <= b;
case BT_gt: return a > b;
case BT_ge: return a >= b;
}
throw new AssertionError();
private static boolean compareWithOp(int cond, short a, short b) {
return switch (cond) {
case BT_eq -> a == b;
case BT_ne -> a != b;
case BT_lt -> a < b;
case BT_le -> a <= b;
case BT_gt -> a > b;
case BT_ge -> a >= b;
case BT_ult -> Short.compareUnsigned(a, b) < 0;
case BT_ule -> Short.compareUnsigned(a, b) <= 0;
case BT_ugt -> Short.compareUnsigned(a, b) > 0;
case BT_uge -> Short.compareUnsigned(a, b) >= 0;
default -> throw new AssertionError();
};
}
/**
@ -2835,6 +2824,159 @@ public abstract class ShortVector extends AbstractVector<Short> {
return vsp.vOp(m, n -> a[offset + indexMap[mapOffset + n]]);
}
/**
* Loads a vector from an array of type {@code char[]}
* starting at an offset.
* For each vector lane, where {@code N} is the vector lane index, the
* array element at index {@code offset + N}
* is first cast to a {@code short} value and then
* placed into the resulting vector at lane index {@code N}.
*
* @param species species of desired vector
* @param a the array
* @param offset the offset into the array
* @return the vector loaded from an array
* @throws IndexOutOfBoundsException
* if {@code offset+N < 0} or {@code offset+N >= a.length}
* for any lane {@code N} in the vector
*/
@ForceInline
public static
ShortVector fromCharArray(VectorSpecies<Short> species,
char[] a, int offset) {
offset = checkFromIndexSize(offset, species.length(), a.length);
ShortSpecies vsp = (ShortSpecies) species;
return vsp.dummyVector().fromCharArray0(a, offset);
}
/**
* Loads a vector from an array of type {@code char[]}
* starting at an offset and using a mask.
* Lanes where the mask is unset are filled with the default
* value of {@code short} (zero).
* For each vector lane, where {@code N} is the vector lane index,
* if the mask lane at index {@code N} is set then the array element at
* index {@code offset + N}
* is first cast to a {@code short} value and then
* 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}.
*
* @param species species of desired vector
* @param a the array
* @param offset the offset into the array
* @param m the mask controlling lane selection
* @return the vector loaded from an array
* @throws IndexOutOfBoundsException
* if {@code offset+N < 0} or {@code offset+N >= a.length}
* for any lane {@code N} in the vector
* where the mask is set
*/
@ForceInline
public static
ShortVector fromCharArray(VectorSpecies<Short> species,
char[] a, int offset,
VectorMask<Short> m) {
ShortSpecies vsp = (ShortSpecies) species;
if (offset >= 0 && offset <= (a.length - species.length())) {
ShortVector zero = vsp.zero();
return zero.blend(zero.fromCharArray0(a, offset), m);
}
// FIXME: optimize
checkMaskFromIndexSize(offset, vsp, m, 1, a.length);
return vsp.vOp(m, i -> (short) a[offset + i]);
}
/**
* Gathers a new vector composed of elements from an array of type
* {@code char[]},
* using indexes obtained by adding a fixed {@code offset} to a
* series of secondary offsets from an <em>index map</em>.
* The index map is a contiguous sequence of {@code VLENGTH}
* elements in a second array of {@code int}s, starting at a given
* {@code mapOffset}.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* the lane is loaded from the expression
* {@code (short) a[f(N)]}, where {@code f(N)} is the
* index mapping expression
* {@code offset + indexMap[mapOffset + N]]}.
*
* @param species species of desired vector
* @param a the array
* @param offset the offset into the array, may be negative if relative
* indexes in the index map compensate to produce a value within the
* array bounds
* @param indexMap the index map
* @param mapOffset the offset into the index map
* @return the vector loaded from the indexed elements of the array
* @throws IndexOutOfBoundsException
* if {@code mapOffset+N < 0}
* or if {@code mapOffset+N >= indexMap.length},
* or if {@code f(N)=offset+indexMap[mapOffset+N]}
* is an invalid index into {@code a},
* for any lane {@code N} in the vector
* @see ShortVector#toIntArray()
*/
@ForceInline
public static
ShortVector fromCharArray(VectorSpecies<Short> species,
char[] a, int offset,
int[] indexMap, int mapOffset) {
// FIXME: optimize
ShortSpecies vsp = (ShortSpecies) species;
return vsp.vOp(n -> (short) a[offset + indexMap[mapOffset + n]]);
}
/**
* Gathers a new vector composed of elements from an array of type
* {@code char[]},
* under the control of a mask, and
* using indexes obtained by adding a fixed {@code offset} to a
* series of secondary offsets from an <em>index map</em>.
* The index map is a contiguous sequence of {@code VLENGTH}
* elements in a second array of {@code int}s, starting at a given
* {@code mapOffset}.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* if the lane is set in the mask,
* the lane is loaded from the expression
* {@code (short) a[f(N)]}, where {@code f(N)} is the
* index mapping expression
* {@code offset + indexMap[mapOffset + N]]}.
* Unset lanes in the resulting vector are set to zero.
*
* @param species species of desired vector
* @param a the array
* @param offset the offset into the array, may be negative if relative
* indexes in the index map compensate to produce a value within the
* array bounds
* @param indexMap the index map
* @param mapOffset the offset into the index map
* @param m the mask controlling lane selection
* @return the vector loaded from the indexed elements of the array
* @throws IndexOutOfBoundsException
* if {@code mapOffset+N < 0}
* or if {@code mapOffset+N >= indexMap.length},
* or if {@code f(N)=offset+indexMap[mapOffset+N]}
* is an invalid index into {@code a},
* for any lane {@code N} in the vector
* where the mask is set
* @see ShortVector#toIntArray()
*/
@ForceInline
public static
ShortVector fromCharArray(VectorSpecies<Short> species,
char[] a, int offset,
int[] indexMap, int mapOffset,
VectorMask<Short> m) {
// FIXME: optimize
ShortSpecies vsp = (ShortSpecies) species;
return vsp.vOp(m, n -> (short) a[offset + indexMap[mapOffset + n]]);
}
/**
* Loads a vector from a {@linkplain ByteBuffer byte buffer}
* starting at an offset into the byte buffer.
@ -2967,7 +3109,7 @@ public abstract class ShortVector extends AbstractVector<Short> {
}
/**
* Stores this vector into an array of {@code short}
* Stores this vector into an array of type {@code short[]}
* starting at offset and using a mask.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
@ -3083,6 +3225,161 @@ public abstract class ShortVector extends AbstractVector<Short> {
});
}
/**
* Stores this vector into an array of type {@code char[]}
* starting at an offset.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* the lane element at index {@code N}
* is first cast to a {@code char} value and then
* stored into the array element {@code a[offset+N]}.
*
* @param a the array, of type {@code char[]}
* @param offset the offset into the array
* @throws IndexOutOfBoundsException
* if {@code offset+N < 0} or {@code offset+N >= a.length}
* for any lane {@code N} in the vector
*/
@ForceInline
public final
void intoCharArray(char[] a, int offset) {
offset = checkFromIndexSize(offset, length(), a.length);
ShortSpecies vsp = vspecies();
VectorSupport.store(
vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
a, charArrayAddress(a, offset),
this,
a, offset,
(arr, off, v)
-> v.stOp(arr, off,
(arr_, off_, i, e) -> arr_[off_ + i] = (char) e));
}
/**
* Stores this vector into an array of type {@code char[]}
* starting at offset and using a mask.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* the lane element at index {@code N}
* is first cast to a {@code char} value and then
* stored into the array element {@code a[offset+N]}.
* If the mask lane at {@code N} is unset then the corresponding
* array element {@code a[offset+N]} is left unchanged.
* <p>
* Array range checking is done for lanes where the mask is set.
* Lanes where the mask is unset are not stored and do not need
* to correspond to legitimate elements of {@code a}.
* That is, unset lanes may correspond to array indexes less than
* zero or beyond the end of the array.
*
* @param a the array, of type {@code char[]}
* @param offset the offset into the array
* @param m the mask controlling lane storage
* @throws IndexOutOfBoundsException
* if {@code offset+N < 0} or {@code offset+N >= a.length}
* for any lane {@code N} in the vector
* where the mask is set
*/
@ForceInline
public final
void intoCharArray(char[] a, int offset,
VectorMask<Short> m) {
if (m.allTrue()) {
intoCharArray(a, offset);
} else {
// FIXME: optimize
ShortSpecies vsp = vspecies();
checkMaskFromIndexSize(offset, vsp, m, 1, a.length);
stOp(a, offset, m, (arr, off, i, v) -> arr[off+i] = (char) v);
}
}
/**
* Scatters this vector into an array of type {@code char[]}
* using indexes obtained by adding a fixed {@code offset} to a
* series of secondary offsets from an <em>index map</em>.
* The index map is a contiguous sequence of {@code VLENGTH}
* elements in a second array of {@code int}s, starting at a given
* {@code mapOffset}.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* the lane element at index {@code N}
* is first cast to a {@code char} value and then
* stored into the array
* element {@code a[f(N)]}, where {@code f(N)} is the
* index mapping expression
* {@code offset + indexMap[mapOffset + N]]}.
*
* @param a the array
* @param offset an offset to combine with the index map offsets
* @param indexMap the index map
* @param mapOffset the offset into the index map
* @throws IndexOutOfBoundsException
* if {@code mapOffset+N < 0}
* or if {@code mapOffset+N >= indexMap.length},
* or if {@code f(N)=offset+indexMap[mapOffset+N]}
* is an invalid index into {@code a},
* for any lane {@code N} in the vector
* @see ShortVector#toIntArray()
*/
@ForceInline
public final
void intoCharArray(char[] a, int offset,
int[] indexMap, int mapOffset) {
// FIXME: optimize
stOp(a, offset,
(arr, off, i, e) -> {
int j = indexMap[mapOffset + i];
arr[off + j] = (char) e;
});
}
/**
* Scatters this vector into an array of type {@code char[]},
* under the control of a mask, and
* using indexes obtained by adding a fixed {@code offset} to a
* series of secondary offsets from an <em>index map</em>.
* The index map is a contiguous sequence of {@code VLENGTH}
* elements in a second array of {@code int}s, starting at a given
* {@code mapOffset}.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* if the mask lane at index {@code N} is set then
* the lane element at index {@code N}
* is first cast to a {@code char} value and then
* stored into the array
* element {@code a[f(N)]}, where {@code f(N)} is the
* index mapping expression
* {@code offset + indexMap[mapOffset + N]]}.
*
* @param a the array
* @param offset an offset to combine with the index map offsets
* @param indexMap the index map
* @param mapOffset the offset into the index map
* @param m the mask
* @throws IndexOutOfBoundsException
* if {@code mapOffset+N < 0}
* or if {@code mapOffset+N >= indexMap.length},
* or if {@code f(N)=offset+indexMap[mapOffset+N]}
* is an invalid index into {@code a},
* for any lane {@code N} in the vector
* where the mask is set
* @see ShortVector#toIntArray()
*/
@ForceInline
public final
void intoCharArray(char[] a, int offset,
int[] indexMap, int mapOffset,
VectorMask<Short> m) {
// FIXME: optimize
stOp(a, offset, m,
(arr, off, i, e) -> {
int j = indexMap[mapOffset + i];
arr[off + j] = (char) e;
});
}
/**
* {@inheritDoc} <!--workaround-->
*/
@ -3189,6 +3486,22 @@ public abstract class ShortVector extends AbstractVector<Short> {
(arr_, off_, i) -> arr_[off_ + i]));
}
/*package-private*/
abstract
ShortVector fromCharArray0(char[] a, int offset);
@ForceInline
final
ShortVector fromCharArray0Template(char[] a, int offset) {
ShortSpecies vsp = vspecies();
return VectorSupport.load(
vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
a, charArrayAddress(a, offset),
a, offset, vsp,
(arr, off, s) -> s.ldOp(arr, off,
(arr_, off_, i) -> (short) arr_[off_ + i]));
}
@Override
abstract
ShortVector fromByteArray0(byte[] a, int offset);
@ -3324,6 +3637,17 @@ public abstract class ShortVector extends AbstractVector<Short> {
return ARRAY_BASE + (((long)index) << ARRAY_SHIFT);
}
static final int ARRAY_CHAR_SHIFT =
31 - Integer.numberOfLeadingZeros(Unsafe.ARRAY_CHAR_INDEX_SCALE);
static final long ARRAY_CHAR_BASE =
Unsafe.ARRAY_CHAR_BASE_OFFSET;
@ForceInline
static long charArrayAddress(char[] a, int index) {
return ARRAY_CHAR_BASE + (((long)index) << ARRAY_CHAR_SHIFT);
}
@ForceInline
static long byteArrayAddress(byte[] a, int index) {
return Unsafe.ARRAY_BYTE_BASE_OFFSET + index;

View file

@ -240,13 +240,13 @@ import java.util.Arrays;
* each distinct lane of the input vector. If there are additional
* vector arguments of the same type, their lanes are aligned with the
* lanes of the first input vector. (They must all have a common
* {@code VLENGTH}.) The output resulting from a lane-wise operation
* will have a {@code VLENGTH} which is equal to the {@code VLENGTH}
* of the input(s) to the operation. Thus, lane-wise operations are
* <em>length-invariant</em>, in their basic definitions.
* {@code VLENGTH}.) For most lane-wise operations, the output resulting
* from a lane-wise operation will have a {@code VLENGTH} which is equal to
* the {@code VLENGTH} of the input(s) to the operation. Thus, such lane-wise
* operations are <em>length-invariant</em>, in their basic definitions.
*
* <p> The principle of length-invariance is combined with another
* basic principle, that lane-wise operations are always
* basic principle, that most length-invariant lane-wise operations are also
* <em>shape-invariant</em>, meaning that the inputs and the output of
* a lane-wise operation will have a common {@code VSHAPE}. When the
* principles conflict, because a logical result (with an invariant
@ -799,7 +799,8 @@ import java.util.Arrays;
* approach to the design of such <em>resizing</em> vector operations.
*
* <p> As a basic principle, lane-wise operations are
* <em>length-invariant</em>. Length-invariance simply means that
* <em>length-invariant</em>, unless clearly marked otherwise.
* Length-invariance simply means that
* if {@code VLENGTH} lanes go into an operation, the same number
* of lanes come out, with nothing discarded and no extra padding.
*

View file

@ -565,7 +565,26 @@ public abstract class VectorOperators {
public static final Comparison GT = compare("GT", ">", VectorSupport.BT_gt, VO_ALL);
/** Compare {@code a>=b}. */
public static final Comparison GE = compare("GE", ">=", VectorSupport.BT_ge, VO_ALL);
// FIXME: add unsigned comparisons
/** Unsigned compare {@code a<b}. Integral only.
* @see java.lang.Integer#compareUnsigned
* @see java.lang.Long#compareUnsigned
*/
public static final Comparison UNSIGNED_LT = compare("UNSIGNED_LT", "<", VectorSupport.BT_ult, VO_NOFP);
/** Unsigned compare {@code a<=b}. Integral only.
* @see java.lang.Integer#compareUnsigned
* @see java.lang.Long#compareUnsigned
*/
public static final Comparison UNSIGNED_LE = compare("UNSIGNED_LE", "<=", VectorSupport.BT_ule, VO_NOFP);
/** Unsigned compare {@code a>b}. Integral only.
* @see java.lang.Integer#compareUnsigned
* @see java.lang.Long#compareUnsigned
*/
public static final Comparison UNSIGNED_GT = compare("UNSIGNED_GT", ">", VectorSupport.BT_ugt, VO_NOFP);
/** Unsigned compare {@code a>=b}. Integral only.
* @see java.lang.Integer#compareUnsigned
* @see java.lang.Long#compareUnsigned
*/
public static final Comparison UNSIGNED_GE = compare("UNSIGNED_GE", ">=", VectorSupport.BT_uge, VO_NOFP);
// Conversion operators

View file

@ -383,20 +383,6 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> {
return maskFactory(bits);
}
/*package-private*/
@ForceInline
static boolean doBinTest(int cond, $type$ a, $type$ b) {
switch (cond) {
case BT_eq: return a == b;
case BT_ne: return a != b;
case BT_lt: return a < b;
case BT_le: return a <= b;
case BT_gt: return a > b;
case BT_ge: return a >= b;
}
throw new AssertionError(Integer.toHexString(cond));
}
/*package-private*/
@Override
abstract $Type$Species vspecies();
@ -2032,17 +2018,22 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> {
}
@ForceInline
private static
boolean compareWithOp(int cond, $type$ a, $type$ b) {
switch (cond) {
case BT_eq: return a == b;
case BT_ne: return a != b;
case BT_lt: return a < b;
case BT_le: return a <= b;
case BT_gt: return a > b;
case BT_ge: return a >= b;
}
throw new AssertionError();
private static boolean compareWithOp(int cond, $type$ a, $type$ b) {
return switch (cond) {
case BT_eq -> a == b;
case BT_ne -> a != b;
case BT_lt -> a < b;
case BT_le -> a <= b;
case BT_gt -> a > b;
case BT_ge -> a >= b;
#if[!FP]
case BT_ult -> $Boxtype$.compareUnsigned(a, b) < 0;
case BT_ule -> $Boxtype$.compareUnsigned(a, b) <= 0;
case BT_ugt -> $Boxtype$.compareUnsigned(a, b) > 0;
case BT_uge -> $Boxtype$.compareUnsigned(a, b) >= 0;
#end[!FP]
default -> throw new AssertionError();
};
}
/**
@ -3375,6 +3366,320 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> {
}
#end[byteOrShort]
#if[short]
/**
* Loads a vector from an array of type {@code char[]}
* starting at an offset.
* For each vector lane, where {@code N} is the vector lane index, the
* array element at index {@code offset + N}
* is first cast to a {@code short} value and then
* placed into the resulting vector at lane index {@code N}.
*
* @param species species of desired vector
* @param a the array
* @param offset the offset into the array
* @return the vector loaded from an array
* @throws IndexOutOfBoundsException
* if {@code offset+N < 0} or {@code offset+N >= a.length}
* for any lane {@code N} in the vector
*/
@ForceInline
public static
$abstractvectortype$ fromCharArray(VectorSpecies<$Boxtype$> species,
char[] a, int offset) {
offset = checkFromIndexSize(offset, species.length(), a.length);
$Type$Species vsp = ($Type$Species) species;
return vsp.dummyVector().fromCharArray0(a, offset);
}
/**
* Loads a vector from an array of type {@code char[]}
* starting at an offset and using a mask.
* Lanes where the mask is unset are filled with the default
* value of {@code $type$} ({#if[FP]?positive }zero).
* For each vector lane, where {@code N} is the vector lane index,
* if the mask lane at index {@code N} is set then the array element at
* index {@code offset + N}
* is first cast to a {@code short} value and then
* 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}.
*
* @param species species of desired vector
* @param a the array
* @param offset the offset into the array
* @param m the mask controlling lane selection
* @return the vector loaded from an array
* @throws IndexOutOfBoundsException
* if {@code offset+N < 0} or {@code offset+N >= a.length}
* for any lane {@code N} in the vector
* where the mask is set
*/
@ForceInline
public static
$abstractvectortype$ fromCharArray(VectorSpecies<$Boxtype$> species,
char[] a, int offset,
VectorMask<$Boxtype$> m) {
$Type$Species vsp = ($Type$Species) species;
if (offset >= 0 && offset <= (a.length - species.length())) {
$abstractvectortype$ zero = vsp.zero();
return zero.blend(zero.fromCharArray0(a, offset), m);
}
// FIXME: optimize
checkMaskFromIndexSize(offset, vsp, m, 1, a.length);
return vsp.vOp(m, i -> (short) a[offset + i]);
}
/**
* Gathers a new vector composed of elements from an array of type
* {@code char[]},
* using indexes obtained by adding a fixed {@code offset} to a
* series of secondary offsets from an <em>index map</em>.
* The index map is a contiguous sequence of {@code VLENGTH}
* elements in a second array of {@code int}s, starting at a given
* {@code mapOffset}.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* the lane is loaded from the expression
* {@code (short) a[f(N)]}, where {@code f(N)} is the
* index mapping expression
* {@code offset + indexMap[mapOffset + N]]}.
*
* @param species species of desired vector
* @param a the array
* @param offset the offset into the array, may be negative if relative
* indexes in the index map compensate to produce a value within the
* array bounds
* @param indexMap the index map
* @param mapOffset the offset into the index map
* @return the vector loaded from the indexed elements of the array
* @throws IndexOutOfBoundsException
* if {@code mapOffset+N < 0}
* or if {@code mapOffset+N >= indexMap.length},
* or if {@code f(N)=offset+indexMap[mapOffset+N]}
* is an invalid index into {@code a},
* for any lane {@code N} in the vector
* @see $abstractvectortype$#toIntArray()
*/
@ForceInline
public static
$abstractvectortype$ fromCharArray(VectorSpecies<$Boxtype$> species,
char[] a, int offset,
int[] indexMap, int mapOffset) {
// FIXME: optimize
$Type$Species vsp = ($Type$Species) species;
return vsp.vOp(n -> (short) a[offset + indexMap[mapOffset + n]]);
}
/**
* Gathers a new vector composed of elements from an array of type
* {@code char[]},
* under the control of a mask, and
* using indexes obtained by adding a fixed {@code offset} to a
* series of secondary offsets from an <em>index map</em>.
* The index map is a contiguous sequence of {@code VLENGTH}
* elements in a second array of {@code int}s, starting at a given
* {@code mapOffset}.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* if the lane is set in the mask,
* the lane is loaded from the expression
* {@code (short) a[f(N)]}, where {@code f(N)} is the
* index mapping expression
* {@code offset + indexMap[mapOffset + N]]}.
* Unset lanes in the resulting vector are set to zero.
*
* @param species species of desired vector
* @param a the array
* @param offset the offset into the array, may be negative if relative
* indexes in the index map compensate to produce a value within the
* array bounds
* @param indexMap the index map
* @param mapOffset the offset into the index map
* @param m the mask controlling lane selection
* @return the vector loaded from the indexed elements of the array
* @throws IndexOutOfBoundsException
* if {@code mapOffset+N < 0}
* or if {@code mapOffset+N >= indexMap.length},
* or if {@code f(N)=offset+indexMap[mapOffset+N]}
* is an invalid index into {@code a},
* for any lane {@code N} in the vector
* where the mask is set
* @see $abstractvectortype$#toIntArray()
*/
@ForceInline
public static
$abstractvectortype$ fromCharArray(VectorSpecies<$Boxtype$> species,
char[] a, int offset,
int[] indexMap, int mapOffset,
VectorMask<$Boxtype$> m) {
// FIXME: optimize
$Type$Species vsp = ($Type$Species) species;
return vsp.vOp(m, n -> (short) a[offset + indexMap[mapOffset + n]]);
}
#end[short]
#if[byte]
/**
* Loads a vector from an array of type {@code boolean[]}
* starting at an offset.
* For each vector lane, where {@code N} is the vector lane index, the
* array element at index {@code offset + N}
* is first converted to a {@code byte} value and then
* placed into the resulting vector at lane index {@code N}.
* <p>
* A {@code boolean} value is converted to a {@code byte} value by applying the
* expression {@code (byte) (b ? 1 : 0)}, where {@code b} is the {@code boolean} value.
*
* @param species species of desired vector
* @param a the array
* @param offset the offset into the array
* @return the vector loaded from an array
* @throws IndexOutOfBoundsException
* if {@code offset+N < 0} or {@code offset+N >= a.length}
* for any lane {@code N} in the vector
*/
@ForceInline
public static
$abstractvectortype$ fromBooleanArray(VectorSpecies<$Boxtype$> species,
boolean[] a, int offset) {
offset = checkFromIndexSize(offset, species.length(), a.length);
$Type$Species vsp = ($Type$Species) species;
return vsp.dummyVector().fromBooleanArray0(a, offset);
}
/**
* Loads a vector from an array of type {@code boolean[]}
* starting at an offset and using a mask.
* Lanes where the mask is unset are filled with the default
* value of {@code $type$} ({#if[FP]?positive }zero).
* For each vector lane, where {@code N} is the vector lane index,
* if the mask lane at index {@code N} is set then the array element at
* index {@code offset + N}
* is first converted to a {@code byte} value and then
* 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}.
* <p>
* A {@code boolean} value is converted to a {@code byte} value by applying the
* expression {@code (byte) (b ? 1 : 0)}, where {@code b} is the {@code boolean} value.
*
* @param species species of desired vector
* @param a the array
* @param offset the offset into the array
* @param m the mask controlling lane selection
* @return the vector loaded from an array
* @throws IndexOutOfBoundsException
* if {@code offset+N < 0} or {@code offset+N >= a.length}
* for any lane {@code N} in the vector
* where the mask is set
*/
@ForceInline
public static
$abstractvectortype$ fromBooleanArray(VectorSpecies<$Boxtype$> species,
boolean[] a, int offset,
VectorMask<$Boxtype$> m) {
$Type$Species vsp = ($Type$Species) species;
if (offset >= 0 && offset <= (a.length - species.length())) {
$abstractvectortype$ zero = vsp.zero();
return zero.blend(zero.fromBooleanArray0(a, offset), m);
}
// FIXME: optimize
checkMaskFromIndexSize(offset, vsp, m, 1, a.length);
return vsp.vOp(m, i -> (byte) (a[offset + i] ? 1 : 0));
}
/**
* Gathers a new vector composed of elements from an array of type
* {@code boolean[]},
* using indexes obtained by adding a fixed {@code offset} to a
* series of secondary offsets from an <em>index map</em>.
* The index map is a contiguous sequence of {@code VLENGTH}
* elements in a second array of {@code int}s, starting at a given
* {@code mapOffset}.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* the lane is loaded from the expression
* {@code (byte) (a[f(N)] ? 1 : 0)}, where {@code f(N)} is the
* index mapping expression
* {@code offset + indexMap[mapOffset + N]]}.
*
* @param species species of desired vector
* @param a the array
* @param offset the offset into the array, may be negative if relative
* indexes in the index map compensate to produce a value within the
* array bounds
* @param indexMap the index map
* @param mapOffset the offset into the index map
* @return the vector loaded from the indexed elements of the array
* @throws IndexOutOfBoundsException
* if {@code mapOffset+N < 0}
* or if {@code mapOffset+N >= indexMap.length},
* or if {@code f(N)=offset+indexMap[mapOffset+N]}
* is an invalid index into {@code a},
* for any lane {@code N} in the vector
* @see $abstractvectortype$#toIntArray()
*/
@ForceInline
public static
$abstractvectortype$ fromBooleanArray(VectorSpecies<$Boxtype$> species,
boolean[] a, int offset,
int[] indexMap, int mapOffset) {
// FIXME: optimize
$Type$Species vsp = ($Type$Species) species;
return vsp.vOp(n -> (byte) (a[offset + indexMap[mapOffset + n]] ? 1 : 0));
}
/**
* Gathers a new vector composed of elements from an array of type
* {@code boolean[]},
* under the control of a mask, and
* using indexes obtained by adding a fixed {@code offset} to a
* series of secondary offsets from an <em>index map</em>.
* The index map is a contiguous sequence of {@code VLENGTH}
* elements in a second array of {@code int}s, starting at a given
* {@code mapOffset}.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* if the lane is set in the mask,
* the lane is loaded from the expression
* {@code (byte) (a[f(N)] ? 1 : 0)}, where {@code f(N)} is the
* index mapping expression
* {@code offset + indexMap[mapOffset + N]]}.
* Unset lanes in the resulting vector are set to zero.
*
* @param species species of desired vector
* @param a the array
* @param offset the offset into the array, may be negative if relative
* indexes in the index map compensate to produce a value within the
* array bounds
* @param indexMap the index map
* @param mapOffset the offset into the index map
* @param m the mask controlling lane selection
* @return the vector loaded from the indexed elements of the array
* @throws IndexOutOfBoundsException
* if {@code mapOffset+N < 0}
* or if {@code mapOffset+N >= indexMap.length},
* or if {@code f(N)=offset+indexMap[mapOffset+N]}
* is an invalid index into {@code a},
* for any lane {@code N} in the vector
* where the mask is set
* @see $abstractvectortype$#toIntArray()
*/
@ForceInline
public static
$abstractvectortype$ fromBooleanArray(VectorSpecies<$Boxtype$> species,
boolean[] a, int offset,
int[] indexMap, int mapOffset,
VectorMask<$Boxtype$> m) {
// FIXME: optimize
$Type$Species vsp = ($Type$Species) species;
return vsp.vOp(m, n -> (byte) (a[offset + indexMap[mapOffset + n]] ? 1 : 0));
}
#end[byte]
/**
* Loads a vector from a {@linkplain ByteBuffer byte buffer}
* starting at an offset into the byte buffer.
@ -3513,7 +3818,7 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> {
}
/**
* Stores this vector into an array of {@code $type$}
* Stores this vector into an array of type {@code $type$[]}
* starting at offset and using a mask.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
@ -3704,6 +4009,331 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> {
}
#end[byteOrShort]
#if[short]
/**
* Stores this vector into an array of type {@code char[]}
* starting at an offset.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* the lane element at index {@code N}
* is first cast to a {@code char} value and then
* stored into the array element {@code a[offset+N]}.
*
* @param a the array, of type {@code char[]}
* @param offset the offset into the array
* @throws IndexOutOfBoundsException
* if {@code offset+N < 0} or {@code offset+N >= a.length}
* for any lane {@code N} in the vector
*/
@ForceInline
public final
void intoCharArray(char[] a, int offset) {
offset = checkFromIndexSize(offset, length(), a.length);
$Type$Species vsp = vspecies();
VectorSupport.store(
vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
a, charArrayAddress(a, offset),
this,
a, offset,
(arr, off, v)
-> v.stOp(arr, off,
(arr_, off_, i, e) -> arr_[off_ + i] = (char) e));
}
/**
* Stores this vector into an array of type {@code char[]}
* starting at offset and using a mask.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* the lane element at index {@code N}
* is first cast to a {@code char} value and then
* stored into the array element {@code a[offset+N]}.
* If the mask lane at {@code N} is unset then the corresponding
* array element {@code a[offset+N]} is left unchanged.
* <p>
* Array range checking is done for lanes where the mask is set.
* Lanes where the mask is unset are not stored and do not need
* to correspond to legitimate elements of {@code a}.
* That is, unset lanes may correspond to array indexes less than
* zero or beyond the end of the array.
*
* @param a the array, of type {@code char[]}
* @param offset the offset into the array
* @param m the mask controlling lane storage
* @throws IndexOutOfBoundsException
* if {@code offset+N < 0} or {@code offset+N >= a.length}
* for any lane {@code N} in the vector
* where the mask is set
*/
@ForceInline
public final
void intoCharArray(char[] a, int offset,
VectorMask<$Boxtype$> m) {
if (m.allTrue()) {
intoCharArray(a, offset);
} else {
// FIXME: optimize
$Type$Species vsp = vspecies();
checkMaskFromIndexSize(offset, vsp, m, 1, a.length);
stOp(a, offset, m, (arr, off, i, v) -> arr[off+i] = (char) v);
}
}
/**
* Scatters this vector into an array of type {@code char[]}
* using indexes obtained by adding a fixed {@code offset} to a
* series of secondary offsets from an <em>index map</em>.
* The index map is a contiguous sequence of {@code VLENGTH}
* elements in a second array of {@code int}s, starting at a given
* {@code mapOffset}.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* the lane element at index {@code N}
* is first cast to a {@code char} value and then
* stored into the array
* element {@code a[f(N)]}, where {@code f(N)} is the
* index mapping expression
* {@code offset + indexMap[mapOffset + N]]}.
*
* @param a the array
* @param offset an offset to combine with the index map offsets
* @param indexMap the index map
* @param mapOffset the offset into the index map
* @throws IndexOutOfBoundsException
* if {@code mapOffset+N < 0}
* or if {@code mapOffset+N >= indexMap.length},
* or if {@code f(N)=offset+indexMap[mapOffset+N]}
* is an invalid index into {@code a},
* for any lane {@code N} in the vector
* @see $abstractvectortype$#toIntArray()
*/
@ForceInline
public final
void intoCharArray(char[] a, int offset,
int[] indexMap, int mapOffset) {
// FIXME: optimize
stOp(a, offset,
(arr, off, i, e) -> {
int j = indexMap[mapOffset + i];
arr[off + j] = (char) e;
});
}
/**
* Scatters this vector into an array of type {@code char[]},
* under the control of a mask, and
* using indexes obtained by adding a fixed {@code offset} to a
* series of secondary offsets from an <em>index map</em>.
* The index map is a contiguous sequence of {@code VLENGTH}
* elements in a second array of {@code int}s, starting at a given
* {@code mapOffset}.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* if the mask lane at index {@code N} is set then
* the lane element at index {@code N}
* is first cast to a {@code char} value and then
* stored into the array
* element {@code a[f(N)]}, where {@code f(N)} is the
* index mapping expression
* {@code offset + indexMap[mapOffset + N]]}.
*
* @param a the array
* @param offset an offset to combine with the index map offsets
* @param indexMap the index map
* @param mapOffset the offset into the index map
* @param m the mask
* @throws IndexOutOfBoundsException
* if {@code mapOffset+N < 0}
* or if {@code mapOffset+N >= indexMap.length},
* or if {@code f(N)=offset+indexMap[mapOffset+N]}
* is an invalid index into {@code a},
* for any lane {@code N} in the vector
* where the mask is set
* @see $abstractvectortype$#toIntArray()
*/
@ForceInline
public final
void intoCharArray(char[] a, int offset,
int[] indexMap, int mapOffset,
VectorMask<$Boxtype$> m) {
// FIXME: optimize
stOp(a, offset, m,
(arr, off, i, e) -> {
int j = indexMap[mapOffset + i];
arr[off + j] = (char) e;
});
}
#end[short]
#if[byte]
/**
* Stores this vector into an array of type {@code boolean[]}
* starting at an offset.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* the lane element at index {@code N}
* is first converted to a {@code boolean} value and then
* stored into the array element {@code a[offset+N]}.
* <p>
* A {@code byte} value is converted to a {@code boolean} value by applying the
* expression {@code (b & 1) != 0} where {@code b} is the byte value.
*
* @param a the array
* @param offset the offset into the array
* @throws IndexOutOfBoundsException
* if {@code offset+N < 0} or {@code offset+N >= a.length}
* for any lane {@code N} in the vector
*/
@ForceInline
public final
void intoBooleanArray(boolean[] a, int offset) {
offset = checkFromIndexSize(offset, length(), a.length);
$Type$Species vsp = vspecies();
ByteVector normalized = this.and((byte) 1);
VectorSupport.store(
vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
a, booleanArrayAddress(a, offset),
normalized,
a, offset,
(arr, off, v)
-> v.stOp(arr, off,
(arr_, off_, i, e) -> arr_[off_ + i] = (e & 1) != 0));
}
/**
* Stores this vector into an array of type {@code boolean[]}
* starting at offset and using a mask.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* the lane element at index {@code N}
* is first converted to a {@code boolean} value and then
* stored into the array element {@code a[offset+N]}.
* If the mask lane at {@code N} is unset then the corresponding
* array element {@code a[offset+N]} is left unchanged.
* <p>
* A {@code byte} value is converted to a {@code boolean} value by applying the
* expression {@code (b & 1) != 0} where {@code b} is the byte value.
* <p>
* Array range checking is done for lanes where the mask is set.
* Lanes where the mask is unset are not stored and do not need
* to correspond to legitimate elements of {@code a}.
* That is, unset lanes may correspond to array indexes less than
* zero or beyond the end of the array.
*
* @param a the array
* @param offset the offset into the array
* @param m the mask controlling lane storage
* @throws IndexOutOfBoundsException
* if {@code offset+N < 0} or {@code offset+N >= a.length}
* for any lane {@code N} in the vector
* where the mask is set
*/
@ForceInline
public final
void intoBooleanArray(boolean[] a, int offset,
VectorMask<$Boxtype$> m) {
if (m.allTrue()) {
intoBooleanArray(a, offset);
} else {
// FIXME: optimize
$Type$Species vsp = vspecies();
checkMaskFromIndexSize(offset, vsp, m, 1, a.length);
stOp(a, offset, m, (arr, off, i, e) -> arr[off+i] = (e & 1) != 0);
}
}
/**
* Scatters this vector into an array of type {@code boolean[]}
* using indexes obtained by adding a fixed {@code offset} to a
* series of secondary offsets from an <em>index map</em>.
* The index map is a contiguous sequence of {@code VLENGTH}
* elements in a second array of {@code int}s, starting at a given
* {@code mapOffset}.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* the lane element at index {@code N}
* is first converted to a {@code boolean} value and then
* stored into the array
* element {@code a[f(N)]}, where {@code f(N)} is the
* index mapping expression
* {@code offset + indexMap[mapOffset + N]]}.
* <p>
* A {@code byte} value is converted to a {@code boolean} value by applying the
* expression {@code (b & 1) != 0} where {@code b} is the byte value.
*
* @param a the array
* @param offset an offset to combine with the index map offsets
* @param indexMap the index map
* @param mapOffset the offset into the index map
* @throws IndexOutOfBoundsException
* if {@code mapOffset+N < 0}
* or if {@code mapOffset+N >= indexMap.length},
* or if {@code f(N)=offset+indexMap[mapOffset+N]}
* is an invalid index into {@code a},
* for any lane {@code N} in the vector
* @see $abstractvectortype$#toIntArray()
*/
@ForceInline
public final
void intoBooleanArray(boolean[] a, int offset,
int[] indexMap, int mapOffset) {
// FIXME: optimize
stOp(a, offset,
(arr, off, i, e) -> {
int j = indexMap[mapOffset + i];
arr[off + j] = (e & 1) != 0;
});
}
/**
* Scatters this vector into an array of type {@code boolean[]},
* under the control of a mask, and
* using indexes obtained by adding a fixed {@code offset} to a
* series of secondary offsets from an <em>index map</em>.
* The index map is a contiguous sequence of {@code VLENGTH}
* elements in a second array of {@code int}s, starting at a given
* {@code mapOffset}.
* <p>
* For each vector lane, where {@code N} is the vector lane index,
* if the mask lane at index {@code N} is set then
* the lane element at index {@code N}
* is first converted to a {@code boolean} value and then
* stored into the array
* element {@code a[f(N)]}, where {@code f(N)} is the
* index mapping expression
* {@code offset + indexMap[mapOffset + N]]}.
* <p>
* A {@code byte} value is converted to a {@code boolean} value by applying the
* expression {@code (b & 1) != 0} where {@code b} is the byte value.
*
* @param a the array
* @param offset an offset to combine with the index map offsets
* @param indexMap the index map
* @param mapOffset the offset into the index map
* @param m the mask
* @throws IndexOutOfBoundsException
* if {@code mapOffset+N < 0}
* or if {@code mapOffset+N >= indexMap.length},
* or if {@code f(N)=offset+indexMap[mapOffset+N]}
* is an invalid index into {@code a},
* for any lane {@code N} in the vector
* where the mask is set
* @see $abstractvectortype$#toIntArray()
*/
@ForceInline
public final
void intoBooleanArray(boolean[] a, int offset,
int[] indexMap, int mapOffset,
VectorMask<$Boxtype$> m) {
// FIXME: optimize
stOp(a, offset, m,
(arr, off, i, e) -> {
int j = indexMap[mapOffset + i];
arr[off + j] = (e & 1) != 0;
});
}
#end[byte]
/**
* {@inheritDoc} <!--workaround-->
*/
@ -3810,6 +4440,40 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> {
(arr_, off_, i) -> arr_[off_ + i]));
}
#if[short]
/*package-private*/
abstract
$abstractvectortype$ fromCharArray0(char[] a, int offset);
@ForceInline
final
$abstractvectortype$ fromCharArray0Template(char[] a, int offset) {
$Type$Species vsp = vspecies();
return VectorSupport.load(
vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
a, charArrayAddress(a, offset),
a, offset, vsp,
(arr, off, s) -> s.ldOp(arr, off,
(arr_, off_, i) -> (short) arr_[off_ + i]));
}
#end[short]
#if[byte]
/*package-private*/
abstract
$abstractvectortype$ fromBooleanArray0(boolean[] a, int offset);
@ForceInline
final
$abstractvectortype$ fromBooleanArray0Template(boolean[] a, int offset) {
$Type$Species vsp = vspecies();
return VectorSupport.load(
vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
a, booleanArrayAddress(a, offset),
a, offset, vsp,
(arr, off, s) -> s.ldOp(arr, off,
(arr_, off_, i) -> (byte) (arr_[off_ + i] ? 1 : 0)));
}
#end[byte]
@Override
abstract
$abstractvectortype$ fromByteArray0(byte[] a, int offset);
@ -3947,6 +4611,30 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> {
return ARRAY_BASE + (((long)index) << ARRAY_SHIFT);
}
#if[short]
static final int ARRAY_CHAR_SHIFT =
31 - Integer.numberOfLeadingZeros(Unsafe.ARRAY_CHAR_INDEX_SCALE);
static final long ARRAY_CHAR_BASE =
Unsafe.ARRAY_CHAR_BASE_OFFSET;
@ForceInline
static long charArrayAddress(char[] a, int index) {
return ARRAY_CHAR_BASE + (((long)index) << ARRAY_CHAR_SHIFT);
}
#end[short]
#if[byte]
static final int ARRAY_BOOLEAN_SHIFT =
31 - Integer.numberOfLeadingZeros(Unsafe.ARRAY_BOOLEAN_INDEX_SCALE);
static final long ARRAY_BOOLEAN_BASE =
Unsafe.ARRAY_BOOLEAN_BASE_OFFSET;
@ForceInline
static long booleanArrayAddress(boolean[] a, int index) {
return ARRAY_BOOLEAN_BASE + (((long)index) << ARRAY_BOOLEAN_SHIFT);
}
#end[byte]
@ForceInline
static long byteArrayAddress(byte[] a, int index) {
return Unsafe.ARRAY_BYTE_BASE_OFFSET + index;

View file

@ -1092,6 +1092,24 @@ final class $vectortype$ extends $abstractvectortype$ {
return super.fromArray0Template(a, offset); // specialize
}
#if[short]
@ForceInline
@Override
final
$abstractvectortype$ fromCharArray0(char[] a, int offset) {
return super.fromCharArray0Template(a, offset); // specialize
}
#end[short]
#if[byte]
@ForceInline
@Override
final
$abstractvectortype$ fromBooleanArray0(boolean[] a, int offset) {
return super.fromBooleanArray0Template(a, offset); // specialize
}
#end[byte]
@ForceInline
@Override
final