ENH: initialize params->error_num to zero in optimize/Zeros/*.c
See original GitHub issueproblem
Currently if you call the c functions in optimize/Zeros/ and they successfully converge, you get garbage b/c the value params->error_num is never initialized, instead it’s only set if there is either SIGNERR or CONVERR.
proposal
The other values in params are initialized to zero, so is there any reason why the error number can’t also be initialized as zero? In the Python extension module _zeros, the flag output is initialized as zero so if params->error_num is neither SIGNERR nor CONVERR, then flag stays zero, which in zeros.RootResults maps to CONVERGED. So is it okay to set params->error_num to zero in the optimizeZeros/*.c for consistency?
Reproducing code example:
In PR #8431 Jupyter notebook there’s an example that calls brentq.c and shows the full output with garbage in params->error_num
>>> %%cython
>>> from scipy.optimize.cython_optimize cimport zeros_tuple
>>> from scipy.optimize.cython_optimize.examples.zeros_tuple_examples cimport f_solarcell
>>> ARGS = (5.25, 6.0, 1e-09, 0.004, 10.0, 0.27456)
>>> XTOL, RTOL, MITR = 0.001, 0.001, 10
>>> cdef scipy_brent_full_output solarcell_brentq_full_output(tuple args, double xa, double xb, double xtol, double rtol, int mitr):
... cdef scipy_brent_full_output full_output
... zeros_tuple.brentq(f_solarcell, xa, xb, args, xtol, rtol, mitr,
... <zeros_tuple.scipy_zeros_parameters *> &full_output)
... return full_output # root = 5.255231961257658 not shown
>>> print(solarcell_brentq_full_output(ARGS, 0.0, 6.0, XTOL, RTOL, MITR))
{'error_num': -1874247292, # <- this means it converged, since it's not -1 or -2
'funcalls': 4,
'iterations': 3}
By contrast, the optimize/cython_optimize/Newton/*.c functions initialize params->error_num = 0 so their output is more meaningful. Here’s another example from the Cython Optimize Zeros API Jupyter notebook that calls newton.c with full output.
>>> %%cython
>>> from scipy.optimize.cython_optimize cimport zeros_tuple
>>> from scipy.optimize.cython_optimize.examples.zeros_tuple_examples cimport f_solarcell, fprime
>>> ARGS = (5.25, 6.0, 1e-09, 0.004, 10.0, 0.27456)
>>> TOL, MAXITER = 1.48e-8, 50
>>> cdef scipy_newton_full_output solarcell_newton_full_output(tuple args, double x0, double tol, int maxiter):
... cdef scipy_newton_full_output full_output
... zeros_tuple.newton(f_solarcell, x0, fprime, args, tol, maxiter,
... <zeros_tuple.scipy_newton_parameters *> &full_output)
... return full_output # root = 5.255320079106907 not shown
>>> print(solarcell_newton_full_output(ARGS, 6.0, TOL, MAXITER))
{'error_num': 0, # <- **more meaningful in my opinion**
'funcalls': 6,
'iterations': 3}
Error message:
There is no error message. The issue is IMO it is more explicit to set the error number to zero instead of forcing the user to infer that functions in optimize/Zeros converged because they did not error.
Scipy/Numpy/Python version information:
1.1.0 1.15.0 sys.version_info(major=3, minor=6, micro=6, releaselevel='final', serial=0)
Issue Analytics
- State:
- Created 5 years ago
- Comments:5 (5 by maintainers)

Top Related StackOverflow Question
Yes, I can confirm #9465 closes this issue because:
CONVERGED = 0inzeros.hCONVERGEDjust prior to successful return in all of the bounded zero search functions, EG: inbisect.cbefore a successful return, error number is set toCONVERGEDThanks!
I think there may be another good reason to initialize
params->error_numbecause if not initialized, the reference might, by pure coincidence, be the same as eitherSIGNERRorCONVERR, and so you would get a false negative. Since in the current codebase the initial value is never set, there’s no way to know what value would be at that reference. By initializing the reference to zero, we know it could only be intentionally set to an error.