| title | Build and Validate MINPACK with PRIK |
|---|---|
| audience | users, advanced users |
| prerequisites | arrays, callbacks, packaging |
| related | fftpack-wrapper.md, ../guide/arrays.md, ../guide/callbacks.md |
| status | maintained |
| publication | reviewed |
This example takes the checked-in fortran-lang/minpack source and builds an importable Python extension containing all 22 public MINPACK procedures.
The example solves known nonlinear and least-squares problems and checks their results with exact solutions and direct linear-algebra identities.
- Wrap a complete numerical solver library as one Python extension.
- Pass NumPy arrays and ordinary Python functions to MINPACK routines.
- Check root-finding, least-squares, Jacobian, and factorization results.
You should already be comfortable with NumPy arrays, Python callables, and building a local Fortran extension.
| Component | Version / source |
|---|---|
| PRIK | current repository checkout |
| MINPACK | fortran-lang/minpack commit c0b5aea |
| Python | 3.12 in the dedicated CI job |
| NumPy | 2.5.1 |
| Fortran compiler | GNU Fortran 13 in CI; a compatible gfortran works locally |
The repository owns the checked-in source snapshot under
examples/minpack/native/, so the example does not download code during its
build.
Clone PRIK, create a virtual environment, and install the Python tools used by the dedicated CI job:
git clone https://github.com/PyNumLab/prik.git
cd prik
python3 -m venv .venv
. .venv/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install -e ".[qa]" "numpy==2.5.1"Install GNU Fortran separately. On Ubuntu:
sudo apt-get update
sudo apt-get install --yes gfortran
gfortran --versionAll remaining commands run from the repository root with the virtual
environment active. The complete runnable project lives under
examples/minpack/.
MINPACK keeps its public declarations and implementations in one source file, so one command can generate the wrapper and compile the library:
export EXAMPLE_WORKSPACE="$PWD"
export MINPACK_BUILD_ROOT="$(mktemp -d)"
mkdir -p "$MINPACK_BUILD_ROOT/prik/generated"
cd "$MINPACK_BUILD_ROOT/prik"
python3 -m prik "$EXAMPLE_WORKSPACE/examples/minpack/native/minpack.f90" \
--out prik_reference_minpack \
--out-dir "$MINPACK_BUILD_ROOT/prik/generated" \
--compiler "$(command -v gfortran)" \
--jobs 8 \
--wrapper-fortran-flags="-O0 -g0" \
--wrapper-c-flags="-O0 -g0"The example uses -O0 so the tests focus on correct results. PRIK compiles the
native source and generated bridge into one extension.
For normal use, source the convenience entrypoint:
source examples/minpack/build_all.shIt builds the extension and exports its directory on PYTHONPATH for the
current shell.
MINPACK routines keep their documented argument order, including work arrays and status values. Pass NumPy arrays with the generated dtype, shape, and layout. Solver callbacks are ordinary Python functions with the generated callback signature.
After the build finishes, run:
python3 -m pytest -q examples/minpack/testsThe tests cover all 22 public procedures:
| Family | Procedures |
|---|---|
| Diagnostics and finite differences | 4 |
| Hybrid nonlinear solvers | 4 |
| Levenberg-Marquardt solvers | 6 |
| Factorization and update helpers | 8 |
| Total | 22 |
Each procedure is called with representative data and checked against SciPy, a known solution, or a direct linear-algebra result.
For example, hybrd1 can solve the two-variable equation
x - [1, -2] = 0. MINPACK calls the Python function whenever it needs the
current residual. The example below is the runnable hybrd1 test; its
minpack fixture supplies the generated module:
def test_hybrd1(minpack):
target = np.array([1.0, -2.0], dtype=np.float64)
callback_calls = 0
def residual(_count, x, fvec, _iflag):
nonlocal callback_calls
callback_calls += 1
fvec[:] = x - target
x = np.array([4.0, 4.0], dtype=np.float64)
fvec = np.empty(2, dtype=np.float64)
info = minpack.hybrd1(
residual,
np.int32(2),
x,
fvec,
np.float64(1.0e-12),
np.empty(19, dtype=np.float64),
np.int32(19),
)
assert info == np.int32(1)
assert callback_calls > 0
np.testing.assert_allclose(x, target, atol=1.0e-10)
np.testing.assert_allclose(fvec, 0.0, atol=1.0e-10)The complete suite applies the same pattern to root-finding and least-squares solvers, then checks their solutions and final residuals against the declared problem.
After building the extension, run a family or one routine:
python3 -m pytest -q examples/minpack/tests/test_solvers.py
python3 -m pytest -q \
examples/minpack/tests/test_solvers.py::test_hybrd1- Callback-driven nonlinear solvers →
test_solvers.py - Diagnostics and finite-difference helpers →
test_diagnostics.py - Factorization and update helpers →
test_linear_algebra.py - Public routine list →
routine_inventory.py - Routine coverage check →
test_routine_coverage.py - Copyable project instructions →
examples/minpack/README.md
- Confirm that
gfortranis available onPATH. - Use
source examples/minpack/build_all.sh; executing it in a child shell does not preserve the exportedPYTHONPATH. - Start with one helper or solver test and add
-vv -swhen diagnosing a callback or generated-wrapper failure.
examples/minpack/native/minpack.f90
matches the upstream src/minpack.f90 at
fortran-lang/minpack commit c0b5aea9fcd2b83865af921a7a7e881904f8d3c2.
See the upstream repository, its API documentation, and its license before redistributing the bundled native source.