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 functiondouble f(double)x1,x2: Bracket interval endpoints (must satisfyf(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.
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.
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 methodbrentq- 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_rootcybrentq- Cython implementation of brentq by Gledis CaushajmodAB- Modified Anderson Bjork's method (Ganchovski & Traykov, 2023; improved 2026)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 |
|---|---|---|---|---|---|---|---|---|
| SUM | 4464 | 2571 | 2534 | 3177 | 1891 | 2571 | 1746 | 1746 |
| AVG | 48 | 28 | 27 | 34 | 20 | 28 | 19 | 19 |
| MEDIAN | 49 | 12 | 12 | 16 | 12 | 12 | 12 | 12 |
| MIN | 3 | 4 | 4 | 3 | 3 | 4 | 3 | 3 |
| MAX | 53 | 102 | 102 | 202 | 58 | 102 | 55 | 55 |
| FACTOR | 2.557x | 1.473x | 1.451x | 1.820x | 1.083x | 1.473x | 1.000x | 1.000x |
Execution times (ms per problem, 100 iterations)
| Func | bisect | brentq | brenth | ridder | chandr | cybrentq | modAB_ct | modAB |
|---|---|---|---|---|---|---|---|---|
| SUM | 1359.38 | 946.80 | 795.71 | 928.54 | 50164.55 | 103.09 | 145.35 | 75.77 |
| Func | bisect | brentq | brenth | ridder | chandr | cybrentq | modAB_ct | modAB |
| AVG | 14.6170 | 10.1806 | 8.5561 | 9.9843 | 539.4037 | 1.1085 | 1.5629 | 0.8147 |
| MEDIAN | 14.1612 | 4.7324 | 4.5651 | 5.9825 | 307.2908 | 0.5875 | 1.2580 | 0.6201 |
| MIN | 2.1026 | 2.5171 | 1.7910 | 1.4065 | 84.3124 | 0.2047 | 0.5414 | 0.1632 |
| MAX | 55.4387 | 78.7136 | 32.4967 | 52.4362 | 1574.8965 | 5.4855 | 4.2678 | 2.8956 |
| FACTOR | 17.941x | 12.496x | 10.502x | 12.255x | 662.085x | 1.361x | 1.918x | 1.000x |
Notes:
Last Run on: 18.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 - the previous implementation with ctypes
modAB: pymodab version 1.0.7 - the latest implementation as native C extension
Release files for pymodab 1.0.7
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pymodab-1.0.7.tar.gz | 114.6 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| pymodab-1.0.7-py3-none-any.whl | Python 3 | none | any | Details |
| pymodab-1.0.7-cp38-abi3-win_amd64.whl | CPython 3.8 | abi3 | Windows x86-64 | Details |
| pymodab-1.0.7-cp38-abi3-musllinux_1_2_x86_64.whl | CPython 3.8 | abi3 | Linux musl 1.2+ x86-64 | Details |
| pymodab-1.0.7-cp38-abi3-musllinux_1_2_aarch64.whl | CPython 3.8 | abi3 | Linux musl 1.2+ ARM64 | Details |
| pymodab-1.0.7-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl | CPython 3.8 | abi3 | Linux glibc 2.28+ ARM64, Linux glibc 2.17+ ARM64 | Details |
| pymodab-1.0.7-cp38-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl | CPython 3.8 | abi3 | Linux glibc 2.5+ x86-64, Linux glibc 2.28+ x86-64 | Details |
| pymodab-1.0.7-cp38-abi3-macosx_10_9_universal2.whl | CPython 3.8 | abi3 | macOS 10.9+ universal2 (ARM64, x86-64) | Details |
Total release size: 327.6 kB
Release files / pymodab-1.0.7.tar.gz
| Download URL | pymodab-1.0.7.tar.gz |
|---|---|
| Size | 114.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3b3349b3aa1382c04f8e8487e1838b027417144e13bef69305c191ae4cf0ce5c
|
|
BLAKE2b-256 checksum How to use checksums |
5eb8e3794a87603ff3b8a2b6bd8afbde1bd944fa4e6b07b7fb05982897d2ec45
|
| 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.0.7-py3-none-any.whl
| Download URL | pymodab-1.0.7-py3-none-any.whl |
|---|---|
| Size | 107.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d5e6e7ecef4ccc9310e3dd4baf5736dad38cfdaffe303b70614b0af87aedf619
|
|
BLAKE2b-256 checksum How to use checksums |
d9a11bfc7a4ff40e6876e5e8e2533517c06bd507904dffe6e7bb0e1193501ae7
|
| 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.0.7-cp38-abi3-win_amd64.whl
| Download URL | pymodab-1.0.7-cp38-abi3-win_amd64.whl |
|---|---|
| Size | 13.9 kB |
| Tags | CPython 3.8 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
5773be87de70f899cd1a125b3ddad8fdccdf9327a5fa71a6b80b2905caba1dc5
|
|
BLAKE2b-256 checksum How to use checksums |
e3799bc6beb4ee75916f445719fc1aedae92c56a97e08d3e03848190caeb6410
|
| 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.0.7-cp38-abi3-musllinux_1_2_x86_64.whl
| Download URL | pymodab-1.0.7-cp38-abi3-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 18.7 kB |
| Tags | CPython 3.8 Linux musl 1.2+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
2008fc6769b70347f427363d35e34406b27e855f11b30ff81ddcd3de155e668d
|
|
BLAKE2b-256 checksum How to use checksums |
3561bdc15ef5b6096770c5bede3fffb2b50b1b86da26c8676fd0c6ebcde18597
|
| 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.0.7-cp38-abi3-musllinux_1_2_aarch64.whl
| Download URL | pymodab-1.0.7-cp38-abi3-musllinux_1_2_aarch64.whl |
|---|---|
| Size | 19.1 kB |
| Tags | CPython 3.8 Linux musl 1.2+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
7cbc21160524d50b45b079d260be139bf81036dc25af2b2a1dbdf4abffc23ba6
|
|
BLAKE2b-256 checksum How to use checksums |
d70828cf738af0723529563c4cdda495c027625ef11c255e74763fc7ecdc1327
|
| 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.0.7-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
| Download URL | pymodab-1.0.7-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl |
|---|---|
| Size | 19.5 kB |
| Tags | CPython 3.8 Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
e95057404ae8994a0927da121bc7a52c9d705794f5625cfd4fcc49778cd8da0e
|
|
BLAKE2b-256 checksum How to use checksums |
d6b79825c87504a5cc61d61b3c20609590a268deec95153200aa30da1160e326
|
| 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.0.7-cp38-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
| Download URL | pymodab-1.0.7-cp38-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl |
|---|---|
| Size | 18.7 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 |
8aca65d899b86cc63bea57d415d97eb08b6073ca805b9b4080a17026ffac1bb5
|
|
BLAKE2b-256 checksum How to use checksums |
50545301279f56ad25f490fe805350ee01e1a07284a112ccda5d349ed72de88f
|
| 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.0.7-cp38-abi3-macosx_10_9_universal2.whl
| Download URL | pymodab-1.0.7-cp38-abi3-macosx_10_9_universal2.whl |
|---|---|
| Size | 15.7 kB |
| Tags | CPython 3.8 abi3 macOS 10.9+ universal2 (ARM64, x86-64) |
|
SHA-256 checksum How to use checksums |
155cca0c44f1c5467311328dca2a5894040d7085e951355794043e3d6fc440ae
|
|
BLAKE2b-256 checksum How to use checksums |
b32a3d53e03c5fbbff04f2920fa5b382a147f2a8cbd99c64b38c088e0005573d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.7
|