package jdk.incubator.vector;
import jdk.internal.vm.annotation.ForceInline;
import jdk.internal.vm.annotation.Stable;
import static jdk.internal.vm.vector.VectorSupport.*;
import static jdk.incubator.vector.VectorIntrinsics.*;
enum LaneType {
FLOAT(float.class, Float.class, float[].class, 'F', 24, Float.SIZE, T_FLOAT),
DOUBLE(double.class, Double.class, double[].class, 'F', 53, Double.SIZE, T_DOUBLE),
BYTE(byte.class, Byte.class, byte[].class, 'I', -1, Byte.SIZE, T_BYTE),
SHORT(short.class, Short.class, short[].class, 'I', -1, Short.SIZE, T_SHORT),
INT(int.class, Integer.class, int[].class, 'I', -1, Integer.SIZE, T_INT),
LONG(long.class, Long.class, long[].class, 'I', -1, Long.SIZE, T_LONG);
LaneType(Class<?> elementType,
Class<?> genericElementType,
Class<?> arrayType,
char elementKind,
int elementPrecision,
int elementSize,
int basicType) {
if (elementPrecision <= 0)
elementPrecision += elementSize;
this.elementType = elementType;
this.genericElementType = genericElementType;
this.arrayType = arrayType;
this.elementKind = elementKind;
this.elementPrecision = elementPrecision;
this.elementSize = elementSize;
this.elementSizeLog2 = Integer.numberOfTrailingZeros(elementSize);
assert(elementSize == (1 << elementSizeLog2));
this.switchKey = 1+ordinal();
this.printName = elementType.getSimpleName();
this.typeChar = printName.toUpperCase().charAt(0);
assert("FDBSIL".indexOf(typeChar) == ordinal()) : this;
this.basicType = basicType;
assert(basicType ==
( (elementSizeLog2 - 3)
| (elementKind == 'F' ? 4 : 8))) : this;
assert("....zcFDBSILoav..".charAt(basicType) == typeChar);
}
final Class<?> elementType;
final Class<?> arrayType;
final Class<?> genericElementType;
final int elementSize;
final int elementSizeLog2;
final int elementPrecision;
final char elementKind;
final int switchKey;
final String printName;
final char typeChar;
final int basicType;
private @Stable LaneType asIntegral;
private @Stable LaneType asFloating;
@Override
public String toString() {
return printName;
}
LaneType asIntegral() {
return asIntegral.check();
}
LaneType asFloating() {
if (asFloating == null) {
throw badElementType(elementType, "either int or long, to reinterpret as float or double");
}
return asFloating;
}
@ForceInline
static LaneType of(Class<?> elementType) {
int c0 = elementType.getName().charAt(0);
LaneType type = ENUM_FROM_C0[c0 & C0_MASK];
if (type != null && type.elementType == elementType) {
return type;
}
return ofSlow(elementType);
}
private static LaneType ofSlow(Class<?> elementType) {
for (LaneType type : ENUM_VALUES) {
if (type.elementType == elementType) {
return type;
}
}
throw badElementType(elementType, "a primitive type such as byte.class with a known bit-size");
}
static LaneType forClassOrNull(Class<?> queryType) {
for (LaneType type : ENUM_VALUES) {
if (type.genericElementType == queryType) {
return type;
}
if (type.elementType == queryType) {
return type;
}
if (type.arrayType == queryType) {
return type;
}
}
return null;
}
LaneType check(Class<?> expectedType) {
if (expectedType == this.elementType)
return this;
throw badElementType(this.elementType, expectedType);
}
private static
RuntimeException badElementType(Class<?> elementType, Object expected) {
String msg = String.format("Bad vector element type: %s (should be %s)",
elementType, expected);
if (expected instanceof Class) {
return new ClassCastException(msg);
} else {
return new UnsupportedOperationException(msg);
}
}
static final int
SK_FLOAT = 1,
SK_DOUBLE = 2,
SK_BYTE = 3,
SK_SHORT = 4,
SK_INT = 5,
SK_LONG = 6,
SK_LIMIT = 7;
@ForceInline
static LaneType ofSwitchKey(int sk) {
return ENUM_FROM_SK[sk].check();
}
@ForceInline
static LaneType ofBasicType(int bt) {
return ENUM_FROM_BT[bt].check();
}
@ForceInline final LaneType check() { return this; }
@Stable private static final LaneType[] ENUM_VALUES;
@Stable private static final LaneType[] ENUM_FROM_SK;
@Stable private static final LaneType[] ENUM_FROM_C0;
@Stable private static final LaneType[] ENUM_FROM_BT;
private static final int C0_MASK = 0x0F, BT_MASK = 0x0F;
static {
LaneType[] values = values().clone();
LaneType[] valuesByKey = new LaneType[1+values.length];
LaneType[] valuesByC0 = new LaneType[C0_MASK+1];
LaneType[] valuesByBT = new LaneType[BT_MASK+1];
for (int ord = 0; ord < values.length; ord++) {
int key = 1+ord;
LaneType value = values[ord];
valuesByKey[key] = value;
try {
assert(LaneType.class
.getDeclaredField("SK_"+value.name())
.get(null).equals(key));
} catch (ReflectiveOperationException ex) {
throw new AssertionError(ex);
}
int c0 = value.elementType.getName().charAt(0);
c0 &= C0_MASK;
assert(valuesByC0[c0] == null);
valuesByC0[c0] = value;
assert(valuesByBT[value.basicType] == null);
valuesByBT[value.basicType] = value;
if (value.elementKind == 'I') {
value.asIntegral = value;
} else {
for (LaneType v : values) {
if (v.elementKind == 'I' &&
v.elementSize == value.elementSize) {
value.asIntegral = v;
break;
}
}
}
if (value.elementKind == 'F') {
value.asFloating = value;
} else {
for (LaneType v : values) {
if (v.elementKind == 'F' &&
v.elementSize == value.elementSize) {
value.asFloating = v;
break;
}
}
}
}
for (LaneType lt : values) {
if (lt.elementKind == 'I') {
assert(lt.asIntegral == lt);
if (lt.asFloating == null) {
assert(lt.elementSize < Float.SIZE);
} else {
assert(lt.asFloating.elementKind == 'F' &&
lt.asFloating.elementSize == lt.elementSize);
}
} else {
assert(lt.elementKind == 'F');
assert(lt.asFloating == lt);
assert(lt.asIntegral.elementKind == 'I' &&
lt.asIntegral.elementSize == lt.elementSize);
}
}
ENUM_VALUES = values;
ENUM_FROM_SK = valuesByKey;
ENUM_FROM_C0 = valuesByC0;
ENUM_FROM_BT = valuesByBT;
}
static {
assert(ofBasicType(T_FLOAT) == FLOAT);
assert(ofBasicType(T_DOUBLE) == DOUBLE);
assert(ofBasicType(T_BYTE) == BYTE);
assert(ofBasicType(T_SHORT) == SHORT);
assert(ofBasicType(T_INT) == INT);
assert(ofBasicType(T_LONG) == LONG);
}
}