Skip to content

Commit 76d823f

Browse files
committed
fixing subnormal cross-platform
1 parent 47c9409 commit 76d823f

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

quaddtype/numpy_quaddtype/src/quaddtype_main.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,26 @@ get_sleef_constant(PyObject *self, PyObject *args)
7171
result->value.sleef_value = SLEEF_QUAD_MIN;
7272
}
7373
else if (strcmp(constant_name, "smallest_subnormal") == 0) {
74+
#ifdef SLEEF_QUAD_C
75+
// On platforms with native __float128 support, use the correct literal
7476
result->value.sleef_value = SLEEF_QUAD_DENORM_MIN;
77+
#else
78+
// On platforms without native __float128, SLEEF_QUAD_DENORM_MIN is broken
79+
// Manually constructing the smallest subnormal: 1 * 2^(-16382-112) = 2^(-16494)
80+
// This represents 0x0.0000000000000000000000000001p-16382
81+
#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
82+
struct {
83+
uint64_t h, l;
84+
} c;
85+
#else
86+
struct {
87+
uint64_t l, h;
88+
} c;
89+
#endif
90+
c.h = 0x0000000000000000ULL; // exponent = 0 (subnormal), mantissa high = 0
91+
c.l = 0x0000000000000001ULL; // mantissa low = 1 (smallest possible)
92+
memcpy(&result->value.sleef_value, &c, 16);
93+
#endif
7594
}
7695
else if (strcmp(constant_name, "bits") == 0) {
7796
Py_DECREF(result);

quaddtype/tests/test_quaddtype.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ def test_finfo_constant(name):
2424
assert isinstance(getattr(numpy_quaddtype, name), QuadPrecision)
2525

2626

27+
def test_smallest_subnormal_value():
28+
"""Test that smallest_subnormal has the correct value across all platforms."""
29+
smallest_sub = numpy_quaddtype.smallest_subnormal
30+
repr_str = repr(smallest_sub)
31+
32+
# The repr should show QuadPrecision('6.0e-4966', backend='sleef')
33+
assert "6.0e-4966" in repr_str, f"Expected '6.0e-4966' in repr, got {repr_str}"
34+
35+
assert smallest_sub > 0, "smallest_subnormal should be positive"
36+
2737
@pytest.mark.parametrize("name,value", [("bits", 128), ("precision", 33)])
2838
def test_finfo_int_constant(name, value):
2939
assert getattr(numpy_quaddtype, name) == value

0 commit comments

Comments
 (0)