Skip to main content

A fast and robust root-finding library written in C for Python, using the Modified Anderson-Bjork method: Ganchovski, N.; Smith, O.; Rackauckas, C.; Tomov, L.; Traykov, A. Improvements to the Modified Anderson–Björck(modAB) Root-Finding Algorithm. Algorithms 2026, 19, 332. https://doi.org/10.3390/a19050332 It finds the root of a single nonlinear equation f(x) = 0 within the specified interval [x1, x2].

Installation

pip install pymodab

Usage

import math
from pymodab import find_root, get_evaluation_count

# Find the root of cos(x) - x = 0 in [0, 1]
root = find_root(lambda x: math.cos(x) - x, 0, 1, 1e-3, 1e-3, 10)
print(f"Root: {root}")  # 0.7390851332086904

# Get the number of function evaluations
print(f"Evaluations: {get_evaluation_count()}")
print(f"Error:       {math.cos(root) - root}")

# Using default tolerances
root = find_root(lambda x: x**2 - 2, 1, 2)
print(f"sqrt(2) = {root}")  # 1.414213562373095

# Get the number of function evaluations
print(f"Evaluations: {get_evaluation_count()}")
print(f"Error:       {root**2 - 2}")

API

find_root(f, x1, x2, atol=1e-14, rtol=1e-14, max_iter=200)

Find the root of f(x) = 0 within the interval [x1, x2].

Parameters:

  • f: A continuous function of one variable, or the address (int) of a compiled C function double f(double)
  • x1, x2: Bracket interval endpoints (must satisfy f(x1) * f(x2) < 0)
  • atol: Absolute tolerance (default: 1e-14)
  • rtol: Relative tolerance (default: 1e-14)
  • max_iter: Maximum iterations (default: 200)

Returns: The root, or NaN if not found. Exceptions raised by f are propagated to the caller. This holds for the native extension only: with the ctypes fallback (pymodab.NATIVE is False), an exception in f is only printed to stderr, the search goes on with an undefined value of f(x), and the result cannot be trusted; it may be NaN or a wrong root.

Since version 1.0.6, find_root is a native CPython extension that calls f directly, which is about 2x faster than the previous ctypes wrapper. Version 1.0.7 ships it as a wheel for Windows, Linux (x86_64 and aarch64, glibc and musl) and macOS (Intel and Apple Silicon); one wheel serves every CPython from 3.8 up. On any other platform pymodab falls back to ctypes automatically; pymodab.NATIVE tells which one is used.

Version 1.0.8 improves the fallback from secant to bisection steps: a secant step that does not shrink the bracket fast enough is still kept if it at least halves the best residual of the bracket. This avoids needless bisection steps when the secant converges from one side, and falls back sooner when it stalls. get_evaluation_count() now returns the exact number of calls to f. Version 1.0.9 ships that work as wheels for every supported platform.

Version 1.0.10 adds overflow and NaN safeguards to the arithmetic. The midpoint and the secant point are computed without forming x1 + x2 or x1*y2 - x2*y1, so they stay finite and inside the bracket even for endpoints or residuals near the floating-point limits. A NaN from f stops the search with NaN instead of corrupting the bracket. The Anderson-Björck scaling never lets an auxiliary ordinate underflow to zero. The new secant formula rounds differently, so single problems may need a few evaluations more or less; the 100 benchmark problems below need 1895 in total instead of 1897.

Version 1.1.0 simplifies these safeguards without weakening them. The test that switches from bisection to secant steps is now computed inline as |ym - y3| < k·|ym| + k·|y3|, which cannot overflow, and it is skipped while f(x2) - f(x1) overflows, so the search keeps bisecting until the residuals shrink. The bracket is updated from the sign of the true residuals instead of the Anderson-Björck auxiliary ordinates, so an auxiliary ordinate that underflows to zero can no longer steer the update, and the extra underflow guard of 1.0.10 is no longer needed. The 100 benchmark problems give the same roots and evaluation counts as with 1.0.10.

Version 1.1.1 separates the bisection and Anderson-Björck steps in the solver loop. A bisection step now updates only the bracket and the true residuals. The Anderson-Björck corrections and the fallback test run only on secant steps, and the auxiliary ordinates start from the true residuals whenever the search switches to secant steps. It also caps the residual exception of 1.0.8: a secant step that does not shrink the bracket fast enough is kept on the strength of halving the residual for at most three consecutive steps (MAX_RESIDUAL_STEPS), after which the search falls back to bisection anyway. Without the cap, f(x) = -x*x for x < 0 and 7*x*x for x >= 0 on [-π, 1], a counterexample by L. Tomov, keeps halving the residual while the bracket never gets narrower than 1, and the search runs out of iterations; with the cap it converges in 76 evaluations. This function is now problem f101 of the benchmark. The other 100 problems give the same roots and evaluation counts as with 1.1.0; all 101 need 1971 evaluations in total.

For maximum speed, pass a compiled function, e.g. from numba. It is then called from C with no Python overhead:

