This is a C version of the minpack minimization package. It has been derived from the fortran code using f2c and some limited manual editing. Note that you need to link against libf2c to use this version of minpack. Extern "C" linkage permits the package routines to be called from C++. Check ftp://netlib.bell-labs.com/netlib/f2c for the latest f2c version. For general minpack info and test programs, see the accompanying readme.txt and http://www.netlib.org/minpack/.
CMake is the standard build system:
cmake -B build && cmake --build build
and ctest --test-dir build runs the tests. See the project home page for
build options (precision variants, BLAS/LAPACK, shared libraries). A plain
Makefile is also provided for backward compatibility: type make to compile
and make install to install in /usr/local, or modify the Makefile to suit
your needs.
Manolis Lourakis -- lourakis at ics forth gr, July 2002 Institute of Computer Science, Foundation for Research and Technology - Hellas Heraklion, Crete, Greece
Repackaging by Frederic Devernay -- frederic dot devernay at m4x dot org
The project home page is at http://devernay.github.io/cminpack
include/cminpackcpp.hpp is a header-only C++
wrapper (issue #74). The C API takes the user callback as a plain function
pointer plus an opaque void *p for user data, which a capturing lambda, a
functor, or a std::function cannot satisfy. The wrapper adds overloads in
namespace cminpack that accept any callable whose signature matches the C
callback minus the leading void *p; the callable is forwarded through the
void *p slot by a small template trampoline, so no global state is needed. It
adds no allocation and no virtual dispatch, and the callable only has to outlive
the solver call.
The wrapped entry points are hybrd1/hybrd and hybrj1 (nonlinear
equations), and lmdif1/lmdif, lmder1/lmder and lmstr1/lmstr (least
squares). Every argument after the callable is identical to the C function — you
just drop the (fcn, p) pair and pass your callable first:
#include <cminpackcpp.hpp>
#include <vector>
std::vector<double> y = /* measured data */;
// signature = the C callback minus the leading void *p
auto residual = [&](int m, int n, const double *x, double *fvec, int iflag) {
for (int i = 0; i < m; ++i)
fvec[i] = model(x, i) - y[i]; // captures y, no global needed
return 0;
};
int info = cminpack::lmdif1(residual, m, n, x, fvec, tol, iwa, wa, lwa);A class member function works too, as long as it is wrapped in a callable
that supplies the instance — a lambda capturing this (or the object) is the
simplest, and std::bind/std::function also work. A bare pointer-to-member
(&Class::residual) is not itself callable, so it must be wrapped:
struct LineModel {
std::vector<double> y;
int residual(int m, int n, const double *x, double *fvec, int iflag) const {
for (int i = 0; i < m; ++i) fvec[i] = model(x, i) - y[i];
return 0;
}
};
LineModel obj = /* ... */;
auto cb = [&obj](int m, int n, const double *x, double *fvec, int iflag) {
return obj.residual(m, n, x, fvec, iflag); // supplies the instance
};
int info = cminpack::lmdif1(cb, m, n, x, fvec, tol, iwa, wa, lwa);
// std::bind is equivalent:
// auto cb = std::bind(&LineModel::residual, &obj, _1, _2, _3, _4, _5);The header is precision-agnostic: like cminpack.h it selects the real type via
__cminpack_real__, so defining __cminpack_float__ (or the long-double macro)
before including it targets that variant — link against the matching cminpack
library. A worked example exercising a capturing lambda, a stateful functor and
a std::function is in examples/tcppwrap.cpp.
Two test routes are available:
- CMake / CTest (recommended): after building, run
ctest --test-dir build. This runs the standard example tests (compared againstexamples/ref/*.refwith the dependency-free C toolcmpfiles), the self-checking regression tests, the intensive driver programs as smoke tests (run to completion, no NaN), and — when Python 3 is available — the FORTRAN-reference cross-check (see below). Set-DCMINPACK_CROSSCHECK=OFFto disable that cross-check. - Makefile:
make checkruns the standard tests for the double, long double and float builds, thenmake crosscheck. The double standard tests are strict (a failure fails the build); the long double and float tests are informational.
The cross-check (examples/crosscheck.py, and the CMake crosscheck_* tests)
is a regression gate against the original FORTRAN MINPACK: on the intensive
driver problems, cminpack must converge on every problem FORTRAN converges on.
It compares against committed FORTRAN reference outputs
(examples/ref/*.fortran.ref), so no Fortran compiler is needed. Where
FORTRAN itself does not converge (the problems pushed from 10*x0/100*x0
starting points), a different result is accepted — pure-C and f2c, like
different compilers, take different (equally valid) iteration paths there, for
the reasons in the next section. Iteration-count and last-digit differences
never fail the build.
Python 3 is optional. It is not needed to build cminpack, nor for the
standard or smoke tests (which use cmpfiles); only the cross-check uses it
(via examples/crosscheck.py and examples/driver_check.py). When Python 3 is
missing, both build systems skip only that cross-check — printing a disclaimer
that coverage is incomplete — and run everything else.
On the difficult test problems (the Moré/Garbow/Hillstrom functions exercised
by the intensive driver programs examples/*drv*), cminpack and the original
FORTRAN MINPACK can report different iteration, function- and
Jacobian-evaluation counts, and last-digit differences in the results. This
is expected and harmless: the problems still converge to equally valid
solutions. Test messages reporting such differences are normal, not a sign of
a broken build.
The difficult test problems themselves are from Moré, Garbow & Hillstrom,
Testing Unconstrained Optimization Software, ACM TOMS 7(1):17-41 (1981)
(doi:10.1145/355934.355936; free
open-access technical report ANL-AMD-TM-324:
https://www.osti.gov/servlets/purl/6650344), and the companion Algorithm 566,
ACM TOMS 7(1):136-140 (1981)
(doi:10.1145/355934.355943). They are
defined in examples/ssqfcn.c (least squares) and examples/vecfcn.c (systems
of equations); the driver programs run each one from progressively harder
starting points (x0, 10*x0, 100*x0), so the hardest problems (e.g.
problem 10, the Meyer function) are deliberately pushed to non-convergence.
The differences do not come from the algorithm:
dpmparreturns identical machine constants on both sides, so the convergence tolerance is the same.- cminpack's own pure C (
src/) is a cleaned-up rewrite of the f2c output (src/f2c/); the two agree on well-conditioned problems, but the cleanup regrouped some expressions, so the compiler can contract FMAs differently in each — meaning even these two can reach different (equally valid) results on the hardest driver problems. - The dominant cause is floating-point contraction:
gccandgfortranfusea*b + cinto a fused multiply-add (FMA) at different places, so intermediate values differ by one unit in the last place (ULP). On ill-conditioned problems a single ULP early in the iteration can flip a trust-region accept/reject decision, and the two runs then follow different paths to (equally valid) results. Compiling both sides with-ffp-contract=offremoves most of the divergence.
(The enorm scaling constants rdwarf/rgiant, which cminpack tunes to the
IEEE range rather than MINPACK's 1980 values, are a separate and minor effect:
they only change the norm of out-of-range vectors in the last bit. See
src/enorm.c for the full explanation.)
Because of this, examples/crosscheck.py and the CMake crosscheck_* tests are
a regression gate against the original FORTRAN MINPACK: on the intensive
driver problems, cminpack must converge on every problem FORTRAN converges on
(compared against the committed examples/ref/*.fortran.ref, so no Fortran
compiler is needed). Following the original MINPACK drivers, a problem is gated
only where FORTRAN converged (exit parameter info < 5); where FORTRAN itself
does not converge (info >= 5) a different result is accepted. On a gated
problem the build fails if either its own solver reports non-convergence
(info >= 5) or FORTRAN drove the residual to ~0 but this build did not (which
catches a genuine divergence the exit code alone would miss). Iteration-count
and last-digit differences are reported for information only and never fail the
build. A handful of deliberately-extreme
problems have compiler-dependent, coin-flip convergence (FORTRAN itself
converges on them only at some optimization levels); those are listed, with the
rationale, in examples/crosscheck_exclude.txt
and skipped by the gate. USE_BLAS/USE_LAPACK builds (double or single
precision only) take a genuinely different numeric path — a BLAS dnrm2 in
enorm, BLAS dot/trsv/swap/rot in lmpar/qrsolv, and above all a
LAPACK geqp3/geqrf QR factorization with different column pivoting (a
different algorithm, not merely a last-bit FMA effect). They can flip a
different, implementation-dependent set of problems, so they get an additional
list,
examples/crosscheck_exclude_blas.txt,
applied only when those options are on.
-
version 1.3.14 (25/07/2026):
- Fix spurious
make checkfailures on the intensive driver tests (#78): the non-portable driver-vs-reference text comparison was dropped. Driver validation is now a regression gate against the original FORTRAN MINPACK — cminpack (pure C and f2c) must converge on every driver problem the committed reference (examples/ref/*.fortran.ref) converges on, so no Fortran compiler is needed. Iteration-count and last-digit differences (compiler FMA) never fail the build. - Add user-maintained exclusion lists for the few deliberately-extreme
coin-flip problems (FORTRAN itself converges on them only at some
optimization levels):
examples/crosscheck_exclude.txt, plusexamples/crosscheck_exclude_blas.txtforUSE_BLAS/USE_LAPACKbuilds. Each gate failure prints the problem asnprob/dim, the token to add. - Replace
crosscheck.shwithcrosscheck.py; adddriver_check.py(--reference-gate) andcrosscheck_matrix.sh(an optimization-level diagnostic). Wire the cross-check into CMake/CTest (CMINPACK_CROSSCHECK); Python 3 is optional (only the cross-check needs it). - Fix a compile error in
examples/tenorm_.c(passdpmpar_its index by pointer, the FORTRAN/f2c calling convention). - Document the numerical differences from FORTRAN MINPACK and correct the
enorm.ccomments (the divergence is FMA, not the rdwarf/rgiant constants).
- Fix spurious
-
version 1.3.13 (16/07/2026):
- Fix a division by zero in
covar1when the Jacobian rank equals the number of residuals (m == rank, e.g. square full-rank problems), which produced Inf/NaN throughout the covariance matrix - Make the banded finite-difference branch of
fdjac1call the user function with iflag=2, like the dense branch,fdjac2and the FORTRAN version - Fix the
USE_BLASNewton correction inlmparto use all n components (it was truncated to the original Jacobian rank, giving a wrong step for rank-deficient problems) - Fix the jpvt memset size in the
USE_LAPACKqrfac, and make the work-array size checks inhybrd,hybrj,hybrd1,hybrj1andlmdif1overflow-safe (also in the f2c versions) - Guard a harmless transient infinity in
doglegfor rank-deficient Jacobians (also in the f2c version) - Add a
USE_LAPACKCMake option to build the LAPACK-based QR factorization (qrfac), which was previously only reachable through theMakefile - Exercise the BLAS and LAPACK builds in CI and run the full test suite
(including
tlmdifc) for them; add the intensive driver programs (lmddrvc,lmfdrvc,lmsdrvc,hyjdrvc,hybdrvc,chkdrvc) as smoke tests and run the FORTRAN example tests in CI
- Fix a division by zero in
-
version 1.3.12 (16/07/2026):
- Fix non-convergence/NaN in
lmder,lmdifandlmstron problems whose solution is the zero vector, by guarding a 0/0 division inlmpar#76 - Compare test output using a numeric tolerance instead of an exact text match, so the tests pass across compilers and math libraries #37 #77
- Fix Windows linking: correct the DLL export/import macros and document
that static-library users define
CMINPACK_NO_DLL#18 - Detect and link the CBLAS interface when
USE_BLASis enabled #12 - Add
cminpackcpp.hpp, a header-only C++ wrapper so the solvers accept lambdas, functors andstd::function#74 - Make CMake the standard build system (the
Makefileis kept for backward compatibility) and remove the unmaintained Xcode, Visual Studio and Eclipse project files (cminpack.xcodeproj,cminpack*.vcproj/.vcxproj,cminpack.sln,.cproject,.project) - Move CI to GitHub Actions (keeping the CMake-based AppVeyor build) and remove the obsolete Travis CI, Coveralls and Coverity configuration and badges
- Fix non-convergence/NaN in
-
version 1.3.11 (13/09/2024):
- Bump installed version number to 1.3.11 #75
-
version 1.3.10 (11/09/2024):
-
version 1.3.9 (28/05/2024):
-
version 1.3.8 (09/02/2021):
-
version 1.3.7 (09/12/2020):
-
version 1.3.6 (24/02/2017):
-
version 1.3.5 (28/05/2016):
- Add support for compiling a long double version (Makefile only).
- CMake: static libraries now have the suffix
_s.
-
version 1.3.4 (28/05/2014):
- Add FindCMinpack.cmake cmake module. If you use the cmake install,
finding CMinpack from your
CMakeLists.txtis as easy asfind_package(CMinpack).
- Add FindCMinpack.cmake cmake module. If you use the cmake install,
finding CMinpack from your
-
version 1.3.3 (04/02/2014):
- Add documentation and examples abouts how to add box constraints to the variables.
- continuous integration https://travis-ci.org/devernay/cminpack
-
version 1.3.2 (27/10/2013):
- Minor change in the CMake build: also set
SOVERSION.
- Minor change in the CMake build: also set
-
version 1.3.1 (02/10/2013):
- Fix CUDA examples compilation, and remove non-free files.
-
version 1.3.0 (09/06/2012):
- Optionally use LAPACK and CBLAS in lmpar, qrfac, and qrsolv. Added
make lapackto build the LAPACK-based cminpack and "make checklapack" to test it (results of the test may depend on the underlying LAPACK and BLAS implementations). On 64-bits architectures, the preprocessor symbol__LP64__must be defined (seecminpackP.h) if the LAPACK library uses the LP64 interface (i.e. 32-bits integer, vhereas the ILP interface uses 64 bits integers).
- Optionally use LAPACK and CBLAS in lmpar, qrfac, and qrsolv. Added
-
version 1.2.2 (16/05/2012):
- Update Makefiles and documentation (see "Using CMinpack" above) for easier building and testing.
-
version 1.2.1 (15/05/2012):
- The library can now be built as double, float or half
versions. Standard tests in the "examples" directory can now be
lauched using
make check(to run common tests, including against the float version),make checkhalf(to test the half version) andmake checkfail(to run all the tests, even those that fail).
- The library can now be built as double, float or half
versions. Standard tests in the "examples" directory can now be
lauched using
-
version 1.2.0 (14/05/2012):
- Added original FORTRAN sources for better testing (type
make -C fortran, thenmake -C examplesand follow the instructions). Added driver testslmsdrv,chkdrv,hyjdrv,hybdrv.make -C examples alltestwill run all possible test combinations (make sure you have gfortran installed).
- Added original FORTRAN sources for better testing (type
-
version 1.1.5 (04/05/2012):
- cminpack now works in CUDA, thanks to Jordi Bataller Mascarell, type
make -C cuda(be careful, though: this is a straightforward port from C, and each problem is solved using a single thread). cminpack can now also be compiled with single-precision floating point computation (define__cminpack_real__to float when compiling and using the library). Fix cmake support forCMINPACK_LIB_INSTALL_DIR. Update the reference files for tests.
- cminpack now works in CUDA, thanks to Jordi Bataller Mascarell, type
-
version 1.1.4 (30/10/2011):
- Translated all the Levenberg-Marquardt code (
lmder,lmdif,lmstr,lmder1,lmdif1,lmstr1,lmpar,qrfac,qrsolv,fdjac2,chkder) to use C-style indices.
- Translated all the Levenberg-Marquardt code (
-
version 1.1.3 (16/03/2011):
- Minor fix: Change non-standard
strnstr()tostrstr()ingenf77tests.c.
- Minor fix: Change non-standard
-
version 1.1.2 (07/01/2011):
- Fix Windows DLL building (David Graeff) and document covar in cminpack.h.
-
version 1.1.1 (04/12/2010):
- Complete rewrite of the C functions (without trailing underscore in the function name). Using the original FORTRAN code, the original algorithms structure was recovered, and many goto's were converted to if...then...else. The code should now be both more readable and easier to optimize, both for humans and for compilers. Added lmddrv and lmfdrv test drivers, which test a lot of difficult functions (these functions are explained in Testing Unconstrained Optimization Software by Moré et al.). Also added the pkg-config files to the cmake build, as well as an "uninstall" target, contributed by Geoffrey Biggs.
-
version 1.0.4 (18/10/2010):
- Support for shared library building using CMake, thanks to Goeffrey
Biggs and Radu Bogdan Rusu from Willow Garage. Shared libraries can be
enabled using cmake options, as in:
cmake -DUSE_FPIC=ON -DBUILD_SHARED_LIBS=ON -DBUILD_EXAMPLES=OFF path_to_sources
- Support for shared library building using CMake, thanks to Goeffrey
Biggs and Radu Bogdan Rusu from Willow Garage. Shared libraries can be
enabled using cmake options, as in:
-
version 1.0.3 (18/03/2010):
- Added CMake support.
- XCode build is now Universal.
- Added
tfdjac2_andtfdjac2cexamples, which test the accuracy of a finite-differences approximation of the Jacobian. - Bug fix in
tlmstr1(signaled by Thomas Capricelli).
-
version 1.0.2 (27/02/2009):
- Added Xcode and Visual Studio project files
-
version 1.0.1 (17/12/2007):
- bug fix in
covar()andcovar_(), the computation of tolr caused a segfault (signaled by Timo Hartmann).
- bug fix in
-
version 1.0.0 (24/04/2007):
- Added FORTRAN and C examples
- Added documentation from Debian man pages
- Wrote pure C version
- Added
covar()andcovar_(), and use it intlmdef/tlmdif