Skip to content

Commit c52b17a

Browse files
authored
More robust packing of flats in FF cache (#20150)
This should fix issues with `librt` not working well on platforms with hardware float support, it should also make cache format endian-independent (since we ask for little-endian format using `1` as last argument independently of current endianness). More details in https://docs.python.org/3/c-api/float.html#pack-functions
1 parent f64bf11 commit c52b17a

File tree

2 files changed

+16
-6
lines changed

2 files changed

+16
-6
lines changed

mypyc/lib-rt/librt_internal.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -509,14 +509,18 @@ write_bytes(PyObject *self, PyObject *const *args, size_t nargs, PyObject *kwnam
509509

510510
/*
511511
float format:
512-
stored as a C double
512+
stored using PyFloat helpers in little-endian format.
513513
*/
514514

515515
static double
516516
read_float_internal(PyObject *data) {
517517
_CHECK_BUFFER(data, CPY_FLOAT_ERROR)
518-
_CHECK_READ(data, sizeof(double), CPY_FLOAT_ERROR)
519-
double res = _READ(data, double)
518+
_CHECK_READ(data, 8, CPY_FLOAT_ERROR)
519+
char *buf = ((BufferObject *)data)->buf;
520+
double res = PyFloat_Unpack8(buf + ((BufferObject *)data)->pos, 1);
521+
if (unlikely((res == -1.0) && PyErr_Occurred()))
522+
return CPY_FLOAT_ERROR;
523+
((BufferObject *)data)->pos += 8;
520524
return res;
521525
}
522526

@@ -538,9 +542,13 @@ read_float(PyObject *self, PyObject *const *args, size_t nargs, PyObject *kwname
538542
static char
539543
write_float_internal(PyObject *data, double value) {
540544
_CHECK_BUFFER(data, CPY_NONE_ERROR)
541-
_CHECK_SIZE(data, sizeof(double))
542-
_WRITE(data, double, value)
543-
((BufferObject *)data)->end += sizeof(double);
545+
_CHECK_SIZE(data, 8)
546+
char *buf = ((BufferObject *)data)->buf;
547+
int res = PyFloat_Pack8(value, buf + ((BufferObject *)data)->pos, 1);
548+
if (unlikely(res == -1))
549+
return CPY_NONE_ERROR;
550+
((BufferObject *)data)->pos += 8;
551+
((BufferObject *)data)->end += 8;
544552
return CPY_NONE;
545553
}
546554

mypyc/test-data/run-classes.test

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2741,6 +2741,7 @@ def test_buffer_roundtrip() -> None:
27412741
write_bytes(b, b"a" * 117)
27422742
write_bytes(b, b"a" * 118)
27432743
write_float(b, 0.1)
2744+
write_float(b, -1.0)
27442745
write_float(b, -113.0)
27452746
write_int(b, 0)
27462747
write_int(b, 1)
@@ -2767,6 +2768,7 @@ def test_buffer_roundtrip() -> None:
27672768
assert read_bytes(b) == b"a" * 117
27682769
assert read_bytes(b) == b"a" * 118
27692770
assert read_float(b) == 0.1
2771+
assert read_float(b) == -1.0
27702772
assert read_float(b) == -113.0
27712773
assert read_int(b) == 0
27722774
assert read_int(b) == 1

0 commit comments

Comments
 (0)