import math
from numba import cfunc
from pymodab import find_root

@cfunc("float64(float64)")
def f(x):
    return math.cos(x) - x

root = find_root(f.address, 0, 1)

get_evaluation_count()

Returns the number of function evaluations from the last root-finding call.

Algorithm

Modified Anderson-Björck's method is a new robust and efficient bracketing root-finding algorithm. It combines bisection with Anderson-Björk's method to achieve both fast performance and worst-case optimality.

References:

Ganchovski N.; Traykov A. Modified Anderson-Björck's method for solving non-linear equations in structural mechanics. IOP Conference Series: Materials Science and Engineering 2023, 1276 (1) 012010, IOP Publishing.
https://iopscience.iop.org/article/10.1088/1757-899X/1276/1/012010/pdf

Ganchovski, N.; Smith, O.; Rackauckas, C.; Tomov, L.; Traykov, A. Improvements to the Modified Anderson–Björck (modAB) Root-Finding Algorithm. Algorithms 2026, 19, 332. https://doi.org/10.3390/a19050332

License

MIT License

Benchmark results

The modAB algorithm is benchmarked against the available algorithms in Python/SciPy in respect to number of evaluations and execution times:

  • bisect- Bisection method
  • brentq - Brent’s method (van Wijngaarden–Dekker–Brent, 1973)
  • brenth - Brent–Dekker variant (hyperbolic extrapolation variant, 1975)
  • ridder - Ridder’s method (1979)
  • toms748 - Alefeld–Potra–Shi method (1995 - TOMS Algorithm 748)
  • chandr - Chandrupatla's method (1997) - scipy.optimize.elementwise.find_root
  • cybrentq - Cython implementation of brentq by Gledis Caushaj
  • modAB_SG - Safeguarded Modified Anderson Bjork's method (Ganchovski & Traykov, 2023; improved 2026 by L.Tomov and N.Ganchovski)
  • modAB_ct - the old version of pymodab 1.0.5 implemented with ctypes

Function evaluations

Func bisect brentq brenth ridder chandr cybrentq modAB_ct modAB_SG
SUM 4883 2810 2769 3425 2112 2810 1993 1971
AVG 48 28 27 34 21 28 20 20
MEDIAN 49 13 12 16 12 13 13 13
MIN 3 4 4 3 3 4 3 3
MAX 53 102 102 202 70 102 78 76
FACTOR 2.477x 1.426x 1.405x 1.738x 1.072x 1.426x 1.011x 1.000x

Execution times (ms per problem, 200 iterations)

Func bisect brentq brenth ridder chandr cybrentq modAB_ct modAB_SG
SUM 1385.66 841.73 814.23 976.14 57729.06 114.57 165.90 87.27
AVG 13.7194 8.3340 8.0617 9.6647 571.5749 1.1344 1.6426 0.8641
MEDIAN 13.9073 4.3587 4.2225 5.4357 336.8105 0.6225 1.3061 0.6450
MIN 1.4121 1.6385 1.7789 1.3487 64.7960 0.1986 0.5643 0.1897
MAX 17.2491 31.5796 32.1298 53.2028 2002.6788 5.4763 4.3412 2.7929
FACTOR 15.877x 9.645x 9.330x 11.185x 661.479x 1.313x 1.901x 1.000x

Notes:

