gh-133304: workaround for RISC-V in PyFloat_Pack4/Unpack4() (#133328)
This commit is contained in:
parent
84a08f8629
commit
f16f06f336
@ -199,13 +199,13 @@ class CAPIFloatTest(unittest.TestCase):
|
|||||||
signaling = 0
|
signaling = 0
|
||||||
quiet = int(not signaling)
|
quiet = int(not signaling)
|
||||||
if size == 8:
|
if size == 8:
|
||||||
payload = random.randint(signaling, 1 << 50)
|
payload = random.randint(signaling, 0x7ffffffffffff)
|
||||||
i = (sign << 63) + (0x7ff << 52) + (quiet << 51) + payload
|
i = (sign << 63) + (0x7ff << 52) + (quiet << 51) + payload
|
||||||
elif size == 4:
|
elif size == 4:
|
||||||
payload = random.randint(signaling, 1 << 21)
|
payload = random.randint(signaling, 0x3fffff)
|
||||||
i = (sign << 31) + (0xff << 23) + (quiet << 22) + payload
|
i = (sign << 31) + (0xff << 23) + (quiet << 22) + payload
|
||||||
elif size == 2:
|
elif size == 2:
|
||||||
payload = random.randint(signaling, 1 << 8)
|
payload = random.randint(signaling, 0x1ff)
|
||||||
i = (sign << 15) + (0x1f << 10) + (quiet << 9) + payload
|
i = (sign << 15) + (0x1f << 10) + (quiet << 9) + payload
|
||||||
data = bytes.fromhex(f'{i:x}')
|
data = bytes.fromhex(f'{i:x}')
|
||||||
for endian in (BIG_ENDIAN, LITTLE_ENDIAN):
|
for endian in (BIG_ENDIAN, LITTLE_ENDIAN):
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
Workaround NaN's "canonicalization" in :c:func:`PyFloat_Pack4`
|
||||||
|
and :c:func:`PyFloat_Unpack4` on RISC-V.
|
@ -2196,12 +2196,33 @@ PyFloat_Pack4(double x, char *data, int le)
|
|||||||
uint64_t v;
|
uint64_t v;
|
||||||
|
|
||||||
memcpy(&v, &x, 8);
|
memcpy(&v, &x, 8);
|
||||||
|
#ifndef __riscv
|
||||||
if ((v & (1ULL << 51)) == 0) {
|
if ((v & (1ULL << 51)) == 0) {
|
||||||
uint32_t u32;
|
uint32_t u32;
|
||||||
memcpy(&u32, &y, 4);
|
memcpy(&u32, &y, 4);
|
||||||
u32 &= ~(1 << 22); /* make sNaN */
|
u32 &= ~(1 << 22); /* make sNaN */
|
||||||
memcpy(&y, &u32, 4);
|
memcpy(&y, &u32, 4);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
uint32_t u32;
|
||||||
|
|
||||||
|
memcpy(&u32, &y, 4);
|
||||||
|
if ((v & (1ULL << 51)) == 0) {
|
||||||
|
u32 &= ~(1 << 22);
|
||||||
|
}
|
||||||
|
/* Workaround RISC-V: "If a NaN value is converted to a
|
||||||
|
* different floating-point type, the result is the
|
||||||
|
* canonical NaN of the new type". The canonical NaN here
|
||||||
|
* is a positive qNaN with zero payload. */
|
||||||
|
if (v & (1ULL << 63)) {
|
||||||
|
u32 |= (1 << 31); /* set sign */
|
||||||
|
}
|
||||||
|
/* add payload */
|
||||||
|
u32 -= (u32 & 0x3fffff);
|
||||||
|
u32 += (uint32_t)((v & 0x7ffffffffffffULL) >> 29);
|
||||||
|
|
||||||
|
memcpy(&y, &u32, 4);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char s[sizeof(float)];
|
unsigned char s[sizeof(float)];
|
||||||
@ -2493,6 +2514,7 @@ PyFloat_Unpack4(const char *data, int le)
|
|||||||
uint32_t v;
|
uint32_t v;
|
||||||
memcpy(&v, &x, 4);
|
memcpy(&v, &x, 4);
|
||||||
|
|
||||||
|
#ifndef __riscv
|
||||||
if ((v & (1 << 22)) == 0) {
|
if ((v & (1 << 22)) == 0) {
|
||||||
double y = x; /* will make qNaN double */
|
double y = x; /* will make qNaN double */
|
||||||
uint64_t u64;
|
uint64_t u64;
|
||||||
@ -2501,6 +2523,25 @@ PyFloat_Unpack4(const char *data, int le)
|
|||||||
memcpy(&y, &u64, 8);
|
memcpy(&y, &u64, 8);
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
double y = x;
|
||||||
|
uint64_t u64;
|
||||||
|
|
||||||
|
memcpy(&u64, &y, 8);
|
||||||
|
if ((v & (1 << 22)) == 0) {
|
||||||
|
u64 &= ~(1ULL << 51);
|
||||||
|
}
|
||||||
|
/* Workaround RISC-V, see PyFloat_Pack4() */
|
||||||
|
if (v & (1 << 31)) {
|
||||||
|
u64 |= (1ULL << 63); /* set sign */
|
||||||
|
}
|
||||||
|
/* add payload */
|
||||||
|
u64 -= (u64 & 0x7ffffffffffffULL);
|
||||||
|
u64 += ((v & 0x3fffffULL) << 29);
|
||||||
|
|
||||||
|
memcpy(&y, &u64, 8);
|
||||||
|
return y;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user