Description
Feature or enhancement
Proposal:
Currently the error handling happens this way for the cmath module (taken from module comments):
Each of the c_* functions computes and returns the C99 Annex G recommended result and also sets errno as follows: errno = 0 if no floating-point exception is associated with the result; errno = EDOM if C99 Annex G recommends raising divide-by-zero or invalid for this result; and errno = ERANGE where the overflow floating-point signal should be raised.
The ValueError raised for EDOM and the OverflowError - for ERANGE, but the Annex G result is hidden from the pure-Python world. Though, it might be helpful for applications. E.g. clog(-0+0i)
returns -∞+πi
and clog(+0+0i)
returns -∞+0i
- correct one-sided limits in the pole of log(). (BTW, something like PoleError could be better here, but that's another story.)
The mpmath and the gmpy2 (per default, if trap_divzero
and/or trap_invalid
context options aren't enabled) rather return special values per the C standard, not raise exceptions. And the mpmath also uses builtin float's and math/cmath functions for the fp context. Thus, to override current behavior of the stdlib - we need to catch ValueError from the called function and then process function arguments to return special values, i.e. essentially re-implement handling of special values. But they already are computed in cmath/math functions, so why not return this information with an exception? An example:
>>> import cmath
>>> try:
... cmath.atanh(1)
... except ValueError as ex:
... print(ex.value)
...
(inf+0j)
Initial patch, working for most functions, not using math_error().
diff --git a/Modules/cmathmodule.c b/Modules/cmathmodule.c
index 81cbf0d554..d388241f94 100644
--- a/Modules/cmathmodule.c
+++ b/Modules/cmathmodule.c
@@ -36,6 +36,15 @@ class Py_complex_protected_return_converter(CReturnConverter):
data.return_conversion.append("""
if (errno == EDOM) {
PyErr_SetString(PyExc_ValueError, "math domain error");
+
+ PyObject *exc = PyErr_GetRaisedException();
+ PyObject *value = PyComplex_FromCComplex(_return_value);
+
+ if (value) {
+ PyObject_SetAttrString(exc, "value", value);
+ }
+ Py_DECREF(value);
+ PyErr_SetRaisedException(exc);
goto exit;
}
else if (errno == ERANGE) {
Similar happens in the math module and fix looks simple as well. I didn't check all cases, but it seems that most functions in the cmath/math modules actually compute correct (per C standard and Annex G) answers for special values.
Alternative approach: some global flag to turn on the gmpy2-like behavior (i.e. raise no exceptions, but return special values instead).
Has this already been discussed elsewhere?
This is a minor feature, which does not need previous discussion elsewhere
Links to previous discussion of this feature:
No response