Last Run on: 29.09.2026
Intel(R) Core(TM) i7-1065G7 CPU @ 1.30GHz (1.50 GHz) with 16.0 GB RAM
Windows 11 Home
Python Version: 3.14.7
numpy Version: 2.4.6
scipy Version: 1.18.0
cybrentq Version: 0.1.5 - by Gledis Caushaj (https://github.com/gledi-ai/cybrentq)
modAB_ct: pymodab version 1.0.5 from PyPI - the previous implementation with ctypes
modAB_SG: pymodab version 1.1.1 - the latest implementation of the safeguarded modab as native C extension

Metadata

Release files for pymodab 1.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pymodab 1.1.1
File Size Uploaded Provenance Actions
pymodab-1.1.1.tar.gz 120.6 kB Without provenance Details for pymodab-1.1.1.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for pymodab 1.1.1
File Actions
pymodab-1.1.1-py3-none-any.whl Python 3 none any Details for pymodab-1.1.1-py3-none-any.whl
pymodab-1.1.1-cp38-abi3-win_amd64.whl CPython 3.8 abi3 Windows x86-64 Details for pymodab-1.1.1-cp38-abi3-win_amd64.whl
pymodab-1.1.1-cp38-abi3-musllinux_1_2_x86_64.whl CPython 3.8 abi3 Linux musl 1.2+ x86-64 Details for pymodab-1.1.1-cp38-abi3-musllinux_1_2_x86_64.whl
pymodab-1.1.1-cp38-abi3-musllinux_1_2_aarch64.whl CPython 3.8 abi3 Linux musl 1.2+ ARM64 Details for pymodab-1.1.1-cp38-abi3-musllinux_1_2_aarch64.whl
pymodab-1.1.1-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl CPython 3.8 abi3 Linux glibc 2.17+ ARM64, Linux glibc 2.28+ ARM64 Details for pymodab-1.1.1-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
pymodab-1.1.1-cp38-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl CPython 3.8 abi3 Linux glibc 2.28+ x86-64, Linux glibc 2.5+ x86-64 Details for pymodab-1.1.1-cp38-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
pymodab-1.1.1-cp38-abi3-macosx_10_9_universal2.whl CPython 3.8 abi3 macOS 10.9+ universal2 (ARM64, x86-64) Details for pymodab-1.1.1-cp38-abi3-macosx_10_9_universal2.whl

Total release size: 348.5 kB

Release files / pymodab-1.1.1.tar.gz

Download URL pymodab-1.1.1.tar.gz
Size 120.6 kB
Tags Source
SHA-256 checksum
How to use checksums
9ad331bd2af2f4ca6af5746384d0892d2a3e86335af38e159f1e88d7c64b65ba
BLAKE2b-256 checksum
How to use checksums
16a0cd523e590cf636e7fa74d99505f7876f1a2fedced0da9dfe1fe56988b9f7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.7

Release files / pymodab-1.1.1-py3-none-any.whl

Download URL pymodab-1.1.1-py3-none-any.whl
Size 110.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b6cd03d1920f94d59a7cc4c32539621a9bfa14c208bc9cbc5d4de881731d9198
BLAKE2b-256 checksum
How to use checksums
810928af14f92c553c6c471cc9df53e24965b51b9f1d96ad0a266f5428927b62
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.7

Release files / pymodab-1.1.1-cp38-abi3-win_amd64.whl

Download URL pymodab-1.1.1-cp38-abi3-win_amd64.whl
Size 15.3 kB
Tags CPython 3.8 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
c03d0c5f3bdedc2ec4b193cf5f7577d169082161e765126a2e9f1e66a6091cec
BLAKE2b-256 checksum
How to use checksums
e406a869eff14786555603b9e2b088aa5f708ff574842f0eea31dc1452ede569
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.7

Release files / pymodab-1.1.1-cp38-abi3-musllinux_1_2_x86_64.whl

Download URL pymodab-1.1.1-cp38-abi3-musllinux_1_2_x86_64.whl
Size 21.3 kB
Tags CPython 3.8 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
e190e4fe50d5ed304446181059d62632073570365027c1f85fa54187d7a43d58
BLAKE2b-256 checksum
How to use checksums
dcb3febb7624917bdaca6864f18bb8ff7dee7707766fcadb0fa693b7d7f6592a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.7

Release files / pymodab-1.1.1-cp38-abi3-musllinux_1_2_aarch64.whl

Download URL pymodab-1.1.1-cp38-abi3-musllinux_1_2_aarch64.whl
Size 21.6 kB
Tags CPython 3.8 Linux musl 1.2+ ARM64 abi3
SHA-256 checksum
How to use checksums
f7f7a48174239dae339d51b9050973af655c19b4d352ef8237d329a98209cf9d
BLAKE2b-256 checksum
How to use checksums
85c17626e1380a29202aa5c2ffb3d941ed322ef22cbeee6548c362d256971420
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.7

Release files / pymodab-1.1.1-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl

Download URL pymodab-1.1.1-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Size 21.4 kB
Tags CPython 3.8 Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64 abi3
SHA-256 checksum
How to use checksums
ae08a589fbfea79fb6351f8832e5221ee5f7694754c5aacf3aac8e6aac007a2f
BLAKE2b-256 checksum
How to use checksums
b9ed69d819e24e4e7c3fda94a9dd33ee2afdc336d70407bce793ed30fbc498a4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.7

Release files / pymodab-1.1.1-cp38-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl

Download URL pymodab-1.1.1-cp38-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
Size 20.6 kB
Tags CPython 3.8 Linux glibc 2.28+ x86-64 Linux glibc 2.5+ x86-64 abi3
SHA-256 checksum
How to use checksums
57be8d1728f9ac66021728306e49d854c3346931ab42a076f0151f4c4878c678
BLAKE2b-256 checksum
How to use checksums
78cc91ad135f50f8cdf6e4d8bbad46c6aa7d93669f74e318698e622cdbd84f86
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.7

Release files / pymodab-1.1.1-cp38-abi3-macosx_10_9_universal2.whl

Download URL pymodab-1.1.1-cp38-abi3-macosx_10_9_universal2.whl
Size 17.6 kB
Tags CPython 3.8 abi3 macOS 10.9+ universal2 (ARM64, x86-64)
SHA-256 checksum
How to use checksums
768822fc02f0aa30db8c19984488a2f434349f4dc23694183669d3db6589da41
BLAKE2b-256 checksum
How to use checksums
f9c594de2e13fff597c9c285f7230522a4ecf6eb6bef9161b65a47d06d19eb0e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.7

Security for pymodab 1.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page