Skip to content

Commit eaf0812

Browse files
committed
true_divide impl
1 parent d4d5b4e commit eaf0812

File tree

3 files changed

+100
-1
lines changed

3 files changed

+100
-1
lines changed

quaddtype/numpy_quaddtype/src/umath/binary_ops.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,8 @@ init_quad_binary_ops(PyObject *numpy)
216216
if (create_quad_binary_ufunc<quad_div, ld_div>(numpy, "divide") < 0) {
217217
return -1;
218218
}
219+
// Note: true_divide is an alias to divide in NumPy for floating-point types
220+
// No need to register separately
219221
if (create_quad_binary_ufunc<quad_pow, ld_pow>(numpy, "power") < 0) {
220222
return -1;
221223
}

quaddtype/release_tracker.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
| divide |||
1313
| logaddexp |||
1414
| logaddexp2 |||
15-
| true_divide | | |
15+
| true_divide | | |
1616
| floor_divide | | |
1717
| negative |||
1818
| positive |||

quaddtype/tests/test_quaddtype.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,103 @@ def test_logaddexp2_special_properties():
635635
np.testing.assert_allclose(float(result_logaddexp2), result_logaddexp, rtol=1e-13)
636636

637637

638+
@pytest.mark.parametrize(
639+
"x_val",
640+
[
641+
0.0, 1.0, 2.0, -1.0, -2.0,
642+
0.5, -0.5,
643+
100.0, 1000.0, -100.0, -1000.0,
644+
1e-10, -1e-10, 1e-20, -1e-20,
645+
float("inf"), float("-inf"), float("nan"), float("-nan"), -0.0
646+
]
647+
)
648+
@pytest.mark.parametrize(
649+
"y_val",
650+
[
651+
0.0, 1.0, 2.0, -1.0, -2.0,
652+
0.5, -0.5,
653+
100.0, 1000.0, -100.0, -1000.0,
654+
1e-10, -1e-10, 1e-20, -1e-20,
655+
float("inf"), float("-inf"), float("nan"), float("-nan"), -0.0
656+
]
657+
)
658+
def test_true_divide(x_val, y_val):
659+
"""Test true_divide ufunc with comprehensive edge cases"""
660+
x_quad = QuadPrecision(str(x_val))
661+
y_quad = QuadPrecision(str(y_val))
662+
663+
# Compute using QuadPrecision
664+
result_quad = np.true_divide(x_quad, y_quad)
665+
666+
# Compute using float64 for comparison
667+
result_float64 = np.true_divide(np.float64(x_val), np.float64(y_val))
668+
669+
# Compare results
670+
if np.isnan(result_float64):
671+
assert np.isnan(float(result_quad)), f"Expected NaN for true_divide({x_val}, {y_val})"
672+
elif np.isinf(result_float64):
673+
assert np.isinf(float(result_quad)), f"Expected inf for true_divide({x_val}, {y_val})"
674+
assert np.sign(float(result_quad)) == np.sign(result_float64), f"Sign mismatch for true_divide({x_val}, {y_val})"
675+
else:
676+
# For finite results, check relative tolerance
677+
np.testing.assert_allclose(
678+
float(result_quad), result_float64, rtol=1e-14,
679+
err_msg=f"Mismatch for true_divide({x_val}, {y_val})"
680+
)
681+
682+
683+
def test_true_divide_special_properties():
684+
"""Test special mathematical properties of true_divide"""
685+
# Division by 1 returns the original value
686+
x = QuadPrecision("42.123456789")
687+
result = np.true_divide(x, QuadPrecision("1.0"))
688+
np.testing.assert_allclose(float(result), float(x), rtol=1e-30)
689+
690+
# Division of 0 by any non-zero number is 0
691+
result = np.true_divide(QuadPrecision("0.0"), QuadPrecision("5.0"))
692+
assert float(result) == 0.0
693+
694+
# Division by 0 gives inf (with appropriate sign)
695+
result = np.true_divide(QuadPrecision("1.0"), QuadPrecision("0.0"))
696+
assert np.isinf(float(result)) and float(result) > 0
697+
698+
result = np.true_divide(QuadPrecision("-1.0"), QuadPrecision("0.0"))
699+
assert np.isinf(float(result)) and float(result) < 0
700+
701+
# 0 / 0 = NaN
702+
result = np.true_divide(QuadPrecision("0.0"), QuadPrecision("0.0"))
703+
assert np.isnan(float(result))
704+
705+
# inf / inf = NaN
706+
result = np.true_divide(QuadPrecision("inf"), QuadPrecision("inf"))
707+
assert np.isnan(float(result))
708+
709+
# inf / finite = inf
710+
result = np.true_divide(QuadPrecision("inf"), QuadPrecision("100.0"))
711+
assert np.isinf(float(result)) and float(result) > 0
712+
713+
# finite / inf = 0
714+
result = np.true_divide(QuadPrecision("100.0"), QuadPrecision("inf"))
715+
assert float(result) == 0.0
716+
717+
# Self-division (x / x) = 1 for finite non-zero x
718+
x = QuadPrecision("7.123456789")
719+
result = np.true_divide(x, x)
720+
np.testing.assert_allclose(float(result), 1.0, rtol=1e-30)
721+
722+
# Sign preservation: (-x) / y = -(x / y)
723+
x = QuadPrecision("5.5")
724+
y = QuadPrecision("2.2")
725+
result1 = np.true_divide(-x, y)
726+
result2 = -np.true_divide(x, y)
727+
np.testing.assert_allclose(float(result1), float(result2), rtol=1e-30)
728+
729+
# Sign rule: negative / negative = positive
730+
result = np.true_divide(QuadPrecision("-6.0"), QuadPrecision("-2.0"))
731+
assert float(result) > 0
732+
np.testing.assert_allclose(float(result), 3.0, rtol=1e-30)
733+
734+
638735
def test_inf():
639736
assert QuadPrecision("inf") > QuadPrecision("1e1000")
640737
assert np.signbit(QuadPrecision("inf")) == 0

0 commit comments

Comments
 (0)