Skip to content

Commit 3d37460

Browse files
committed
adding related tests
1 parent 1ec36d6 commit 3d37460

File tree

1 file changed

+70
-1
lines changed

1 file changed

+70
-1
lines changed

quaddtype/tests/test_quaddtype.py

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5132,4 +5132,73 @@ def test_large_array_casting(dtype, size):
51325132

51335133
# check roundtrip
51345134
roundtrip = quad_arr.astype(dtype)
5135-
np.testing.assert_array_equal(arr, roundtrip)
5135+
np.testing.assert_array_equal(arr, roundtrip)
5136+
5137+
5138+
class TestBinaryOpsEdgeCases:
5139+
"""Edge case tests for binary operations - SLEEF 3.8 had inconsistency where (0 + x) != (x + 0).
5140+
5141+
In SLEEF 3.8:
5142+
- (0 + 6.724206286224186953608055004397316e-4932) gave half the expected value
5143+
- (6.724206286224186953608055004397316e-4932 + 0) was correct
5144+
5145+
SLEEF 4.0 fixes this inconsistency.
5146+
"""
5147+
5148+
# The exact values from the bug
5149+
SMALL_VALUE = "6.724206286224186953608055004397316e-4932"
5150+
ZERO = 0.0
5151+
5152+
@pytest.mark.parametrize('op', [
5153+
("add", "fadd"),
5154+
("subtract", "fsub"),
5155+
("multiply", "fmul"),
5156+
("divide", "fdiv"),
5157+
("mod", "fmod"),
5158+
("power", "power"),
5159+
("hypot", "hypot"),
5160+
("atan2", "atan2"),
5161+
])
5162+
def test_binary_op_consistency(self, op):
5163+
"""Test that abs(x op y) == abs(y op x) - catches half-value bugs."""
5164+
mp.prec = 113
5165+
small = QuadPrecision(self.SMALL_VALUE)
5166+
zero = QuadPrecision(self.ZERO)
5167+
5168+
mp_small = mp.mpf(self.SMALL_VALUE)
5169+
mp_zero = mp.mpf(self.ZERO)
5170+
5171+
quad_op_str, mpmath_op_str = op
5172+
quad_op, mpmath_op = getattr(np, quad_op_str), getattr(mp, mpmath_op_str)
5173+
quad_result = quad_op(zero, small)
5174+
mpmath_result = mpmath_op(mp_zero, mp_small)
5175+
5176+
# Use mp.nstr to get full precision (50 digits for quad precision)
5177+
mpmath_result = QuadPrecision(mp.nstr(mpmath_result, 50))
5178+
5179+
# Handle NaN cases
5180+
if np.isnan(mpmath_result):
5181+
assert np.isnan(quad_result), f"Expected NaN for {quad_op_str}, got {quad_result}"
5182+
return
5183+
5184+
# Handle infinity cases
5185+
if np.isinf(mpmath_result):
5186+
assert np.isinf(quad_result), f"Expected inf for {quad_op_str}, got {quad_result}"
5187+
assert np.sign(mpmath_result) == np.sign(quad_result), f"Infinity sign mismatch for {quad_op_str}"
5188+
return
5189+
5190+
# For finite non-zero results
5191+
np.testing.assert_allclose(quad_result, mpmath_result, rtol=1e-32, atol=1e-34,
5192+
err_msg=f"Value mismatch for {quad_op_str}, expected {mpmath_result}, got {quad_result}")
5193+
5194+
5195+
def test_add_regression_zero_plus_small(self):
5196+
"""The exact SLEEF 3.8 bug: 0 + small_value gave half the expected."""
5197+
x = QuadPrecision(self.SMALL_VALUE)
5198+
y = QuadPrecision(self.ZERO)
5199+
5200+
result_yx = y + x # 0 + x (this was buggy in SLEEF 3.8)
5201+
result_xy = x + y # x + 0 (this was correct in SLEEF 3.8)
5202+
5203+
assert result_yx == result_xy, f"0 + x = {result_yx}, but x + 0 = {result_xy}"
5204+
assert result_yx == x, f"0 + x = {result_yx}, expected {x}"

0 commit comments

Comments
 (0)