mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-02 07:10:23 +00:00
8386255: Float16Vector NaN canonicalization for hashCode computation
Reviewed-by: psandoz, sherman
This commit is contained in:
parent
a34314dd79
commit
8740fbb4ee
@ -2861,6 +2861,17 @@ public abstract sealed class Float16Vector extends AbstractVector<Float16>
|
||||
return a;
|
||||
}
|
||||
|
||||
// Returns the lane values boxed as Float16 elements.
|
||||
@ForceInline
|
||||
final Float16[] toFloat16Array() {
|
||||
short[] bits = vec();
|
||||
Float16[] a = new Float16[bits.length];
|
||||
for (int i = 0; i < bits.length; i++) {
|
||||
a[i] = Float16.shortBitsToFloat16(bits[i]);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} <!--workaround-->
|
||||
*/
|
||||
@ForceInline
|
||||
@ -3734,8 +3745,9 @@ public abstract sealed class Float16Vector extends AbstractVector<Float16>
|
||||
@ForceInline
|
||||
public final
|
||||
int hashCode() {
|
||||
// now that toArray is strongly typed, we can define this
|
||||
return Objects.hash(species(), Arrays.hashCode(toArray()));
|
||||
// Hash the lanes as Float16 values; Float16.hashCode canonicalizes NaN
|
||||
// so that all NaN representations contribute the same hash code.
|
||||
return Objects.hash(species(), Arrays.hashCode(toFloat16Array()));
|
||||
}
|
||||
|
||||
// ================================================
|
||||
|
||||
@ -3705,6 +3705,19 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp
|
||||
return a;
|
||||
}
|
||||
|
||||
#if[FP16]
|
||||
// Returns the lane values boxed as Float16 elements.
|
||||
@ForceInline
|
||||
final Float16[] toFloat16Array() {
|
||||
short[] bits = vec();
|
||||
Float16[] a = new Float16[bits.length];
|
||||
for (int i = 0; i < bits.length; i++) {
|
||||
a[i] = Float16.shortBitsToFloat16(bits[i]);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
#end[FP16]
|
||||
#if[int]
|
||||
/**
|
||||
* {@inheritDoc} <!--workaround-->
|
||||
@ -5749,8 +5762,14 @@ public abstract sealed class $abstractvectortype$ extends AbstractVector<$Boxtyp
|
||||
@ForceInline
|
||||
public final
|
||||
int hashCode() {
|
||||
#if[FP16]
|
||||
// Hash the lanes as Float16 values; Float16.hashCode canonicalizes NaN
|
||||
// so that all NaN representations contribute the same hash code.
|
||||
return Objects.hash(species(), Arrays.hashCode(toFloat16Array()));
|
||||
#else[FP16]
|
||||
// now that toArray is strongly typed, we can define this
|
||||
return Objects.hash(species(), Arrays.hashCode(toArray()));
|
||||
#end[FP16]
|
||||
}
|
||||
|
||||
// ================================================
|
||||
|
||||
@ -1561,14 +1561,16 @@ public class Float16Vector128Tests extends AbstractVectorTest {
|
||||
}
|
||||
|
||||
static short cornerCaseValue(int i) {
|
||||
return switch(i % 8) {
|
||||
return switch(i % 10) {
|
||||
case 0 -> float16ToRawShortBits(Float16.MAX_VALUE);
|
||||
case 1 -> float16ToRawShortBits(Float16.MIN_VALUE);
|
||||
case 2 -> float16ToRawShortBits(Float16.NEGATIVE_INFINITY);
|
||||
case 3 -> float16ToRawShortBits(Float16.POSITIVE_INFINITY);
|
||||
case 4 -> float16ToRawShortBits(Float16.NaN);
|
||||
case 5 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7FFA));
|
||||
case 6 -> float16ToShortBits(Float16.valueOf(0.0f));
|
||||
case 6 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7c01)); // signaling NaN
|
||||
case 7 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7e00)); // quiet NaN
|
||||
case 8 -> float16ToShortBits(Float16.valueOf(0.0f));
|
||||
default -> float16ToShortBits(Float16.valueOf(-0.0f));
|
||||
};
|
||||
}
|
||||
@ -5423,11 +5425,19 @@ public class Float16Vector128Tests extends AbstractVectorTest {
|
||||
int hash = av.hashCode();
|
||||
|
||||
short subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length());
|
||||
int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(subarr));
|
||||
int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(toFloat16Array(subarr)));
|
||||
Assert.assertTrue(hash == expectedHash, "at index " + i + ", hash should be = " + expectedHash + ", but is = " + hash);
|
||||
}
|
||||
}
|
||||
|
||||
static Float16[] toFloat16Array(short[] bits) {
|
||||
Float16[] a = new Float16[bits.length];
|
||||
for (int j = 0; j < bits.length; j++) {
|
||||
a[j] = shortBitsToFloat16(bits[j]);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
static long ADDReduceLong(short[] a, int idx) {
|
||||
short res = 0;
|
||||
|
||||
@ -1561,14 +1561,16 @@ public class Float16Vector256Tests extends AbstractVectorTest {
|
||||
}
|
||||
|
||||
static short cornerCaseValue(int i) {
|
||||
return switch(i % 8) {
|
||||
return switch(i % 10) {
|
||||
case 0 -> float16ToRawShortBits(Float16.MAX_VALUE);
|
||||
case 1 -> float16ToRawShortBits(Float16.MIN_VALUE);
|
||||
case 2 -> float16ToRawShortBits(Float16.NEGATIVE_INFINITY);
|
||||
case 3 -> float16ToRawShortBits(Float16.POSITIVE_INFINITY);
|
||||
case 4 -> float16ToRawShortBits(Float16.NaN);
|
||||
case 5 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7FFA));
|
||||
case 6 -> float16ToShortBits(Float16.valueOf(0.0f));
|
||||
case 6 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7c01)); // signaling NaN
|
||||
case 7 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7e00)); // quiet NaN
|
||||
case 8 -> float16ToShortBits(Float16.valueOf(0.0f));
|
||||
default -> float16ToShortBits(Float16.valueOf(-0.0f));
|
||||
};
|
||||
}
|
||||
@ -5423,11 +5425,19 @@ public class Float16Vector256Tests extends AbstractVectorTest {
|
||||
int hash = av.hashCode();
|
||||
|
||||
short subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length());
|
||||
int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(subarr));
|
||||
int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(toFloat16Array(subarr)));
|
||||
Assert.assertTrue(hash == expectedHash, "at index " + i + ", hash should be = " + expectedHash + ", but is = " + hash);
|
||||
}
|
||||
}
|
||||
|
||||
static Float16[] toFloat16Array(short[] bits) {
|
||||
Float16[] a = new Float16[bits.length];
|
||||
for (int j = 0; j < bits.length; j++) {
|
||||
a[j] = shortBitsToFloat16(bits[j]);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
static long ADDReduceLong(short[] a, int idx) {
|
||||
short res = 0;
|
||||
|
||||
@ -1561,14 +1561,16 @@ public class Float16Vector512Tests extends AbstractVectorTest {
|
||||
}
|
||||
|
||||
static short cornerCaseValue(int i) {
|
||||
return switch(i % 8) {
|
||||
return switch(i % 10) {
|
||||
case 0 -> float16ToRawShortBits(Float16.MAX_VALUE);
|
||||
case 1 -> float16ToRawShortBits(Float16.MIN_VALUE);
|
||||
case 2 -> float16ToRawShortBits(Float16.NEGATIVE_INFINITY);
|
||||
case 3 -> float16ToRawShortBits(Float16.POSITIVE_INFINITY);
|
||||
case 4 -> float16ToRawShortBits(Float16.NaN);
|
||||
case 5 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7FFA));
|
||||
case 6 -> float16ToShortBits(Float16.valueOf(0.0f));
|
||||
case 6 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7c01)); // signaling NaN
|
||||
case 7 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7e00)); // quiet NaN
|
||||
case 8 -> float16ToShortBits(Float16.valueOf(0.0f));
|
||||
default -> float16ToShortBits(Float16.valueOf(-0.0f));
|
||||
};
|
||||
}
|
||||
@ -5423,11 +5425,19 @@ public class Float16Vector512Tests extends AbstractVectorTest {
|
||||
int hash = av.hashCode();
|
||||
|
||||
short subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length());
|
||||
int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(subarr));
|
||||
int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(toFloat16Array(subarr)));
|
||||
Assert.assertTrue(hash == expectedHash, "at index " + i + ", hash should be = " + expectedHash + ", but is = " + hash);
|
||||
}
|
||||
}
|
||||
|
||||
static Float16[] toFloat16Array(short[] bits) {
|
||||
Float16[] a = new Float16[bits.length];
|
||||
for (int j = 0; j < bits.length; j++) {
|
||||
a[j] = shortBitsToFloat16(bits[j]);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
static long ADDReduceLong(short[] a, int idx) {
|
||||
short res = 0;
|
||||
|
||||
@ -1561,14 +1561,16 @@ public class Float16Vector64Tests extends AbstractVectorTest {
|
||||
}
|
||||
|
||||
static short cornerCaseValue(int i) {
|
||||
return switch(i % 8) {
|
||||
return switch(i % 10) {
|
||||
case 0 -> float16ToRawShortBits(Float16.MAX_VALUE);
|
||||
case 1 -> float16ToRawShortBits(Float16.MIN_VALUE);
|
||||
case 2 -> float16ToRawShortBits(Float16.NEGATIVE_INFINITY);
|
||||
case 3 -> float16ToRawShortBits(Float16.POSITIVE_INFINITY);
|
||||
case 4 -> float16ToRawShortBits(Float16.NaN);
|
||||
case 5 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7FFA));
|
||||
case 6 -> float16ToShortBits(Float16.valueOf(0.0f));
|
||||
case 6 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7c01)); // signaling NaN
|
||||
case 7 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7e00)); // quiet NaN
|
||||
case 8 -> float16ToShortBits(Float16.valueOf(0.0f));
|
||||
default -> float16ToShortBits(Float16.valueOf(-0.0f));
|
||||
};
|
||||
}
|
||||
@ -5423,11 +5425,19 @@ public class Float16Vector64Tests extends AbstractVectorTest {
|
||||
int hash = av.hashCode();
|
||||
|
||||
short subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length());
|
||||
int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(subarr));
|
||||
int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(toFloat16Array(subarr)));
|
||||
Assert.assertTrue(hash == expectedHash, "at index " + i + ", hash should be = " + expectedHash + ", but is = " + hash);
|
||||
}
|
||||
}
|
||||
|
||||
static Float16[] toFloat16Array(short[] bits) {
|
||||
Float16[] a = new Float16[bits.length];
|
||||
for (int j = 0; j < bits.length; j++) {
|
||||
a[j] = shortBitsToFloat16(bits[j]);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
static long ADDReduceLong(short[] a, int idx) {
|
||||
short res = 0;
|
||||
|
||||
@ -1567,14 +1567,16 @@ public class Float16VectorMaxTests extends AbstractVectorTest {
|
||||
}
|
||||
|
||||
static short cornerCaseValue(int i) {
|
||||
return switch(i % 8) {
|
||||
return switch(i % 10) {
|
||||
case 0 -> float16ToRawShortBits(Float16.MAX_VALUE);
|
||||
case 1 -> float16ToRawShortBits(Float16.MIN_VALUE);
|
||||
case 2 -> float16ToRawShortBits(Float16.NEGATIVE_INFINITY);
|
||||
case 3 -> float16ToRawShortBits(Float16.POSITIVE_INFINITY);
|
||||
case 4 -> float16ToRawShortBits(Float16.NaN);
|
||||
case 5 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7FFA));
|
||||
case 6 -> float16ToShortBits(Float16.valueOf(0.0f));
|
||||
case 6 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7c01)); // signaling NaN
|
||||
case 7 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7e00)); // quiet NaN
|
||||
case 8 -> float16ToShortBits(Float16.valueOf(0.0f));
|
||||
default -> float16ToShortBits(Float16.valueOf(-0.0f));
|
||||
};
|
||||
}
|
||||
@ -5429,11 +5431,19 @@ public class Float16VectorMaxTests extends AbstractVectorTest {
|
||||
int hash = av.hashCode();
|
||||
|
||||
short subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length());
|
||||
int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(subarr));
|
||||
int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(toFloat16Array(subarr)));
|
||||
Assert.assertTrue(hash == expectedHash, "at index " + i + ", hash should be = " + expectedHash + ", but is = " + hash);
|
||||
}
|
||||
}
|
||||
|
||||
static Float16[] toFloat16Array(short[] bits) {
|
||||
Float16[] a = new Float16[bits.length];
|
||||
for (int j = 0; j < bits.length; j++) {
|
||||
a[j] = shortBitsToFloat16(bits[j]);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
static long ADDReduceLong(short[] a, int idx) {
|
||||
short res = 0;
|
||||
|
||||
@ -100,11 +100,25 @@
|
||||
int hash = av.hashCode();
|
||||
|
||||
$type$ subarr[] = Arrays.copyOfRange(a, i, i + SPECIES.length());
|
||||
#if[FP16]
|
||||
int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(toFloat16Array(subarr)));
|
||||
#else[FP16]
|
||||
int expectedHash = Objects.hash(SPECIES, Arrays.hashCode(subarr));
|
||||
#end[FP16]
|
||||
Assert.assertTrue(hash == expectedHash, "at index " + i + ", hash should be = " + expectedHash + ", but is = " + hash);
|
||||
}
|
||||
}
|
||||
|
||||
#if[FP16]
|
||||
static Float16[] toFloat16Array(short[] bits) {
|
||||
Float16[] a = new Float16[bits.length];
|
||||
for (int j = 0; j < bits.length; j++) {
|
||||
a[j] = shortBitsToFloat16(bits[j]);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
#end[FP16]
|
||||
#if[byte]
|
||||
@Test(dataProvider = "$type$UnaryOpProvider")
|
||||
static void reinterpretAsBytes$vectorteststype$SmokeTest(IntFunction<$type$[]> fa) {
|
||||
|
||||
@ -2013,14 +2013,16 @@ relativeError));
|
||||
static $type$ cornerCaseValue(int i) {
|
||||
#if[FP]
|
||||
#if[FP16]
|
||||
return switch(i % 8) {
|
||||
return switch(i % 10) {
|
||||
case 0 -> float16ToRawShortBits($Wideboxtype$.MAX_VALUE);
|
||||
case 1 -> float16ToRawShortBits($Wideboxtype$.MIN_VALUE);
|
||||
case 2 -> float16ToRawShortBits($Wideboxtype$.NEGATIVE_INFINITY);
|
||||
case 3 -> float16ToRawShortBits($Wideboxtype$.POSITIVE_INFINITY);
|
||||
case 4 -> float16ToRawShortBits($Wideboxtype$.NaN);
|
||||
case 5 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7FFA));
|
||||
case 6 -> float16ToShortBits(Float16.valueOf(0.0f));
|
||||
case 6 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7c01)); // signaling NaN
|
||||
case 7 -> float16ToRawShortBits(shortBitsToFloat16((short)0x7e00)); // quiet NaN
|
||||
case 8 -> float16ToShortBits(Float16.valueOf(0.0f));
|
||||
default -> float16ToShortBits(Float16.valueOf(-0.0f));
|
||||
};
|
||||
#else[FP16]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user