c245cf4
From facb9273c571b6bef430e71b31ff229abd6d1a46 Mon Sep 17 00:00:00 2001
c245cf4
From: Mark Abraham <mark.j.abraham@gmail.com>
c245cf4
Date: Mon, 11 Jun 2018 08:30:19 +0200
c245cf4
Subject: [PATCH] Bump lmfit support to version 7
c245cf4
c245cf4
The breaking API change means that distributions will not be able to
c245cf4
build GROMACS reliably with support for lmfit of arbitrary versions.
c245cf4
Nor does lmfit provide any support for querying the version. Tools
c245cf4
that call such fitting will now issue a fatal error.
c245cf4
c245cf4
Updated the FindLmfit and other cmake code to make better use of
c245cf4
modern cmake idioms for managing build targets. lmfit support is now
c245cf4
handled by a tri-state GMX_USE_LMFIT cmake variable, which defaults to
c245cf4
using the bundled version.
c245cf4
c245cf4
Reorganized aspects of gmx_lmcurve to better encapsulate the
c245cf4
dependency, now that we have to support the absence of lmfit.
c245cf4
c245cf4
Updated install guide and COPYING file.
c245cf4
c245cf4
Refs #2533
c245cf4
c245cf4
Change-Id: I6b14e08be216f803326b0ad9215b8d89bb0962c1
c245cf4
---
c245cf4
c245cf4
diff --git a/COPYING b/COPYING
c245cf4
index 4cc52a2..ba2710e 100644
c245cf4
--- a/COPYING
c245cf4
+++ b/COPYING
c245cf4
@@ -1249,7 +1249,7 @@
c245cf4
 --
c245cf4
   Copyright (c) 1980-1999 University of Chicago,
c245cf4
                           as operator of Argonne National Laboratory
c245cf4
-  Copyright (c) 2004-2013 Joachim Wuttke, Forschungszentrum Juelich GmbH
c245cf4
+  Copyright (c) 2004-2015 Joachim Wuttke, Forschungszentrum Juelich GmbH
c245cf4
 
c245cf4
   All rights reserved.
c245cf4
 
c245cf4
diff --git a/cmake/FindLmfit.cmake b/cmake/FindLmfit.cmake
c245cf4
index 5bf489a..9dd23f1 100644
c245cf4
--- a/cmake/FindLmfit.cmake
c245cf4
+++ b/cmake/FindLmfit.cmake
c245cf4
@@ -1,7 +1,7 @@
c245cf4
 #
c245cf4
 # This file is part of the GROMACS molecular simulation package.
c245cf4
 #
c245cf4
-# Copyright (c) 2016, by the GROMACS development team, led by
c245cf4
+# Copyright (c) 2016,2018, by the GROMACS development team, led by
c245cf4
 # Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
c245cf4
 # and including many others, as listed in the AUTHORS file in the
c245cf4
 # top-level source directory and at http://www.gromacs.org.
c245cf4
@@ -32,19 +32,20 @@
c245cf4
 # To help us fund GROMACS development, we humbly ask that you cite
c245cf4
 # the research papers on the package. Check out http://www.gromacs.org.
c245cf4
 
c245cf4
-# This package tries to find an external lmfit library. It is intended
c245cf4
-# to work with pkg-config, because that is the mechanism supported in
c245cf4
-# lmfit. Upon exit, the following variables may be set:
c245cf4
+# This package tries to find an external lmfit library, version
c245cf4
+# 7. Note that pkg-config support was removed before version 7, so is
c245cf4
+# no longer supported here. Upon exit, the following variables may be
c245cf4
+# set:
c245cf4
 #
c245cf4
 # LMFIT_FOUND       - lmfit was found
c245cf4
 # LMFIT_INCLUDE_DIR - lmfit include directory
c245cf4
-# LMFIT_LIBRARIES   - lmfit libraries
c245cf4
+# LMFIT_LIBRARY     - lmfit library
c245cf4
 # LMFIT_LINKS_OK    - lmfit libraries link correctly
c245cf4
 # LMFIT_VERSION     - lmfit version string as "major.minor"
c245cf4
 #
c245cf4
-# If you cannot use pkg-config for some reason, then setting
c245cf4
-# LMFIT_INCLUDE_DIRS and LMFIT_LIBRARY_DIRS on the cmake command line
c245cf4
-# to suitable values will work.
c245cf4
+# CMake will search the CMAKE_PREFIX_PATH in the usual way, but if you
c245cf4
+# need more control then setting LMFIT_INCLUDE_DIR and LMFIT_LIBRARY
c245cf4
+# on the cmake command line to suitable values will work.
c245cf4
 
c245cf4
 include(CMakePushCheckState)
c245cf4
 cmake_push_check_state()
c245cf4
@@ -55,12 +56,12 @@
c245cf4
         # lmfit doesn't support CMake-based find_package version
c245cf4
         # checking in 6.1, so this code does nothing.
c245cf4
         if(LMFIT_FIND_VERSION_EXACT)
c245cf4
-            pkg_check_modules(PC_LMFIT lmfit=${LMFIT_FIND_VERSION})
c245cf4
+            pkg_check_modules(PC_LMFIT QUIET lmfit=${LMFIT_FIND_VERSION})
c245cf4
         else()
c245cf4
-            pkg_check_modules(PC_LMFIT lmfit>=${LMFIT_FIND_VERSION})
c245cf4
+            pkg_check_modules(PC_LMFIT QUIET lmfit>=${LMFIT_FIND_VERSION})
c245cf4
         endif()
c245cf4
     else()
c245cf4
-        pkg_check_modules(PC_LMFIT lmfit)
c245cf4
+        pkg_check_modules(PC_LMFIT QUIET lmfit)
c245cf4
         if (PC_LMFIT_VERSION)
c245cf4
             string(REGEX REPLACE "^([0-9]+):([0-9]+)" "\\1.\\2" LMFIT_VERSION "${PC_LMFIT_VERSION}")
c245cf4
         endif()
c245cf4
@@ -68,20 +69,15 @@
c245cf4
 endif()
c245cf4
 
c245cf4
 # Try to find lmfit, perhaps with help from pkg-config
c245cf4
-find_path(LMFIT_INCLUDE_DIRS lmcurve.h HINTS "${PC_LMFIT_INCLUDE_DIRS}" PATH_SUFFIXES include)
c245cf4
-find_library(LMFIT_LIBRARY_DIRS NAMES lmfit HINTS "${PC_LMFIT_LIBRARY_DIRS}" PATH_SUFFIXES lib64 lib)
c245cf4
+find_path(LMFIT_INCLUDE_DIR lmcurve.h HINTS "${PC_LMFIT_INCLUDE_DIRS}" PATH_SUFFIXES include)
c245cf4
+find_library(LMFIT_LIBRARY NAMES lmfit HINTS "${PC_LMFIT_LIBRARY_DIRS}" PATH_SUFFIXES lib64 lib)
c245cf4
 
c245cf4
 # Make sure we can also link, so that cross-compilation is properly supported
c245cf4
-if (LMFIT_INCLUDE_DIRS AND LMFIT_LIBRARY_DIRS)
c245cf4
+if (LMFIT_INCLUDE_DIR AND LMFIT_LIBRARY)
c245cf4
     include(CheckCXXSourceCompiles)
c245cf4
-    set(CMAKE_REQUIRED_INCLUDES ${LMFIT_INCLUDE_DIRS})
c245cf4
-    set(CMAKE_REQUIRED_LIBRARIES ${LMFIT_LIBRARY_DIRS})
c245cf4
+    set(CMAKE_REQUIRED_INCLUDES ${LMFIT_INCLUDE_DIR})
c245cf4
+    set(CMAKE_REQUIRED_LIBRARIES ${LMFIT_LIBRARY})
c245cf4
     check_cxx_source_compiles("#include <lmcurve.h>\nint main(){lmcurve(0,0,0,0,0,0,0,0);}" LMFIT_LINKS_OK)
c245cf4
-endif()
c245cf4
-
c245cf4
-if (LMFIT_LINKS_OK)
c245cf4
-    set(LMFIT_INCLUDE_DIR ${LMFIT_INCLUDE_DIRS})
c245cf4
-    set(LMFIT_LIBRARIES ${LMFIT_LIBRARY_DIRS})
c245cf4
 endif()
c245cf4
 
c245cf4
 include(FindPackageHandleStandardArgs)
c245cf4
@@ -90,11 +86,19 @@
c245cf4
     LMFIT_FOUND
c245cf4
     REQUIRED_VARS
c245cf4
     LMFIT_INCLUDE_DIR
c245cf4
-    LMFIT_LIBRARIES
c245cf4
+    LMFIT_LIBRARY
c245cf4
     LMFIT_LINKS_OK
c245cf4
     VERSION_VAR
c245cf4
     LMFIT_VERSION)
c245cf4
 
c245cf4
-mark_as_advanced(LMFIT_INCLUDE_DIRS LMFIT_LIBRARY_DIRS)
c245cf4
+mark_as_advanced(LMFIT_INCLUDE_DIR LMFIT_LIBRARY)
c245cf4
+
c245cf4
+if (LMFIT_FOUND)
c245cf4
+    add_library(lmfit INTERFACE IMPORTED)
c245cf4
+    set_target_properties(lmfit PROPERTIES
c245cf4
+        INTERFACE_INCLUDE_DIRECTORIES "${LMFIT_INCLUDE_DIR}"
c245cf4
+        INTERFACE_LINK_LIBRARIES "${LMFIT_LIBRARY}"
c245cf4
+        )
c245cf4
+endif()
c245cf4
 
c245cf4
 cmake_pop_check_state()
c245cf4
diff --git a/cmake/gmxManageLmfit.cmake b/cmake/gmxManageLmfit.cmake
c245cf4
index 182928f..5953a19 100644
c245cf4
--- a/cmake/gmxManageLmfit.cmake
c245cf4
+++ b/cmake/gmxManageLmfit.cmake
c245cf4
@@ -1,7 +1,7 @@
c245cf4
 #
c245cf4
 # This file is part of the GROMACS molecular simulation package.
c245cf4
 #
c245cf4
-# Copyright (c) 2016, by the GROMACS development team, led by
c245cf4
+# Copyright (c) 2016,2018, by the GROMACS development team, led by
c245cf4
 # Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
c245cf4
 # and including many others, as listed in the AUTHORS file in the
c245cf4
 # top-level source directory and at http://www.gromacs.org.
c245cf4
@@ -32,21 +32,16 @@
c245cf4
 # To help us fund GROMACS development, we humbly ask that you cite
c245cf4
 # the research papers on the package. Check out http://www.gromacs.org.
c245cf4
 
c245cf4
-set(GMX_LMFIT_MINIMUM_REQUIRED_VERSION "6.1")
c245cf4
-set(GMX_BUNDLED_LMFIT_DIR "${CMAKE_SOURCE_DIR}/src/external/lmfit")
c245cf4
+# Note that lmfit does not have a stable API, so GROMACS only supports
c245cf4
+# the same version that it bundles.
c245cf4
+set(GMX_LMFIT_REQUIRED_VERSION "7.0")
c245cf4
 
c245cf4
-option(GMX_EXTERNAL_LMFIT "Use external lmfit instead of compiling the version bundled with GROMACS." OFF)
c245cf4
-mark_as_advanced(GMX_EXTERNAL_LMFIT)
c245cf4
+include(gmxOptionUtilities)
c245cf4
 
c245cf4
-macro(manage_lmfit)
c245cf4
-    if(GMX_EXTERNAL_LMFIT)
c245cf4
-        # Find an external lmfit library.
c245cf4
-        find_package(Lmfit ${GMX_LMFIT_MINIMUM_REQUIRED_VERSION})
c245cf4
-        if(NOT LMFIT_FOUND)
c245cf4
-            message(FATAL_ERROR "External lmfit could not be found, please adjust your pkg-config path to include the lmfit.pc file")
c245cf4
-        endif()
c245cf4
-    endif()
c245cf4
-endmacro()
c245cf4
+gmx_option_multichoice(GMX_USE_LMFIT
c245cf4
+    "Use external lmfit instead of compiling the version bundled with GROMACS."
c245cf4
+    INTERNAL
c245cf4
+    INTERNAL EXTERNAL NONE)
c245cf4
 
c245cf4
 macro(get_lmfit_properties LMFIT_SOURCES_VAR LMFIT_LIBRARIES_VAR LMFIT_INCLUDE_DIR_VAR LMFIT_INCLUDE_DIR_ORDER_VAR)
c245cf4
     if (GMX_EXTERNAL_LMFIT)
c245cf4
@@ -62,5 +57,29 @@
c245cf4
     endif()
c245cf4
 endmacro()
c245cf4
 
c245cf4
-manage_lmfit()
c245cf4
+function(manage_lmfit)
c245cf4
+    if(GMX_USE_LMFIT STREQUAL "INTERNAL")
c245cf4
+        set(BUNDLED_LMFIT_DIR "${CMAKE_SOURCE_DIR}/src/external/lmfit")
c245cf4
+        file(GLOB LMFIT_SOURCES ${BUNDLED_LMFIT_DIR}/*.cpp)
c245cf4
 
c245cf4
+        # Create a fake library for lmfit for libgromacs to depend on
c245cf4
+        add_library(lmfit INTERFACE)
c245cf4
+        target_sources(lmfit INTERFACE ${LMFIT_SOURCES})
c245cf4
+        target_include_directories(lmfit INTERFACE
c245cf4
+            $<BUILD_INTERFACE:${BUNDLED_LMFIT_DIR}>)
c245cf4
+        target_link_libraries(libgromacs PRIVATE lmfit)
c245cf4
+
c245cf4
+        set(HAVE_LMFIT_VALUE TRUE)
c245cf4
+    elseif(GMX_USE_LMFIT STREQUAL "EXTERNAL")
c245cf4
+        # Find an external lmfit library.
c245cf4
+        find_package(Lmfit ${GMX_LMFIT_MINIMUM_REQUIRED_VERSION})
c245cf4
+        if(NOT LMFIT_FOUND)
c245cf4
+            message(FATAL_ERROR "External lmfit could not be found, please adjust your pkg-config path to include the lmfit.pc file")
c245cf4
+        endif()
c245cf4
+        target_link_libraries(libgromacs PRIVATE lmfit)
c245cf4
+        set(HAVE_LMFIT_VALUE TRUE)
c245cf4
+    else()
c245cf4
+        set(HAVE_LMFIT_VALUE FALSE)
c245cf4
+    endif()
c245cf4
+    set(HAVE_LMFIT ${HAVE_LMFIT_VALUE} CACHE BOOL "Whether lmfit library support is enabled")
c245cf4
+endfunction()
c245cf4
diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt
c245cf4
index 9b38d75..3f050b5 100644
c245cf4
--- a/docs/CMakeLists.txt
c245cf4
+++ b/docs/CMakeLists.txt
c245cf4
@@ -366,7 +366,7 @@
c245cf4
             REQUIRED_CUDA_COMPUTE_CAPABILITY REGRESSIONTEST_VERSION
c245cf4
             SOURCE_MD5SUM REGRESSIONTEST_MD5SUM_STRING
c245cf4
             GMX_TNG_MINIMUM_REQUIRED_VERSION
c245cf4
-            GMX_LMFIT_MINIMUM_REQUIRED_VERSION
c245cf4
+            GMX_LMFIT_REQUIRED_VERSION
c245cf4
         COMMENT "Configuring Sphinx configuration file")
c245cf4
     gmx_add_sphinx_input_file(${SPHINX_CONFIG_VARS_FILE})
c245cf4
     gmx_add_sphinx_source_files(FILES ${SPHINX_SOURCE_FILES})
c245cf4
diff --git a/docs/conf-vars.py.cmakein b/docs/conf-vars.py.cmakein
c245cf4
index f4c3e02..038014a 100644
c245cf4
--- a/docs/conf-vars.py.cmakein
c245cf4
+++ b/docs/conf-vars.py.cmakein
c245cf4
@@ -1,7 +1,7 @@
c245cf4
 #
c245cf4
 # This file is part of the GROMACS molecular simulation package.
c245cf4
 #
c245cf4
-# Copyright (c) 2015,2016,2017, by the GROMACS development team, led by
c245cf4
+# Copyright (c) 2015,2016,2017,2018, by the GROMACS development team, led by
c245cf4
 # Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
c245cf4
 # and including many others, as listed in the AUTHORS file in the
c245cf4
 # top-level source directory and at http://www.gromacs.org.
c245cf4
@@ -48,5 +48,5 @@
c245cf4
         ('SOURCE_MD5SUM', '@SOURCE_MD5SUM@'),
c245cf4
         ('REGRESSIONTEST_MD5SUM', '@REGRESSIONTEST_MD5SUM_STRING@'),
c245cf4
         ('GMX_TNG_MINIMUM_REQUIRED_VERSION', '@GMX_TNG_MINIMUM_REQUIRED_VERSION@'),
c245cf4
-        ('GMX_LMFIT_MINIMUM_REQUIRED_VERSION', '@GMX_LMFIT_MINIMUM_REQUIRED_VERSION@')
c245cf4
+        ('GMX_LMFIT_REQUIRED_VERSION', '@GMX_LMFIT_REQUIRED_VERSION@')
c245cf4
     ]
c245cf4
diff --git a/docs/install-guide/index.rst b/docs/install-guide/index.rst
c245cf4
index 48fe2c3..5324629 100644
c245cf4
--- a/docs/install-guide/index.rst
c245cf4
+++ b/docs/install-guide/index.rst
c245cf4
@@ -340,10 +340,14 @@
c245cf4
   by setting ``-DGMX_EXTERNAL_TNG=yes``, but TNG
c245cf4
   |GMX_TNG_MINIMUM_REQUIRED_VERSION| is bundled in the |Gromacs|
c245cf4
   source already.
c245cf4
-* An external lmfit library for Levenberg-Marquardt curve fitting
c245cf4
-  can be used by setting ``-DGMX_EXTERNAL_LMFIT=yes``, but lmfit
c245cf4
-  |GMX_LMFIT_MINIMUM_REQUIRED_VERSION| is bundled in the |Gromacs|
c245cf4
-  source already.
c245cf4
+* The lmfit library for Levenberg-Marquardt curve fitting is used in
c245cf4
+  |Gromacs|. Only lmfit |GMX_LMFIT_REQUIRED_VERSION| is supported.  A
c245cf4
+  reduced version of that library is bundled in the |Gromacs|
c245cf4
+  distribution, and the default build uses it. That default may be
c245cf4
+  explicitly enabled with ``-DGMX_USE_LMFIT=internal``. To use an
c245cf4
+  external lmfit library, set ``-DGMX_USE_LMFIT=external``, and adjust
c245cf4
+  ``CMAKE_PREFIX_PATH`` as needed.  lmfit support can be disabled with
c245cf4
+  ``-DGMX_USE_LMFIT=none``.
c245cf4
 * zlib is used by TNG for compressing some kinds of trajectory data
c245cf4
 * Building the |Gromacs| documentation is optional, and requires
c245cf4
   ImageMagick, pdflatex, bibtex, doxygen, python 2.7, sphinx 
c245cf4
diff --git a/src/config.h.cmakein b/src/config.h.cmakein
c245cf4
index b7e5964..d0c3c35 100644
c245cf4
--- a/src/config.h.cmakein
c245cf4
+++ b/src/config.h.cmakein
c245cf4
@@ -377,6 +377,9 @@
c245cf4
 /* Define if we have feenableexcept */
c245cf4
 #cmakedefine01 HAVE_FEENABLEEXCEPT
c245cf4
 
c245cf4
+/* Define if we have lmfit support */
c245cf4
+#cmakedefine01 HAVE_LMFIT
c245cf4
+
c245cf4
 /*! \endcond */
c245cf4
 
c245cf4
 #endif
c245cf4
diff --git a/src/external/lmfit/README b/src/external/lmfit/README
c245cf4
index 3c0557b..4b8d7c6 100644
c245cf4
--- a/src/external/lmfit/README
c245cf4
+++ b/src/external/lmfit/README
c245cf4
@@ -1,5 +1,5 @@
c245cf4
 This directory contains only the barebones version of the
c245cf4
-lmfit package, version 6.1. Full version is available from
c245cf4
+lmfit package, version 7.0. Full version is available from
c245cf4
 http://apps.jcns.fz-juelich.de/doku/sc/lmfit
c245cf4
 
c245cf4
 The license under which lmfit is bundled may be found in the GROMACS
c245cf4
diff --git a/src/external/lmfit/lmmin.cpp b/src/external/lmfit/lmmin.cpp
c245cf4
index eb2d298..813fe5d 100644
c245cf4
--- a/src/external/lmfit/lmmin.cpp
c245cf4
+++ b/src/external/lmfit/lmmin.cpp
c245cf4
@@ -16,40 +16,41 @@
c245cf4
 #include <assert.h>
c245cf4
 #include <stdlib.h>
c245cf4
 #include <stdio.h>
c245cf4
-#include <cmath>
c245cf4
+#include <math.h>
c245cf4
 #include <float.h>
c245cf4
 #include "lmmin.h"
c245cf4
 
c245cf4
-using namespace std;
c245cf4
-
c245cf4
-static double lm_enorm(int n, const double* x);
c245cf4
-
c245cf4
-#define MIN(a, b) (((a) <= (b)) ? (a) : (b))
c245cf4
-#define MAX(a, b) (((a) >= (b)) ? (a) : (b))
c245cf4
-#define SQR(x) (x) * (x)
c245cf4
+#define MIN(a,b) (((a)<=(b)) ? (a) : (b))
c245cf4
+#define MAX(a,b) (((a)>=(b)) ? (a) : (b))
c245cf4
+#define SQR(x)   (x)*(x)
c245cf4
 
c245cf4
 /* Declare functions that do the heavy numerics.
c245cf4
    Implementions are in this source file, below lmmin.
c245cf4
-   Dependences: lmmin calls lmpar, which calls qrfac and qrsolv. */
c245cf4
-static void lm_lmpar(const int n, double* r, const int ldr, const int* Pivot,
c245cf4
-                     const double* diag, const double* qtb, const double delta,
c245cf4
-                     double* par, double* x, double* Sdiag, double* aux, double* xdi);
c245cf4
-static void lm_qrfac(const int m, const int n, double* A, int* Pivot, double* Rdiag,
c245cf4
-                     double* Acnorm, double* W);
c245cf4
-static void lm_qrsolv(const int n, double* r, const int ldr, const int* Pivot,
c245cf4
-                      const double* diag, const double* qtb, double* x,
c245cf4
-                      double* Sdiag, double* W);
c245cf4
+   Dependences: lmmin calls qrfac and lmpar; lmpar calls qrsolv. */
c245cf4
+void lm_lmpar(
c245cf4
+    const int n, double *const r, const int ldr, int *const ipvt,
c245cf4
+    double *const diag, double *const qtb, double delta, double *const par,
c245cf4
+    double *const x,
c245cf4
+    double *const sdiag, double *const aux, double *const xdi);
c245cf4
+void lm_qrfac(
c245cf4
+    const int m, const int n, double *const a, int *const ipvt,
c245cf4
+    double *const rdiag, double *const acnorm, double *const wa );
c245cf4
+void lm_qrsolv(
c245cf4
+    const int n, double *const r, const int ldr, int *const ipvt,
c245cf4
+    double *const diag, double *const qtb, double *const x,
c245cf4
+    double *const sdiag, double *const wa);
c245cf4
 
c245cf4
-/******************************************************************************/
c245cf4
-/*  Numeric constants                                                         */
c245cf4
-/******************************************************************************/
c245cf4
 
c245cf4
-/* Set machine-dependent constants to values from float.h. */
c245cf4
-#define LM_MACHEP DBL_EPSILON       /* resolution of arithmetic */
c245cf4
-#define LM_DWARF DBL_MIN            /* smallest nonzero number */
c245cf4
+/*****************************************************************************/
c245cf4
+/*  Numeric constants                                                        */
c245cf4
+/*****************************************************************************/
c245cf4
+
c245cf4
+/* machine-dependent constants from float.h */
c245cf4
+#define LM_MACHEP     DBL_EPSILON   /* resolution of arithmetic */
c245cf4
+#define LM_DWARF      DBL_MIN       /* smallest nonzero number */
c245cf4
 #define LM_SQRT_DWARF sqrt(DBL_MIN) /* square should not underflow */
c245cf4
 #define LM_SQRT_GIANT sqrt(DBL_MAX) /* square should not overflow */
c245cf4
-#define LM_USERTOL 30 * LM_MACHEP   /* users are recommended to require this */
c245cf4
+#define LM_USERTOL    30*LM_MACHEP  /* users are recommended to require this */
c245cf4
 
c245cf4
 /* If the above values do not work, the following seem good for an x86:
c245cf4
  LM_MACHEP     .555e-16
c245cf4
@@ -65,19 +66,19 @@
c245cf4
  LM_USER_TOL   1.e-14
c245cf4
 */
c245cf4
 
c245cf4
-/* Predefined control parameter sets (msgfile=NULL means stdout). */
c245cf4
 const lm_control_struct lm_control_double = {
c245cf4
-    LM_USERTOL, LM_USERTOL, LM_USERTOL, LM_USERTOL,
c245cf4
-    100., 100, 1, NULL, 0, -1, -1};
c245cf4
+    LM_USERTOL, LM_USERTOL, LM_USERTOL, LM_USERTOL, 100., 100, 1,
c245cf4
+    NULL, 0, -1, -1 };
c245cf4
 const lm_control_struct lm_control_float = {
c245cf4
-    1.e-7, 1.e-7, 1.e-7, 1.e-7,
c245cf4
-    100., 100, 1, NULL, 0, -1, -1};
c245cf4
+    1.e-7,      1.e-7,      1.e-7,      1.e-7,      100., 100, 1,
c245cf4
+    NULL, 0, -1, -1 };
c245cf4
 
c245cf4
-/******************************************************************************/
c245cf4
-/*  Message texts (indexed by status.info)                                    */
c245cf4
-/******************************************************************************/
c245cf4
 
c245cf4
-const char* lm_infmsg[] = {
c245cf4
+/*****************************************************************************/
c245cf4
+/*  Message texts (indexed by status.info)                                   */
c245cf4
+/*****************************************************************************/
c245cf4
+
c245cf4
+const char *lm_infmsg[] = {
c245cf4
     "found zero (sum of squares below underflow limit)",
c245cf4
     "converged  (the relative error in the sum of squares is at most tol)",
c245cf4
     "converged  (the relative error of the parameter vector is at most tol)",
c245cf4
@@ -90,66 +91,86 @@
c245cf4
     "crashed    (not enough memory)",
c245cf4
     "exploded   (fatal coding error: improper input parameters)",
c245cf4
     "stopped    (break requested within function evaluation)",
c245cf4
-    "found nan  (function value is not-a-number or infinite)"};
c245cf4
+    "found nan  (function value is not-a-number or infinite)",
c245cf4
+    "won't fit  (no free parameter)"
c245cf4
+};
c245cf4
 
c245cf4
-/******************************************************************************/
c245cf4
-/*  Monitoring auxiliaries.                                                   */
c245cf4
-/******************************************************************************/
c245cf4
+const char *lm_shortmsg[] = {
c245cf4
+    "found zero",      //  0
c245cf4
+    "converged (f)",   //  1
c245cf4
+    "converged (p)",   //  2
c245cf4
+    "converged (2)",   //  3
c245cf4
+    "degenerate",      //  4
c245cf4
+    "call limit",      //  5
c245cf4
+    "failed (f)",      //  6
c245cf4
+    "failed (p)",      //  7
c245cf4
+    "failed (o)",      //  8
c245cf4
+    "no memory",       //  9
c245cf4
+    "invalid input",   // 10
c245cf4
+    "user break",      // 11
c245cf4
+    "found nan",       // 12
c245cf4
+    "no free par"      // 13
c245cf4
+};
c245cf4
 
c245cf4
-static void lm_print_pars(int nout, const double* par, FILE* fout)
c245cf4
+
c245cf4
+/*****************************************************************************/
c245cf4
+/*  Monitoring auxiliaries.                                                  */
c245cf4
+/*****************************************************************************/
c245cf4
+
c245cf4
+static void lm_print_pars(const int nout, const double *par, FILE* fout)
c245cf4
 {
c245cf4
-    int i;
c245cf4
-    for (i = 0; i < nout; ++i)
c245cf4
-        fprintf(fout, " %16.9g", par[i]);
c245cf4
+    fprintf(fout, "  pars:");
c245cf4
+    for (int i = 0; i < nout; ++i)
c245cf4
+        fprintf(fout, " %23.16g", par[i]);
c245cf4
     fprintf(fout, "\n");
c245cf4
 }
c245cf4
 
c245cf4
-/******************************************************************************/
c245cf4
-/*  lmmin (main minimization routine)                                         */
c245cf4
-/******************************************************************************/
c245cf4
 
c245cf4
-void lmmin(const int n, double* x, const int m, const void* data,
c245cf4
-           void (*evaluate)(const double* par, const int m_dat,
c245cf4
-                            const void* data, double* fvec, int* userbreak),
c245cf4
-           const lm_control_struct* C, lm_status_struct* S)
c245cf4
+/*****************************************************************************/
c245cf4
+/*  lmmin (main minimization routine)                                        */
c245cf4
+/*****************************************************************************/
c245cf4
+
c245cf4
+void lmmin(
c245cf4
+    const int n, double *const x, const int m, const double* y,
c245cf4
+    const void *const data,
c245cf4
+    void (*const evaluate)(
c245cf4
+        const double *const par, const int m_dat, const void *const data,
c245cf4
+        double *const fvec, int *const userbreak),
c245cf4
+    const lm_control_struct *const C, lm_status_struct *const S)
c245cf4
 {
c245cf4
     int j, i;
c245cf4
-    double actred, dirder, fnorm, fnorm1, gnorm, pnorm, prered, ratio, step,
c245cf4
-        sum, temp, temp1, temp2, temp3;
c245cf4
-
c245cf4
-    /***  Initialize internal variables.  ***/
c245cf4
+    double actred, dirder, fnorm, fnorm1, gnorm, pnorm,
c245cf4
+        prered, ratio, step, sum, temp, temp1, temp2, temp3;
c245cf4
+    static double p1 = 0.1, p0001 = 1.0e-4;
c245cf4
 
c245cf4
     int maxfev = C->patience * (n+1);
c245cf4
 
c245cf4
-    int inner_success; /* flag for loop control */
c245cf4
-    double lmpar = 0;  /* Levenberg-Marquardt parameter */
c245cf4
+    int    inner_success; /* flag for loop control */
c245cf4
+    double lmpar = 0;     /* Levenberg-Marquardt parameter */
c245cf4
     double delta = 0;
c245cf4
     double xnorm = 0;
c245cf4
     double eps = sqrt(MAX(C->epsilon, LM_MACHEP)); /* for forward differences */
c245cf4
 
c245cf4
-    int nout = C->n_maxpri == -1 ? n : MIN(C->n_maxpri, n);
c245cf4
+    int nout = C->n_maxpri==-1 ? n : MIN(C->n_maxpri, n);
c245cf4
 
c245cf4
-    /* Reinterpret C->msgfile=NULL as stdout (which is unavailable for
c245cf4
-       compile-time initialization of lm_control_double and similar). */
c245cf4
+    /* The workaround msgfile=NULL is needed for default initialization */
c245cf4
     FILE* msgfile = C->msgfile ? C->msgfile : stdout;
c245cf4
 
c245cf4
-    /***  Default status info; must be set before first return statement.  ***/
c245cf4
-
c245cf4
-    S->outcome = 0; /* status code */
c245cf4
+    /* Default status info; must be set ahead of first return statements */
c245cf4
+    S->outcome = 0;      /* status code */
c245cf4
     S->userbreak = 0;
c245cf4
-    S->nfev = 0; /* function evaluation counter */
c245cf4
+    S->nfev = 0;      /* function evaluation counter */
c245cf4
 
c245cf4
-    /***  Check input parameters for errors.  ***/
c245cf4
+/***  Check input parameters for errors.  ***/
c245cf4
 
c245cf4
-    if (n <= 0) {
c245cf4
+    if ( n < 0 ) {
c245cf4
         fprintf(stderr, "lmmin: invalid number of parameters %i\n", n);
c245cf4
-        S->outcome = 10;
c245cf4
+        S->outcome = 10; /* invalid parameter */
c245cf4
         return;
c245cf4
     }
c245cf4
     if (m < n) {
c245cf4
         fprintf(stderr, "lmmin: number of data points (%i) "
c245cf4
-                        "smaller than number of parameters (%i)\n",
c245cf4
-                m, n);
c245cf4
+                "smaller than number of parameters (%i)\n", m, n);
c245cf4
         S->outcome = 10;
c245cf4
         return;
c245cf4
     }
c245cf4
@@ -173,93 +194,99 @@
c245cf4
     }
c245cf4
     if (C->scale_diag != 0 && C->scale_diag != 1) {
c245cf4
         fprintf(stderr, "lmmin: logical variable scale_diag=%i, "
c245cf4
-                        "should be 0 or 1\n",
c245cf4
-                C->scale_diag);
c245cf4
+                "should be 0 or 1\n", C->scale_diag);
c245cf4
         S->outcome = 10;
c245cf4
         return;
c245cf4
     }
c245cf4
 
c245cf4
-    /***  Allocate work space.  ***/
c245cf4
+/***  Allocate work space.  ***/
c245cf4
 
c245cf4
     /* Allocate total workspace with just one system call */
c245cf4
-    char* ws;
c245cf4
-    if ((ws = (char *)malloc((2*m + 5*n + m*n) * sizeof(double) +
c245cf4
-                             n * sizeof(int))) == NULL) {
c245cf4
+    char *ws;
c245cf4
+    if ( ( ws = static_cast<char *>(malloc(
c245cf4
+               (2*m+5*n+m*n)*sizeof(double) + n*sizeof(int)) ) ) == NULL ) {
c245cf4
         S->outcome = 9;
c245cf4
         return;
c245cf4
     }
c245cf4
 
c245cf4
     /* Assign workspace segments. */
c245cf4
-    char* pws = ws;
c245cf4
-    double* fvec = (double*)pws;
c245cf4
-    pws += m * sizeof(double) / sizeof(char);
c245cf4
-    double* diag = (double*)pws;
c245cf4
-    pws += n * sizeof(double) / sizeof(char);
c245cf4
-    double* qtf = (double*)pws;
c245cf4
-    pws += n * sizeof(double) / sizeof(char);
c245cf4
-    double* fjac = (double*)pws;
c245cf4
-    pws += n * m * sizeof(double) / sizeof(char);
c245cf4
-    double* wa1 = (double*)pws;
c245cf4
-    pws += n * sizeof(double) / sizeof(char);
c245cf4
-    double* wa2 = (double*)pws;
c245cf4
-    pws += n * sizeof(double) / sizeof(char);
c245cf4
-    double* wa3 = (double*)pws;
c245cf4
-    pws += n * sizeof(double) / sizeof(char);
c245cf4
-    double* wf = (double*)pws;
c245cf4
-    pws += m * sizeof(double) / sizeof(char);
c245cf4
-    int* Pivot = (int*)pws;
c245cf4
-    //pws += n * sizeof(int) / sizeof(char);
c245cf4
+    char *pws = ws;
c245cf4
+    double *fvec = (double*) pws; pws += m * sizeof(double)/sizeof(char);
c245cf4
+    double *diag = (double*) pws; pws += n * sizeof(double)/sizeof(char);
c245cf4
+    double *qtf  = (double*) pws; pws += n * sizeof(double)/sizeof(char);
c245cf4
+    double *fjac = (double*) pws; pws += n*m*sizeof(double)/sizeof(char);
c245cf4
+    double *wa1  = (double*) pws; pws += n * sizeof(double)/sizeof(char);
c245cf4
+    double *wa2  = (double*) pws; pws += n * sizeof(double)/sizeof(char);
c245cf4
+    double *wa3  = (double*) pws; pws += n * sizeof(double)/sizeof(char);
c245cf4
+    double *wf   = (double*) pws; pws += m * sizeof(double)/sizeof(char);
c245cf4
+    int    *ipvt = (int*)    pws; pws += n * sizeof(int)   /sizeof(char);
c245cf4
 
c245cf4
-    /* Initialize diag. */
c245cf4
-    if (!C->scale_diag)
c245cf4
+    /* Initialize diag */ // TODO: check whether this is still needed
c245cf4
+    if (!C->scale_diag) {
c245cf4
         for (j = 0; j < n; j++)
c245cf4
-            diag[j] = 1;
c245cf4
-
c245cf4
-    /***  Evaluate function at starting point and calculate norm.  ***/
c245cf4
-
c245cf4
-    if (C->verbosity) {
c245cf4
-        fprintf(msgfile, "lmmin start ");
c245cf4
-        lm_print_pars(nout, x, msgfile);
c245cf4
+            diag[j] = 1.;
c245cf4
     }
c245cf4
-    (*evaluate)(x, m, data, fvec, &(S->userbreak));
c245cf4
-    if (C->verbosity > 4)
c245cf4
-        for (i = 0; i < m; ++i)
c245cf4
-            fprintf(msgfile, "    fvec[%4i] = %18.8g\n", i, fvec[i]);
c245cf4
-    S->nfev = 1;
c245cf4
-    if (S->userbreak)
c245cf4
-        goto terminate;
c245cf4
-    fnorm = lm_enorm(m, fvec);
c245cf4
-    if (C->verbosity)
c245cf4
-        fprintf(msgfile, "  fnorm = %18.8g\n", fnorm);
c245cf4
 
c245cf4
-    if (!std::isfinite(fnorm)) {
c245cf4
+/***  Evaluate function at starting point and calculate norm.  ***/
c245cf4
+
c245cf4
+    if( C->verbosity&1 )
c245cf4
+        fprintf(msgfile, "lmmin start (ftol=%g gtol=%g xtol=%g)\n",
c245cf4
+                C->ftol, C->gtol, C->xtol);
c245cf4
+    if( C->verbosity&2 )
c245cf4
+        lm_print_pars(nout, x, msgfile);
c245cf4
+    (*evaluate)(x, m, data, fvec, &(S->userbreak));
c245cf4
+    if( C->verbosity&8 )
c245cf4
+    {
c245cf4
+        if (y) {
c245cf4
+            for( i=0; i
c245cf4
+                fprintf(msgfile, "    i, f, y-f: %4i %18.8g %18.8g\n",
c245cf4
+                        i, fvec[i], y[i]-fvec[i]);
c245cf4
+        } else {
c245cf4
+            for( i=0; i
c245cf4
+                fprintf(msgfile, "    i, f: %4i %18.8g\n", i, fvec[i]);
c245cf4
+        }
c245cf4
+    }
c245cf4
+    S->nfev = 1;
c245cf4
+    if ( S->userbreak )
c245cf4
+        goto terminate;
c245cf4
+    if ( n == 0 ) {
c245cf4
+        S->outcome = 13; /* won't fit */
c245cf4
+        goto terminate;
c245cf4
+    }
c245cf4
+    fnorm = lm_fnorm(m, fvec, y);
c245cf4
+    if( C->verbosity&2 )
c245cf4
+        fprintf(msgfile, "  fnorm = %24.16g\n", fnorm);
c245cf4
+    if( !isfinite(fnorm) ){
c245cf4
+        if( C->verbosity )
c245cf4
+            fprintf(msgfile, "nan case 1\n");
c245cf4
         S->outcome = 12; /* nan */
c245cf4
         goto terminate;
c245cf4
-    } else if (fnorm <= LM_DWARF) {
c245cf4
+    } else if( fnorm <= LM_DWARF ){
c245cf4
         S->outcome = 0; /* sum of squares almost zero, nothing to do */
c245cf4
         goto terminate;
c245cf4
     }
c245cf4
 
c245cf4
-    /***  The outer loop: compute gradient, then descend.  ***/
c245cf4
+/***  The outer loop: compute gradient, then descend.  ***/
c245cf4
 
c245cf4
-    for (int outer = 0;; ++outer) {
c245cf4
+    for( int outer=0; ; ++outer ) {
c245cf4
 
c245cf4
-        /** Calculate the Jacobian. **/
c245cf4
+/***  [outer]  Calculate the Jacobian.  ***/
c245cf4
+
c245cf4
         for (j = 0; j < n; j++) {
c245cf4
             temp = x[j];
c245cf4
-            step = MAX(eps * eps, eps * fabs(temp));
c245cf4
+            step = MAX(eps*eps, eps * fabs(temp));
c245cf4
             x[j] += step; /* replace temporarily */
c245cf4
             (*evaluate)(x, m, data, wf, &(S->userbreak));
c245cf4
             ++(S->nfev);
c245cf4
-            if (S->userbreak)
c245cf4
+            if ( S->userbreak )
c245cf4
                 goto terminate;
c245cf4
             for (i = 0; i < m; i++)
c245cf4
                 fjac[j*m+i] = (wf[i] - fvec[i]) / step;
c245cf4
             x[j] = temp; /* restore */
c245cf4
         }
c245cf4
-        if (C->verbosity >= 10) {
c245cf4
+        if ( C->verbosity&16 ) {
c245cf4
             /* print the entire matrix */
c245cf4
-            printf("\nlmmin Jacobian\n");
c245cf4
+            printf("Jacobian\n");
c245cf4
             for (i = 0; i < m; i++) {
c245cf4
                 printf("  ");
c245cf4
                 for (j = 0; j < n; j++)
c245cf4
@@ -268,34 +295,39 @@
c245cf4
             }
c245cf4
         }
c245cf4
 
c245cf4
-        /** Compute the QR factorization of the Jacobian. **/
c245cf4
+/***  [outer]  Compute the QR factorization of the Jacobian.  ***/
c245cf4
 
c245cf4
-        /* fjac is an m by n array. The upper n by n submatrix of fjac is made
c245cf4
-         *   to contain an upper triangular matrix R with diagonal elements of
c245cf4
-         *   nonincreasing magnitude such that
c245cf4
-         *
c245cf4
-         *         P^T*(J^T*J)*P = R^T*R
c245cf4
-         *
c245cf4
-         *         (NOTE: ^T stands for matrix transposition),
c245cf4
-         *
c245cf4
-         *   where P is a permutation matrix and J is the final calculated
c245cf4
-         *   Jacobian. Column j of P is column Pivot(j) of the identity matrix.
c245cf4
-         *   The lower trapezoidal part of fjac contains information generated
c245cf4
-         *   during the computation of R.
c245cf4
-         *
c245cf4
-         * Pivot is an integer array of length n. It defines a permutation
c245cf4
-         *   matrix P such that jac*P = Q*R, where jac is the final calculated
c245cf4
-         *   Jacobian, Q is orthogonal (not stored), and R is upper triangular
c245cf4
-         *   with diagonal elements of nonincreasing magnitude. Column j of P
c245cf4
-         *   is column Pivot(j) of the identity matrix.
c245cf4
-         */
c245cf4
+/*      fjac is an m by n array. The upper n by n submatrix of fjac
c245cf4
+ *        is made to contain an upper triangular matrix R with diagonal
c245cf4
+ *        elements of nonincreasing magnitude such that
c245cf4
+ *
c245cf4
+ *              P^T*(J^T*J)*P = R^T*R
c245cf4
+ *
c245cf4
+ *              (NOTE: ^T stands for matrix transposition),
c245cf4
+ *
c245cf4
+ *        where P is a permutation matrix and J is the final calculated
c245cf4
+ *        Jacobian. Column j of P is column ipvt(j) of the identity matrix.
c245cf4
+ *        The lower trapezoidal part of fjac contains information generated
c245cf4
+ *        during the computation of R.
c245cf4
+ *
c245cf4
+ *      ipvt is an integer array of length n. It defines a permutation
c245cf4
+ *        matrix P such that jac*P = Q*R, where jac is the final calculated
c245cf4
+ *        Jacobian, Q is orthogonal (not stored), and R is upper triangular
c245cf4
+ *        with diagonal elements of nonincreasing magnitude. Column j of P
c245cf4
+ *        is column ipvt(j) of the identity matrix.
c245cf4
+ */
c245cf4
 
c245cf4
-        lm_qrfac(m, n, fjac, Pivot, wa1, wa2, wa3);
c245cf4
-        /* return values are Pivot, wa1=rdiag, wa2=acnorm */
c245cf4
+        lm_qrfac(m, n, fjac, ipvt, wa1, wa2, wa3);
c245cf4
+        /* return values are ipvt, wa1=rdiag, wa2=acnorm */
c245cf4
 
c245cf4
-        /** Form Q^T * fvec, and store first n components in qtf. **/
c245cf4
-        for (i = 0; i < m; i++)
c245cf4
-            wf[i] = fvec[i];
c245cf4
+/***  [outer]  Form Q^T * fvec, and store first n components in qtf.  ***/
c245cf4
+
c245cf4
+        if (y)
c245cf4
+            for (i = 0; i < m; i++)
c245cf4
+                wf[i] = fvec[i] - y[i];
c245cf4
+        else
c245cf4
+            for (i = 0; i < m; i++)
c245cf4
+                wf[i] = fvec[i];
c245cf4
 
c245cf4
         for (j = 0; j < n; j++) {
c245cf4
             temp3 = fjac[j*m+j];
c245cf4
@@ -311,15 +343,16 @@
c245cf4
             qtf[j] = wf[j];
c245cf4
         }
c245cf4
 
c245cf4
-        /**  Compute norm of scaled gradient and detect degeneracy. **/
c245cf4
+/***  [outer]  Compute norm of scaled gradient and detect degeneracy.  ***/
c245cf4
+
c245cf4
         gnorm = 0;
c245cf4
         for (j = 0; j < n; j++) {
c245cf4
-            if (wa2[Pivot[j]] == 0)
c245cf4
+            if (wa2[ipvt[j]] == 0)
c245cf4
                 continue;
c245cf4
             sum = 0;
c245cf4
             for (i = 0; i <= j; i++)
c245cf4
                 sum += fjac[j*m+i] * qtf[i];
c245cf4
-            gnorm = MAX(gnorm, fabs(sum / wa2[Pivot[j]] / fnorm));
c245cf4
+            gnorm = MAX(gnorm, fabs( sum / wa2[ipvt[j]] / fnorm ));
c245cf4
         }
c245cf4
 
c245cf4
         if (gnorm <= C->gtol) {
c245cf4
@@ -327,8 +360,10 @@
c245cf4
             goto terminate;
c245cf4
         }
c245cf4
 
c245cf4
-        /** Initialize or update diag and delta. **/
c245cf4
-        if (!outer) { /* first iteration only */
c245cf4
+/***  [outer]  Initialize / update diag and delta. ***/
c245cf4
+
c245cf4
+        if ( !outer ) {
c245cf4
+            /* first iteration only */
c245cf4
             if (C->scale_diag) {
c245cf4
                 /* diag := norms of the columns of the initial Jacobian */
c245cf4
                 for (j = 0; j < n; j++)
c245cf4
@@ -337,129 +372,140 @@
c245cf4
                 for (j = 0; j < n; j++)
c245cf4
                     wa3[j] = diag[j] * x[j];
c245cf4
                 xnorm = lm_enorm(n, wa3);
c245cf4
-                if (C->verbosity >= 2) {
c245cf4
-                    fprintf(msgfile, "lmmin diag  ");
c245cf4
-                    lm_print_pars(nout, x, msgfile); // xnorm
c245cf4
-                    fprintf(msgfile, "  xnorm = %18.8g\n", xnorm);
c245cf4
-                }
c245cf4
-                /* Only now print the header for the loop table. */
c245cf4
-                if (C->verbosity >= 3) {
c245cf4
-                    fprintf(msgfile, "  o  i     lmpar    prered"
c245cf4
-                                     "          ratio    dirder      delta"
c245cf4
-                                     "      pnorm                 fnorm");
c245cf4
-                    for (i = 0; i < nout; ++i)
c245cf4
-                        fprintf(msgfile, "               p%i", i);
c245cf4
-                    fprintf(msgfile, "\n");
c245cf4
-                }
c245cf4
             } else {
c245cf4
                 xnorm = lm_enorm(n, x);
c245cf4
             }
c245cf4
-            if (!std::isfinite(xnorm)) {
c245cf4
+            if( !isfinite(xnorm) ){
c245cf4
+                if( C->verbosity )
c245cf4
+                    fprintf(msgfile, "nan case 2\n");
c245cf4
                 S->outcome = 12; /* nan */
c245cf4
                 goto terminate;
c245cf4
             }
c245cf4
-            /* Initialize the step bound delta. */
c245cf4
-            if (xnorm)
c245cf4
+            /* initialize the step bound delta. */
c245cf4
+            if ( xnorm )
c245cf4
                 delta = C->stepbound * xnorm;
c245cf4
             else
c245cf4
                 delta = C->stepbound;
c245cf4
+            /* only now print the header for the loop table */
c245cf4
+            if( C->verbosity&2 ) {
c245cf4
+                fprintf(msgfile, " #o #i     lmpar    prered  actred"
c245cf4
+                        "        ratio    dirder      delta"
c245cf4
+                        "      pnorm                 fnorm");
c245cf4
+                for (i = 0; i < nout; ++i)
c245cf4
+                    fprintf(msgfile, "               p%i", i);
c245cf4
+                fprintf(msgfile, "\n");
c245cf4
+            }
c245cf4
         } else {
c245cf4
             if (C->scale_diag) {
c245cf4
                 for (j = 0; j < n; j++)
c245cf4
-                    diag[j] = MAX(diag[j], wa2[j]);
c245cf4
+                    diag[j] = MAX( diag[j], wa2[j] );
c245cf4
             }
c245cf4
         }
c245cf4
 
c245cf4
-        /** The inner loop. **/
c245cf4
+/***  The inner loop. ***/
c245cf4
         int inner = 0;
c245cf4
         do {
c245cf4
 
c245cf4
-            /** Determine the Levenberg-Marquardt parameter. **/
c245cf4
-            lm_lmpar(n, fjac, m, Pivot, diag, qtf, delta, &lmpar,
c245cf4
+/***  [inner]  Determine the Levenberg-Marquardt parameter.  ***/
c245cf4
+
c245cf4
+            lm_lmpar(n, fjac, m, ipvt, diag, qtf, delta, &lmpar,
c245cf4
                      wa1, wa2, wf, wa3);
c245cf4
             /* used return values are fjac (partly), lmpar, wa1=x, wa3=diag*x */
c245cf4
 
c245cf4
-            /* Predict scaled reduction. */
c245cf4
+            /* predict scaled reduction */
c245cf4
             pnorm = lm_enorm(n, wa3);
c245cf4
-            if (!std::isfinite(pnorm)) {
c245cf4
+            if( !isfinite(pnorm) ){
c245cf4
+                if( C->verbosity )
c245cf4
+                    fprintf(msgfile, "nan case 3\n");
c245cf4
                 S->outcome = 12; /* nan */
c245cf4
                 goto terminate;
c245cf4
             }
c245cf4
-            temp2 = lmpar * SQR(pnorm / fnorm);
c245cf4
+            temp2 = lmpar * SQR( pnorm / fnorm );
c245cf4
             for (j = 0; j < n; j++) {
c245cf4
                 wa3[j] = 0;
c245cf4
                 for (i = 0; i <= j; i++)
c245cf4
-                    wa3[i] -= fjac[j*m+i] * wa1[Pivot[j]];
c245cf4
+                    wa3[i] -= fjac[j*m+i] * wa1[ipvt[j]];
c245cf4
             }
c245cf4
-            temp1 = SQR(lm_enorm(n, wa3) / fnorm);
c245cf4
-            if (!std::isfinite(temp1)) {
c245cf4
+            temp1 = SQR( lm_enorm(n, wa3) / fnorm );
c245cf4
+            if( !isfinite(temp1) ){
c245cf4
+                if( C->verbosity )
c245cf4
+                    fprintf(msgfile, "nan case 4\n");
c245cf4
                 S->outcome = 12; /* nan */
c245cf4
                 goto terminate;
c245cf4
             }
c245cf4
-            prered = temp1 + 2*temp2;
c245cf4
+            prered = temp1 + 2 * temp2;
c245cf4
             dirder = -temp1 + temp2; /* scaled directional derivative */
c245cf4
 
c245cf4
-            /* At first call, adjust the initial step bound. */
c245cf4
-            if (!outer && pnorm < delta)
c245cf4
+            /* at first call, adjust the initial step bound. */
c245cf4
+            if ( !outer && !inner && pnorm < delta )
c245cf4
                 delta = pnorm;
c245cf4
 
c245cf4
-            /** Evaluate the function at x + p. **/
c245cf4
+/***  [inner]  Evaluate the function at x + p.  ***/
c245cf4
+
c245cf4
             for (j = 0; j < n; j++)
c245cf4
                 wa2[j] = x[j] - wa1[j];
c245cf4
-            (*evaluate)(wa2, m, data, wf, &(S->userbreak));
c245cf4
+
c245cf4
+            (*evaluate)( wa2, m, data, wf, &(S->userbreak) );
c245cf4
             ++(S->nfev);
c245cf4
-            if (S->userbreak)
c245cf4
+            if ( S->userbreak )
c245cf4
                 goto terminate;
c245cf4
-            fnorm1 = lm_enorm(m, wf);
c245cf4
-            if (!std::isfinite(fnorm1)) {
c245cf4
-                S->outcome = 12; /* nan */
c245cf4
-                goto terminate;
c245cf4
+            fnorm1 = lm_fnorm(m, wf, y);
c245cf4
+            // exceptionally, for this norm we do not test for infinity
c245cf4
+            // because we can deal with it without terminating.
c245cf4
+
c245cf4
+/***  [inner]  Evaluate the scaled reduction.  ***/
c245cf4
+
c245cf4
+            /* actual scaled reduction (supports even the case fnorm1=infty) */
c245cf4
+	    if (p1 * fnorm1 < fnorm)
c245cf4
+		actred = 1 - SQR(fnorm1 / fnorm);
c245cf4
+	    else
c245cf4
+		actred = -1;
c245cf4
+
c245cf4
+            /* ratio of actual to predicted reduction */
c245cf4
+            ratio = prered ? actred/prered : 0;
c245cf4
+
c245cf4
+            if( C->verbosity&32 ) {
c245cf4
+                if (y) {
c245cf4
+                    for( i=0; i
c245cf4
+                        fprintf(msgfile, "    i, f, y-f: %4i %18.8g %18.8g\n",
c245cf4
+                                i, fvec[i], y[i]-fvec[i]);
c245cf4
+                } else {
c245cf4
+                    for( i=0; i
c245cf4
+                        fprintf(msgfile, "    i, f, y-f: %4i %18.8g\n",
c245cf4
+                                i, fvec[i]);
c245cf4
+                }
c245cf4
             }
c245cf4
-
c245cf4
-            /** Evaluate the scaled reduction. **/
c245cf4
-
c245cf4
-            /* Actual scaled reduction. */
c245cf4
-            actred = 1 - SQR(fnorm1 / fnorm);
c245cf4
-
c245cf4
-            /* Ratio of actual to predicted reduction. */
c245cf4
-            ratio = prered ? actred / prered : 0;
c245cf4
-
c245cf4
-            if (C->verbosity == 2) {
c245cf4
-                fprintf(msgfile, "lmmin (%i:%i) ", outer, inner);
c245cf4
-                lm_print_pars(nout, wa2, msgfile); // fnorm1,
c245cf4
-            } else if (C->verbosity >= 3) {
c245cf4
-                printf("%3i %2i %9.2g %9.2g %14.6g"
c245cf4
+            if( C->verbosity&2 ) {
c245cf4
+                printf("%3i %2i %9.2g %9.2g %9.2g %14.6g"
c245cf4
                        " %9.2g %10.3e %10.3e %21.15e",
c245cf4
-                       outer, inner, lmpar, prered, ratio,
c245cf4
+                       outer, inner, lmpar, prered, actred, ratio,
c245cf4
                        dirder, delta, pnorm, fnorm1);
c245cf4
                 for (i = 0; i < nout; ++i)
c245cf4
                     fprintf(msgfile, " %16.9g", wa2[i]);
c245cf4
                 fprintf(msgfile, "\n");
c245cf4
             }
c245cf4
 
c245cf4
-            /* Update the step bound. */
c245cf4
-            if (ratio <= 0.25) {
c245cf4
-                if (actred >= 0)
c245cf4
-                    temp = 0.5;
c245cf4
-                else if (actred > -99) /* -99 = 1-1/0.1^2 */
c245cf4
-                    temp = MAX(dirder / (2*dirder + actred), 0.1);
c245cf4
-                else
c245cf4
-                    temp = 0.1;
c245cf4
-                delta = temp * MIN(delta, pnorm / 0.1);
c245cf4
-                lmpar /= temp;
c245cf4
-            } else if (ratio >= 0.75) {
c245cf4
-                delta = 2 * pnorm;
c245cf4
-                lmpar *= 0.5;
c245cf4
-            } else if (!lmpar) {
c245cf4
-                delta = 2 * pnorm;
c245cf4
-            }
c245cf4
+            /* update the step bound */
c245cf4
+	    if (ratio <= 0.25) {
c245cf4
+		if (actred >= 0)
c245cf4
+		    temp = 0.5;
c245cf4
+		else
c245cf4
+		    temp = 0.5 * dirder / (dirder + 0.5 * actred);
c245cf4
+		if (p1 * fnorm1 >= fnorm || temp < p1)
c245cf4
+		    temp = p1;
c245cf4
+		delta = temp * MIN(delta, pnorm / p1);
c245cf4
+		lmpar /= temp;
c245cf4
+	    } else if (lmpar == 0 || ratio >= 0.75) {
c245cf4
+		delta = 2 * pnorm;
c245cf4
+		lmpar *= 0.5;
c245cf4
+	    }
c245cf4
 
c245cf4
-            /**  On success, update solution, and test for convergence. **/
c245cf4
+/***  [inner]  On success, update solution, and test for convergence.  ***/
c245cf4
 
c245cf4
-            inner_success = ratio >= 1e-4;
c245cf4
-            if (inner_success) {
c245cf4
+            inner_success = ratio >= p0001;
c245cf4
+            if ( inner_success ) {
c245cf4
 
c245cf4
-                /* Update x, fvec, and their norms. */
c245cf4
+                /* update x, fvec, and their norms */
c245cf4
                 if (C->scale_diag) {
c245cf4
                     for (j = 0; j < n; j++) {
c245cf4
                         x[j] = wa2[j];
c245cf4
@@ -472,172 +518,193 @@
c245cf4
                 for (i = 0; i < m; i++)
c245cf4
                     fvec[i] = wf[i];
c245cf4
                 xnorm = lm_enorm(n, wa2);
c245cf4
-                if (!std::isfinite(xnorm)) {
c245cf4
+                if( !isfinite(xnorm) ){
c245cf4
+                    if( C->verbosity )
c245cf4
+                        fprintf(msgfile, "nan case 6\n");
c245cf4
                     S->outcome = 12; /* nan */
c245cf4
                     goto terminate;
c245cf4
                 }
c245cf4
                 fnorm = fnorm1;
c245cf4
             }
c245cf4
 
c245cf4
-            /* Convergence tests. */
c245cf4
+            /* convergence tests */
c245cf4
             S->outcome = 0;
c245cf4
-            if (fnorm <= LM_DWARF)
c245cf4
-                goto terminate; /* success: sum of squares almost zero */
c245cf4
-            /* Test two criteria (both may be fulfilled). */
c245cf4
+            if( fnorm<=LM_DWARF )
c245cf4
+                goto terminate;  /* success: sum of squares almost zero */
c245cf4
+            /* test two criteria (both may be fulfilled) */
c245cf4
             if (fabs(actred) <= C->ftol && prered <= C->ftol && ratio <= 2)
c245cf4
-                S->outcome = 1; /* success: x almost stable */
c245cf4
+                S->outcome = 1;  /* success: x almost stable */
c245cf4
             if (delta <= C->xtol * xnorm)
c245cf4
                 S->outcome += 2; /* success: sum of squares almost stable */
c245cf4
             if (S->outcome != 0) {
c245cf4
                 goto terminate;
c245cf4
             }
c245cf4
 
c245cf4
-            /** Tests for termination and stringent tolerances. **/
c245cf4
-            if (S->nfev >= maxfev) {
c245cf4
+/***  [inner]  Tests for termination and stringent tolerances.  ***/
c245cf4
+
c245cf4
+            if ( S->nfev >= maxfev ){
c245cf4
                 S->outcome = 5;
c245cf4
                 goto terminate;
c245cf4
             }
c245cf4
-            if (fabs(actred) <= LM_MACHEP && prered <= LM_MACHEP &&
c245cf4
-                ratio <= 2) {
c245cf4
+            if ( fabs(actred) <= LM_MACHEP &&
c245cf4
+                 prered <= LM_MACHEP && ratio <= 2 ){
c245cf4
                 S->outcome = 6;
c245cf4
                 goto terminate;
c245cf4
             }
c245cf4
-            if (delta <= LM_MACHEP * xnorm) {
c245cf4
+            if ( delta <= LM_MACHEP*xnorm ){
c245cf4
                 S->outcome = 7;
c245cf4
                 goto terminate;
c245cf4
             }
c245cf4
-            if (gnorm <= LM_MACHEP) {
c245cf4
+            if ( gnorm <= LM_MACHEP ){
c245cf4
                 S->outcome = 8;
c245cf4
                 goto terminate;
c245cf4
             }
c245cf4
 
c245cf4
-            /** End of the inner loop. Repeat if iteration unsuccessful. **/
c245cf4
-            ++inner;
c245cf4
-        } while (!inner_success);
c245cf4
+/***  [inner]  End of the loop. Repeat if iteration unsuccessful.  ***/
c245cf4
 
c245cf4
-    }; /***  End of the outer loop.  ***/
c245cf4
+            ++inner;
c245cf4
+        } while ( !inner_success );
c245cf4
+
c245cf4
+/***  [outer]  End of the loop. ***/
c245cf4
+
c245cf4
+    };
c245cf4
 
c245cf4
 terminate:
c245cf4
-    S->fnorm = lm_enorm(m, fvec);
c245cf4
-    if (C->verbosity >= 2)
c245cf4
-        printf("lmmin outcome (%i) xnorm %g ftol %g xtol %g\n", S->outcome,
c245cf4
-               xnorm, C->ftol, C->xtol);
c245cf4
-    if (C->verbosity & 1) {
c245cf4
-        fprintf(msgfile, "lmmin final ");
c245cf4
-        lm_print_pars(nout, x, msgfile); // S->fnorm,
c245cf4
-        fprintf(msgfile, "  fnorm = %18.8g\n", S->fnorm);
c245cf4
+    S->fnorm = lm_fnorm(m, fvec, y);
c245cf4
+    if( C->verbosity&1 )
c245cf4
+        fprintf(msgfile, "lmmin terminates with outcome %i\n", S->outcome);
c245cf4
+    if( C->verbosity&2 )
c245cf4
+        lm_print_pars(nout, x, msgfile);
c245cf4
+    if( C->verbosity&8 ) {
c245cf4
+        if (y) {
c245cf4
+            for( i=0; i
c245cf4
+                fprintf(msgfile, "    i, f, y-f: %4i %18.8g %18.8g\n",
c245cf4
+                        i, fvec[i], y[i]-fvec[i] );
c245cf4
+        } else {
c245cf4
+            for( i=0; i
c245cf4
+                fprintf(msgfile, "    i, f, y-f: %4i %18.8g\n", i, fvec[i]);
c245cf4
+        }
c245cf4
     }
c245cf4
-    if (S->userbreak) /* user-requested break */
c245cf4
+    if( C->verbosity&2 )
c245cf4
+        fprintf(msgfile, "  fnorm=%24.16g xnorm=%24.16g\n", S->fnorm, xnorm);
c245cf4
+    if ( S->userbreak ) /* user-requested break */
c245cf4
         S->outcome = 11;
c245cf4
 
c245cf4
-    /***  Deallocate the workspace.  ***/
c245cf4
+/***  Deallocate the workspace.  ***/
c245cf4
     free(ws);
c245cf4
 
c245cf4
 } /*** lmmin. ***/
c245cf4
 
c245cf4
-/******************************************************************************/
c245cf4
-/*  lm_lmpar (determine Levenberg-Marquardt parameter)                        */
c245cf4
-/******************************************************************************/
c245cf4
 
c245cf4
-static void lm_lmpar(const int n, double* r, const int ldr, const int* Pivot,
c245cf4
-                     const double* diag, const double* qtb, const double delta,
c245cf4
-                     double* par, double* x, double* Sdiag, double* aux, double* xdi)
c245cf4
+/*****************************************************************************/
c245cf4
+/*  lm_lmpar (determine Levenberg-Marquardt parameter)                       */
c245cf4
+/*****************************************************************************/
c245cf4
+
c245cf4
+void lm_lmpar(
c245cf4
+    const int n, double *const r, const int ldr, int *const ipvt,
c245cf4
+    double *const diag, double *const qtb, double delta, double *const par,
c245cf4
+    double *const x, double *const sdiag, double *const aux, double *const xdi)
c245cf4
+{
c245cf4
 /*     Given an m by n matrix A, an n by n nonsingular diagonal matrix D,
c245cf4
  *     an m-vector b, and a positive number delta, the problem is to
c245cf4
  *     determine a parameter value par such that if x solves the system
c245cf4
  *
c245cf4
  *          A*x = b  and  sqrt(par)*D*x = 0
c245cf4
  *
c245cf4
- *     in the least squares sense, and dxnorm is the Euclidean norm of D*x,
c245cf4
- *     then either par=0 and (dxnorm-delta) < 0.1*delta, or par>0 and
c245cf4
- *     abs(dxnorm-delta) < 0.1*delta.
c245cf4
+ *     in the least squares sense, and dxnorm is the euclidean
c245cf4
+ *     norm of D*x, then either par=0 and (dxnorm-delta) < 0.1*delta,
c245cf4
+ *     or par>0 and abs(dxnorm-delta) < 0.1*delta.
c245cf4
  *
c245cf4
  *     Using lm_qrsolv, this subroutine completes the solution of the
c245cf4
- *     problem if it is provided with the necessary information from the
c245cf4
- *     QR factorization, with column pivoting, of A. That is, if A*P = Q*R,
c245cf4
- *     where P is a permutation matrix, Q has orthogonal columns, and R is
c245cf4
- *     an upper triangular matrix with diagonal elements of nonincreasing
c245cf4
- *     magnitude, then lmpar expects the full upper triangle of R, the
c245cf4
- *     permutation matrix P, and the first n components of Q^T*b. On output
c245cf4
- *     lmpar also provides an upper triangular matrix S such that
c245cf4
+ *     problem if it is provided with the necessary information from
c245cf4
+ *     the QR factorization, with column pivoting, of A. That is, if
c245cf4
+ *     A*P = Q*R, where P is a permutation matrix, Q has orthogonal
c245cf4
+ *     columns, and R is an upper triangular matrix with diagonal
c245cf4
+ *     elements of nonincreasing magnitude, then lmpar expects the
c245cf4
+ *     full upper triangle of R, the permutation matrix P, and the
c245cf4
+ *     first n components of Q^T*b. On output lmpar also provides an
c245cf4
+ *     upper triangular matrix S such that
c245cf4
  *
c245cf4
  *          P^T*(A^T*A + par*D*D)*P = S^T*S.
c245cf4
  *
c245cf4
  *     S is employed within lmpar and may be of separate interest.
c245cf4
  *
c245cf4
- *     Only a few iterations are generally needed for convergence of the
c245cf4
- *     algorithm. If, however, the limit of 10 iterations is reached, then
c245cf4
- *     the output par will contain the best value obtained so far.
c245cf4
+ *     Only a few iterations are generally needed for convergence
c245cf4
+ *     of the algorithm. If, however, the limit of 10 iterations
c245cf4
+ *     is reached, then the output par will contain the best value
c245cf4
+ *     obtained so far.
c245cf4
  *
c245cf4
  *     Parameters:
c245cf4
  *
c245cf4
  *      n is a positive integer INPUT variable set to the order of r.
c245cf4
  *
c245cf4
- *      r is an n by n array. On INPUT the full upper triangle must contain
c245cf4
- *        the full upper triangle of the matrix R. On OUTPUT the full upper
c245cf4
- *        triangle is unaltered, and the strict lower triangle contains the
c245cf4
- *        strict upper triangle (transposed) of the upper triangular matrix S.
c245cf4
+ *      r is an n by n array. On INPUT the full upper triangle
c245cf4
+ *        must contain the full upper triangle of the matrix R.
c245cf4
+ *        On OUTPUT the full upper triangle is unaltered, and the
c245cf4
+ *        strict lower triangle contains the strict upper triangle
c245cf4
+ *        (transposed) of the upper triangular matrix S.
c245cf4
  *
c245cf4
- *      ldr is a positive integer INPUT variable not less than n which
c245cf4
- *        specifies the leading dimension of the array R.
c245cf4
+ *      ldr is a positive integer INPUT variable not less than n
c245cf4
+ *        which specifies the leading dimension of the array R.
c245cf4
  *
c245cf4
- *      Pivot is an integer INPUT array of length n which defines the
c245cf4
- *        permutation matrix P such that A*P = Q*R. Column j of P is column
c245cf4
- *        Pivot(j) of the identity matrix.
c245cf4
+ *      ipvt is an integer INPUT array of length n which defines the
c245cf4
+ *        permutation matrix P such that A*P = Q*R. Column j of P
c245cf4
+ *        is column ipvt(j) of the identity matrix.
c245cf4
  *
c245cf4
- *      diag is an INPUT array of length n which must contain the diagonal
c245cf4
- *        elements of the matrix D.
c245cf4
+ *      diag is an INPUT array of length n which must contain the
c245cf4
+ *        diagonal elements of the matrix D.
c245cf4
  *
c245cf4
  *      qtb is an INPUT array of length n which must contain the first
c245cf4
  *        n elements of the vector Q^T*b.
c245cf4
  *
c245cf4
- *      delta is a positive INPUT variable which specifies an upper bound
c245cf4
- *        on the Euclidean norm of D*x.
c245cf4
+ *      delta is a positive INPUT variable which specifies an upper
c245cf4
+ *        bound on the euclidean norm of D*x.
c245cf4
  *
c245cf4
- *      par is a nonnegative variable. On INPUT par contains an initial
c245cf4
- *        estimate of the Levenberg-Marquardt parameter. On OUTPUT par
c245cf4
- *        contains the final estimate.
c245cf4
+ *      par is a nonnegative variable. On INPUT par contains an
c245cf4
+ *        initial estimate of the Levenberg-Marquardt parameter.
c245cf4
+ *        On OUTPUT par contains the final estimate.
c245cf4
  *
c245cf4
- *      x is an OUTPUT array of length n which contains the least-squares
c245cf4
- *        solution of the system A*x = b, sqrt(par)*D*x = 0, for the output par.
c245cf4
+ *      x is an OUTPUT array of length n which contains the least
c245cf4
+ *        squares solution of the system A*x = b, sqrt(par)*D*x = 0,
c245cf4
+ *        for the output par.
c245cf4
  *
c245cf4
- *      Sdiag is an array of length n needed as workspace; on OUTPUT it
c245cf4
- *        contains the diagonal elements of the upper triangular matrix S.
c245cf4
+ *      sdiag is an array of length n needed as workspace; on OUTPUT
c245cf4
+ *        it contains the diagonal elements of the upper triangular
c245cf4
+ *        matrix S.
c245cf4
  *
c245cf4
  *      aux is a multi-purpose work array of length n.
c245cf4
  *
c245cf4
  *      xdi is a work array of length n. On OUTPUT: diag[j] * x[j].
c245cf4
  *
c245cf4
  */
c245cf4
-{
c245cf4
     int i, iter, j, nsing;
c245cf4
     double dxnorm, fp, fp_old, gnorm, parc, parl, paru;
c245cf4
     double sum, temp;
c245cf4
     static double p1 = 0.1;
c245cf4
 
c245cf4
-    /*** Compute and store in x the Gauss-Newton direction. If the Jacobian
c245cf4
-         is rank-deficient, obtain a least-squares solution. ***/
c245cf4
+/*** lmpar: compute and store in x the gauss-newton direction. if the
c245cf4
+     jacobian is rank-deficient, obtain a least squares solution. ***/
c245cf4
 
c245cf4
     nsing = n;
c245cf4
     for (j = 0; j < n; j++) {
c245cf4
         aux[j] = qtb[j];
c245cf4
-        if (r[j*ldr+j] == 0 && nsing == n)
c245cf4
+        if (r[j * ldr + j] == 0 && nsing == n)
c245cf4
             nsing = j;
c245cf4
         if (nsing < n)
c245cf4
             aux[j] = 0;
c245cf4
     }
c245cf4
-    for (j = nsing-1; j >= 0; j--) {
c245cf4
-        aux[j] = aux[j] / r[j+ldr*j];
c245cf4
+    for (j = nsing - 1; j >= 0; j--) {
c245cf4
+        aux[j] = aux[j] / r[j + ldr * j];
c245cf4
         temp = aux[j];
c245cf4
         for (i = 0; i < j; i++)
c245cf4
-            aux[i] -= r[j*ldr+i] * temp;
c245cf4
+            aux[i] -= r[j * ldr + i] * temp;
c245cf4
     }
c245cf4
 
c245cf4
     for (j = 0; j < n; j++)
c245cf4
-        x[Pivot[j]] = aux[j];
c245cf4
+        x[ipvt[j]] = aux[j];
c245cf4
 
c245cf4
-    /*** Initialize the iteration counter, evaluate the function at the origin,
c245cf4
-         and test for acceptance of the Gauss-Newton direction. ***/
c245cf4
+/*** lmpar: initialize the iteration counter, evaluate the function at the
c245cf4
+     origin, and test for acceptance of the gauss-newton direction. ***/
c245cf4
 
c245cf4
     for (j = 0; j < n; j++)
c245cf4
         xdi[j] = diag[j] * x[j];
c245cf4
@@ -645,65 +712,67 @@
c245cf4
     fp = dxnorm - delta;
c245cf4
     if (fp <= p1 * delta) {
c245cf4
 #ifdef LMFIT_DEBUG_MESSAGES
c245cf4
-        printf("debug lmpar nsing=%d, n=%d, terminate[fp<=p1*del]\n", nsing, n);
c245cf4
+        printf("debug lmpar nsing %d n %d, terminate (fp
c245cf4
+               nsing, n);
c245cf4
 #endif
c245cf4
         *par = 0;
c245cf4
         return;
c245cf4
     }
c245cf4
 
c245cf4
-    /*** If the Jacobian is not rank deficient, the Newton step provides a
c245cf4
-         lower bound, parl, for the zero of the function. Otherwise set this
c245cf4
-         bound to zero. ***/
c245cf4
+/*** lmpar: if the jacobian is not rank deficient, the newton
c245cf4
+     step provides a lower bound, parl, for the zero of
c245cf4
+     the function. otherwise set this bound to zero. ***/
c245cf4
 
c245cf4
     parl = 0;
c245cf4
     if (nsing >= n) {
c245cf4
         for (j = 0; j < n; j++)
c245cf4
-            aux[j] = diag[Pivot[j]] * xdi[Pivot[j]] / dxnorm;
c245cf4
+            aux[j] = diag[ipvt[j]] * xdi[ipvt[j]] / dxnorm;
c245cf4
 
c245cf4
         for (j = 0; j < n; j++) {
c245cf4
             sum = 0;
c245cf4
             for (i = 0; i < j; i++)
c245cf4
-                sum += r[j*ldr+i] * aux[i];
c245cf4
-            aux[j] = (aux[j] - sum) / r[j+ldr*j];
c245cf4
+                sum += r[j * ldr + i] * aux[i];
c245cf4
+            aux[j] = (aux[j] - sum) / r[j + ldr * j];
c245cf4
         }
c245cf4
         temp = lm_enorm(n, aux);
c245cf4
         parl = fp / delta / temp / temp;
c245cf4
     }
c245cf4
 
c245cf4
-    /*** Calculate an upper bound, paru, for the zero of the function. ***/
c245cf4
+/*** lmpar: calculate an upper bound, paru, for the zero of the function. ***/
c245cf4
 
c245cf4
     for (j = 0; j < n; j++) {
c245cf4
         sum = 0;
c245cf4
         for (i = 0; i <= j; i++)
c245cf4
-            sum += r[j*ldr+i] * qtb[i];
c245cf4
-        aux[j] = sum / diag[Pivot[j]];
c245cf4
+            sum += r[j * ldr + i] * qtb[i];
c245cf4
+        aux[j] = sum / diag[ipvt[j]];
c245cf4
     }
c245cf4
     gnorm = lm_enorm(n, aux);
c245cf4
     paru = gnorm / delta;
c245cf4
     if (paru == 0)
c245cf4
         paru = LM_DWARF / MIN(delta, p1);
c245cf4
 
c245cf4
-    /*** If the input par lies outside of the interval (parl,paru),
c245cf4
-         set par to the closer endpoint. ***/
c245cf4
+/*** lmpar: if the input par lies outside of the interval (parl,paru),
c245cf4
+     set par to the closer endpoint. ***/
c245cf4
 
c245cf4
     *par = MAX(*par, parl);
c245cf4
     *par = MIN(*par, paru);
c245cf4
     if (*par == 0)
c245cf4
         *par = gnorm / dxnorm;
c245cf4
 
c245cf4
-    /*** Iterate. ***/
c245cf4
+/*** lmpar: iterate. ***/
c245cf4
 
c245cf4
-    for (iter = 0;; iter++) {
c245cf4
+    for (iter=0; ; iter++) {
c245cf4
 
c245cf4
-        /** Evaluate the function at the current value of par. **/
c245cf4
+        /** evaluate the function at the current value of par. **/
c245cf4
+
c245cf4
         if (*par == 0)
c245cf4
             *par = MAX(LM_DWARF, 0.001 * paru);
c245cf4
         temp = sqrt(*par);
c245cf4
         for (j = 0; j < n; j++)
c245cf4
             aux[j] = temp * diag[j];
c245cf4
 
c245cf4
-        lm_qrsolv(n, r, ldr, Pivot, aux, qtb, x, Sdiag, xdi);
c245cf4
-        /* return values are r, x, Sdiag */
c245cf4
+        lm_qrsolv(n, r, ldr, ipvt, aux, qtb, x, sdiag, xdi);
c245cf4
+        /* return values are r, x, sdiag */
c245cf4
 
c245cf4
         for (j = 0; j < n; j++)
c245cf4
             xdi[j] = diag[j] * x[j]; /* used as output */
c245cf4
@@ -711,49 +780,58 @@
c245cf4
         fp_old = fp;
c245cf4
         fp = dxnorm - delta;
c245cf4
 
c245cf4
-        /** If the function is small enough, accept the current value
c245cf4
+        /** if the function is small enough, accept the current value
c245cf4
             of par. Also test for the exceptional cases where parl
c245cf4
             is zero or the number of iterations has reached 10. **/
c245cf4
-        if (fabs(fp) <= p1 * delta ||
c245cf4
-            (parl == 0 && fp <= fp_old && fp_old < 0) || iter == 10) {
c245cf4
+
c245cf4
+        if (fabs(fp) <= p1 * delta
c245cf4
+            || (parl == 0 && fp <= fp_old && fp_old < 0)
c245cf4
+            || iter == 10) {
c245cf4
 #ifdef LMFIT_DEBUG_MESSAGES
c245cf4
-            printf("debug lmpar nsing=%d, iter=%d, "
c245cf4
-                   "par=%.4e [%.4e %.4e], delta=%.4e, fp=%.4e\n",
c245cf4
+            printf("debug lmpar nsing %d iter %d "
c245cf4
+                   "par %.4e [%.4e %.4e] delta %.4e fp %.4e\n",
c245cf4
                    nsing, iter, *par, parl, paru, delta, fp);
c245cf4
 #endif
c245cf4
             break; /* the only exit from the iteration. */
c245cf4
         }
c245cf4
 
c245cf4
-        /** Compute the Newton correction. **/
c245cf4
+        /** compute the Newton correction. **/
c245cf4
+
c245cf4
         for (j = 0; j < n; j++)
c245cf4
-            aux[j] = diag[Pivot[j]] * xdi[Pivot[j]] / dxnorm;
c245cf4
+            aux[j] = diag[ipvt[j]] * xdi[ipvt[j]] / dxnorm;
c245cf4
 
c245cf4
         for (j = 0; j < n; j++) {
c245cf4
-            aux[j] = aux[j] / Sdiag[j];
c245cf4
-            for (i = j+1; i < n; i++)
c245cf4
-                aux[i] -= r[j*ldr+i] * aux[j];
c245cf4
+            aux[j] = aux[j] / sdiag[j];
c245cf4
+            for (i = j + 1; i < n; i++)
c245cf4
+                aux[i] -= r[j * ldr + i] * aux[j];
c245cf4
         }
c245cf4
         temp = lm_enorm(n, aux);
c245cf4
         parc = fp / delta / temp / temp;
c245cf4
 
c245cf4
-        /** Depending on the sign of the function, update parl or paru. **/
c245cf4
+        /** depending on the sign of the function, update parl or paru. **/
c245cf4
+
c245cf4
         if (fp > 0)
c245cf4
             parl = MAX(parl, *par);
c245cf4
-        else /* fp < 0 [the case fp==0 is precluded by the break condition] */
c245cf4
+        else if (fp < 0)
c245cf4
             paru = MIN(paru, *par);
c245cf4
+        /* the case fp==0 is precluded by the break condition  */
c245cf4
 
c245cf4
-        /** Compute an improved estimate for par. **/
c245cf4
+        /** compute an improved estimate for par. **/
c245cf4
+
c245cf4
         *par = MAX(parl, *par + parc);
c245cf4
+
c245cf4
     }
c245cf4
 
c245cf4
 } /*** lm_lmpar. ***/
c245cf4
 
c245cf4
-/******************************************************************************/
c245cf4
-/*  lm_qrfac (QR factorization, from lapack)                                  */
c245cf4
-/******************************************************************************/
c245cf4
+/*****************************************************************************/
c245cf4
+/*  lm_qrfac (QR factorization, from lapack)                                 */
c245cf4
+/*****************************************************************************/
c245cf4
 
c245cf4
-static void lm_qrfac(const int m, const int n, double* A, int* Pivot, double* Rdiag,
c245cf4
-                     double* Acnorm, double* W)
c245cf4
+void lm_qrfac(
c245cf4
+    const int m, const int n, double *const A, int *const Pivot,
c245cf4
+    double *const Rdiag, double *const Acnorm, double *const W)
c245cf4
+{
c245cf4
 /*
c245cf4
  *     This subroutine uses Householder transformations with column pivoting
c245cf4
  *     to compute a QR factorization of the m by n matrix A. That is, qrfac
c245cf4
@@ -772,27 +850,27 @@
c245cf4
  *
c245cf4
  *      n is an INPUT parameter set to the number of columns of A.
c245cf4
  *
c245cf4
- *      A is an m by n array. On INPUT, A contains the matrix for which the
c245cf4
- *        QR factorization is to be computed. On OUTPUT the strict upper
c245cf4
- *        trapezoidal part of A contains the strict upper trapezoidal part
c245cf4
- *        of R, and the lower trapezoidal part of A contains a factored form
c245cf4
- *        of Q (the non-trivial elements of the vectors w described above).
c245cf4
+ *      A is an m by n array. On INPUT, A contains the matrix for
c245cf4
+ *        which the QR factorization is to be computed. On OUTPUT
c245cf4
+ *        the strict upper trapezoidal part of A contains the strict
c245cf4
+ *        upper trapezoidal part of R, and the lower trapezoidal
c245cf4
+ *        part of A contains a factored form of Q (the non-trivial
c245cf4
+ *        elements of the vectors w described above).
c245cf4
  *
c245cf4
  *      Pivot is an integer OUTPUT array of length n that describes the
c245cf4
- *        permutation matrix P. Column j of P is column Pivot(j) of the
c245cf4
- *        identity matrix.
c245cf4
+ *        permutation matrix P:
c245cf4
+ *        Column j of P is column ipvt(j) of the identity matrix.
c245cf4
  *
c245cf4
- *      Rdiag is an OUTPUT array of length n which contains the diagonal
c245cf4
- *        elements of R.
c245cf4
+ *      Rdiag is an OUTPUT array of length n which contains the
c245cf4
+ *        diagonal elements of R.
c245cf4
  *
c245cf4
- *      Acnorm is an OUTPUT array of length n which contains the norms of
c245cf4
- *        the corresponding columns of the input matrix A. If this information
c245cf4
- *        is not needed, then Acnorm can share storage with Rdiag.
c245cf4
+ *      Acnorm is an OUTPUT array of length n which contains the norms
c245cf4
+ *        of the corresponding columns of the input matrix A. If this
c245cf4
+ *        information is not needed, then Acnorm can share storage with Rdiag.
c245cf4
  *
c245cf4
  *      W is a work array of length n.
c245cf4
  *
c245cf4
  */
c245cf4
-{
c245cf4
     int i, j, k, kmax;
c245cf4
     double ajnorm, sum, temp;
c245cf4
 
c245cf4
@@ -802,16 +880,19 @@
c245cf4
 
c245cf4
     /** Compute initial column norms;
c245cf4
         initialize Pivot with identity permutation. ***/
c245cf4
+
c245cf4
     for (j = 0; j < n; j++) {
c245cf4
         W[j] = Rdiag[j] = Acnorm[j] = lm_enorm(m, &A[j*m]);
c245cf4
         Pivot[j] = j;
c245cf4
     }
c245cf4
 
c245cf4
     /** Loop over columns of A. **/
c245cf4
-    assert(n <= m);
c245cf4
+
c245cf4
+    assert( n <= m );
c245cf4
     for (j = 0; j < n; j++) {
c245cf4
 
c245cf4
         /** Bring the column of largest norm into the pivot position. **/
c245cf4
+
c245cf4
         kmax = j;
c245cf4
         for (k = j+1; k < n; k++)
c245cf4
             if (Rdiag[k] > Rdiag[kmax])
c245cf4
@@ -834,6 +915,7 @@
c245cf4
 
c245cf4
         /** Compute the Householder reflection vector w_j to reduce the
c245cf4
             j-th column of A to a multiple of the j-th unit vector. **/
c245cf4
+
c245cf4
         ajnorm = lm_enorm(m-j, &A[j*m+j]);
c245cf4
         if (ajnorm == 0) {
c245cf4
             Rdiag[j] = 0;
c245cf4
@@ -850,6 +932,7 @@
c245cf4
 
c245cf4
         /** Apply the Householder transformation U_w := 1 - 2*w_j.w_j/|w_j|^2
c245cf4
             to the remaining columns, and update the norms. **/
c245cf4
+
c245cf4
         for (k = j+1; k < n; k++) {
c245cf4
             /* Compute scalar product w_j * a_j. */
c245cf4
             sum = 0;
c245cf4
@@ -866,12 +949,12 @@
c245cf4
             /* No idea what happens here. */
c245cf4
             if (Rdiag[k] != 0) {
c245cf4
                 temp = A[m*k+j] / Rdiag[k];
c245cf4
-                if (fabs(temp) < 1) {
c245cf4
-                    Rdiag[k] *= sqrt(1 - SQR(temp));
c245cf4
+                if ( fabs(temp)<1 ) {
c245cf4
+                    Rdiag[k] *= sqrt(1-SQR(temp));
c245cf4
                     temp = Rdiag[k] / W[k];
c245cf4
                 } else
c245cf4
                     temp = 0;
c245cf4
-                if (temp == 0 || 0.05 * SQR(temp) <= LM_MACHEP) {
c245cf4
+                if ( temp == 0 || 0.05 * SQR(temp) <= LM_MACHEP ) {
c245cf4
                     Rdiag[k] = lm_enorm(m-j-1, &A[m*k+j+1]);
c245cf4
                     W[k] = Rdiag[k];
c245cf4
                 }
c245cf4
@@ -882,13 +965,16 @@
c245cf4
     }
c245cf4
 } /*** lm_qrfac. ***/
c245cf4
 
c245cf4
-/******************************************************************************/
c245cf4
-/*  lm_qrsolv (linear least-squares)                                          */
c245cf4
-/******************************************************************************/
c245cf4
 
c245cf4
-static void lm_qrsolv(const int n, double* r, const int ldr, const int* Pivot,
c245cf4
-                      const double* diag, const double* qtb, double* x,
c245cf4
-                      double* Sdiag, double* W)
c245cf4
+/*****************************************************************************/
c245cf4
+/*  lm_qrsolv (linear least-squares)                                         */
c245cf4
+/*****************************************************************************/
c245cf4
+
c245cf4
+void lm_qrsolv(
c245cf4
+    const int n, double *const r, const int ldr, int *const ipvt,
c245cf4
+    double *const diag, double *const qtb, double *const x,
c245cf4
+    double *const sdiag, double *const wa)
c245cf4
+{
c245cf4
 /*
c245cf4
  *     Given an m by n matrix A, an n by n diagonal matrix D, and an
c245cf4
  *     m-vector b, the problem is to determine an x which solves the
c245cf4
@@ -921,145 +1007,152 @@
c245cf4
  *
c245cf4
  *      n is a positive integer INPUT variable set to the order of R.
c245cf4
  *
c245cf4
- *      r is an n by n array. On INPUT the full upper triangle must contain
c245cf4
- *        the full upper triangle of the matrix R. On OUTPUT the full upper
c245cf4
- *        triangle is unaltered, and the strict lower triangle contains the
c245cf4
- *        strict upper triangle (transposed) of the upper triangular matrix S.
c245cf4
+ *      r is an n by n array. On INPUT the full upper triangle must
c245cf4
+ *        contain the full upper triangle of the matrix R. On OUTPUT
c245cf4
+ *        the full upper triangle is unaltered, and the strict lower
c245cf4
+ *        triangle contains the strict upper triangle (transposed) of
c245cf4
+ *        the upper triangular matrix S.
c245cf4
  *
c245cf4
- *      ldr is a positive integer INPUT variable not less than n which
c245cf4
- *        specifies the leading dimension of the array R.
c245cf4
+ *      ldr is a positive integer INPUT variable not less than n
c245cf4
+ *        which specifies the leading dimension of the array R.
c245cf4
  *
c245cf4
- *      Pivot is an integer INPUT array of length n which defines the
c245cf4
- *        permutation matrix P such that A*P = Q*R. Column j of P is column
c245cf4
- *        Pivot(j) of the identity matrix.
c245cf4
+ *      ipvt is an integer INPUT array of length n which defines the
c245cf4
+ *        permutation matrix P such that A*P = Q*R. Column j of P
c245cf4
+ *        is column ipvt(j) of the identity matrix.
c245cf4
  *
c245cf4
- *      diag is an INPUT array of length n which must contain the diagonal
c245cf4
- *        elements of the matrix D.
c245cf4
+ *      diag is an INPUT array of length n which must contain the
c245cf4
+ *        diagonal elements of the matrix D.
c245cf4
  *
c245cf4
  *      qtb is an INPUT array of length n which must contain the first
c245cf4
  *        n elements of the vector Q^T*b.
c245cf4
  *
c245cf4
- *      x is an OUTPUT array of length n which contains the least-squares
c245cf4
- *        solution of the system A*x = b, D*x = 0.
c245cf4
+ *      x is an OUTPUT array of length n which contains the least
c245cf4
+ *        squares solution of the system A*x = b, D*x = 0.
c245cf4
  *
c245cf4
- *      Sdiag is an OUTPUT array of length n which contains the diagonal
c245cf4
- *        elements of the upper triangular matrix S.
c245cf4
+ *      sdiag is an OUTPUT array of length n which contains the
c245cf4
+ *        diagonal elements of the upper triangular matrix S.
c245cf4
  *
c245cf4
- *      W is a work array of length n.
c245cf4
+ *      wa is a work array of length n.
c245cf4
  *
c245cf4
  */
c245cf4
-{
c245cf4
     int i, kk, j, k, nsing;
c245cf4
     double qtbpj, sum, temp;
c245cf4
     double _sin, _cos, _tan, _cot; /* local variables, not functions */
c245cf4
 
c245cf4
-    /*** Copy R and Q^T*b to preserve input and initialize S.
c245cf4
-         In particular, save the diagonal elements of R in x. ***/
c245cf4
+/*** qrsolv: copy R and Q^T*b to preserve input and initialize S.
c245cf4
+     In particular, save the diagonal elements of R in x. ***/
c245cf4
 
c245cf4
     for (j = 0; j < n; j++) {
c245cf4
         for (i = j; i < n; i++)
c245cf4
-            r[j*ldr+i] = r[i*ldr+j];
c245cf4
-        x[j] = r[j*ldr+j];
c245cf4
-        W[j] = qtb[j];
c245cf4
+            r[j * ldr + i] = r[i * ldr + j];
c245cf4
+        x[j] = r[j * ldr + j];
c245cf4
+        wa[j] = qtb[j];
c245cf4
     }
c245cf4
 
c245cf4
-    /*** Eliminate the diagonal matrix D using a Givens rotation. ***/
c245cf4
+/*** qrsolv: eliminate the diagonal matrix D using a Givens rotation. ***/
c245cf4
 
c245cf4
     for (j = 0; j < n; j++) {
c245cf4
 
c245cf4
-        /*** Prepare the row of D to be eliminated, locating the diagonal
c245cf4
-             element using P from the QR factorization. ***/
c245cf4
+/*** qrsolv: prepare the row of D to be eliminated, locating the
c245cf4
+     diagonal element using P from the QR factorization. ***/
c245cf4
 
c245cf4
-        if (diag[Pivot[j]] != 0) {
c245cf4
-            for (k = j; k < n; k++)
c245cf4
-                Sdiag[k] = 0;
c245cf4
-            Sdiag[j] = diag[Pivot[j]];
c245cf4
+        if (diag[ipvt[j]] == 0)
c245cf4
+            goto L90;
c245cf4
+        for (k = j; k < n; k++)
c245cf4
+            sdiag[k] = 0;
c245cf4
+        sdiag[j] = diag[ipvt[j]];
c245cf4
 
c245cf4
-            /*** The transformations to eliminate the row of D modify only
c245cf4
-                 a single element of Q^T*b beyond the first n, which is
c245cf4
-                 initially 0. ***/
c245cf4
+/*** qrsolv: the transformations to eliminate the row of D modify only
c245cf4
+     a single element of Q^T*b beyond the first n, which is initially 0. ***/
c245cf4
 
c245cf4
-            qtbpj = 0;
c245cf4
-            for (k = j; k < n; k++) {
c245cf4
+        qtbpj = 0;
c245cf4
+        for (k = j; k < n; k++) {
c245cf4
 
c245cf4
-                /** Determine a Givens rotation which eliminates the
c245cf4
-                    appropriate element in the current row of D. **/
c245cf4
-                if (Sdiag[k] == 0)
c245cf4
-                    continue;
c245cf4
-                kk = k + ldr * k;
c245cf4
-                if (fabs(r[kk]) < fabs(Sdiag[k])) {
c245cf4
-                    _cot = r[kk] / Sdiag[k];
c245cf4
-                    _sin = 1 / hypot(1, _cot);
c245cf4
-                    _cos = _sin * _cot;
c245cf4
-                } else {
c245cf4
-                    _tan = Sdiag[k] / r[kk];
c245cf4
-                    _cos = 1 / hypot(1, _tan);
c245cf4
-                    _sin = _cos * _tan;
c245cf4
-                }
c245cf4
+            /** determine a Givens rotation which eliminates the
c245cf4
+                appropriate element in the current row of D. **/
c245cf4
 
c245cf4
-                /** Compute the modified diagonal element of R and
c245cf4
-                    the modified element of (Q^T*b,0). **/
c245cf4
-                r[kk] = _cos * r[kk] + _sin * Sdiag[k];
c245cf4
-                temp = _cos * W[k] + _sin * qtbpj;
c245cf4
-                qtbpj = -_sin * W[k] + _cos * qtbpj;
c245cf4
-                W[k] = temp;
c245cf4
+            if (sdiag[k] == 0)
c245cf4
+                continue;
c245cf4
+            kk = k + ldr * k;
c245cf4
+            if (fabs(r[kk]) < fabs(sdiag[k])) {
c245cf4
+                _cot = r[kk] / sdiag[k];
c245cf4
+                _sin = 1 / sqrt(1 + SQR(_cot));
c245cf4
+                _cos = _sin * _cot;
c245cf4
+            } else {
c245cf4
+                _tan = sdiag[k] / r[kk];
c245cf4
+                _cos = 1 / sqrt(1 + SQR(_tan));
c245cf4
+                _sin = _cos * _tan;
c245cf4
+            }
c245cf4
 
c245cf4
-                /** Accumulate the tranformation in the row of S. **/
c245cf4
-                for (i = k+1; i < n; i++) {
c245cf4
-                    temp = _cos * r[k*ldr+i] + _sin * Sdiag[i];
c245cf4
-                    Sdiag[i] = -_sin * r[k*ldr+i] + _cos * Sdiag[i];
c245cf4
-                    r[k*ldr+i] = temp;
c245cf4
-                }
c245cf4
+            /** compute the modified diagonal element of R and
c245cf4
+                the modified element of (Q^T*b,0). **/
c245cf4
+
c245cf4
+            r[kk] = _cos * r[kk] + _sin * sdiag[k];
c245cf4
+            temp = _cos * wa[k] + _sin * qtbpj;
c245cf4
+            qtbpj = -_sin * wa[k] + _cos * qtbpj;
c245cf4
+            wa[k] = temp;
c245cf4
+
c245cf4
+            /** accumulate the tranformation in the row of S. **/
c245cf4
+
c245cf4
+            for (i = k + 1; i < n; i++) {
c245cf4
+                temp = _cos * r[k * ldr + i] + _sin * sdiag[i];
c245cf4
+                sdiag[i] = -_sin * r[k * ldr + i] + _cos * sdiag[i];
c245cf4
+                r[k * ldr + i] = temp;
c245cf4
             }
c245cf4
         }
c245cf4
 
c245cf4
-        /** Store the diagonal element of S and restore
c245cf4
+      L90:
c245cf4
+        /** store the diagonal element of S and restore
c245cf4
             the corresponding diagonal element of R. **/
c245cf4
-        Sdiag[j] = r[j*ldr+j];
c245cf4
-        r[j*ldr+j] = x[j];
c245cf4
+
c245cf4
+        sdiag[j] = r[j * ldr + j];
c245cf4
+        r[j * ldr + j] = x[j];
c245cf4
     }
c245cf4
 
c245cf4
-    /*** Solve the triangular system for z. If the system is singular, then
c245cf4
-        obtain a least-squares solution. ***/
c245cf4
+/*** qrsolv: solve the triangular system for z. If the system is
c245cf4
+     singular, then obtain a least squares solution. ***/
c245cf4
 
c245cf4
     nsing = n;
c245cf4
     for (j = 0; j < n; j++) {
c245cf4
-        if (Sdiag[j] == 0 && nsing == n)
c245cf4
+        if (sdiag[j] == 0 && nsing == n)
c245cf4
             nsing = j;
c245cf4
         if (nsing < n)
c245cf4
-            W[j] = 0;
c245cf4
+            wa[j] = 0;
c245cf4
     }
c245cf4
 
c245cf4
-    for (j = nsing-1; j >= 0; j--) {
c245cf4
+    for (j = nsing - 1; j >= 0; j--) {
c245cf4
         sum = 0;
c245cf4
-        for (i = j+1; i < nsing; i++)
c245cf4
-            sum += r[j*ldr+i] * W[i];
c245cf4
-        W[j] = (W[j] - sum) / Sdiag[j];
c245cf4
+        for (i = j + 1; i < nsing; i++)
c245cf4
+            sum += r[j * ldr + i] * wa[i];
c245cf4
+        wa[j] = (wa[j] - sum) / sdiag[j];
c245cf4
     }
c245cf4
 
c245cf4
-    /*** Permute the components of z back to components of x. ***/
c245cf4
+/*** qrsolv: permute the components of z back to components of x. ***/
c245cf4
 
c245cf4
     for (j = 0; j < n; j++)
c245cf4
-        x[Pivot[j]] = W[j];
c245cf4
+        x[ipvt[j]] = wa[j];
c245cf4
 
c245cf4
 } /*** lm_qrsolv. ***/
c245cf4
 
c245cf4
-/******************************************************************************/
c245cf4
-/*  lm_enorm (Euclidean norm)                                                 */
c245cf4
-/******************************************************************************/
c245cf4
 
c245cf4
-static double lm_enorm(int n, const double* x)
c245cf4
+/*****************************************************************************/
c245cf4
+/*  lm_enorm (Euclidean norm)                                                */
c245cf4
+/*****************************************************************************/
c245cf4
+
c245cf4
+double lm_enorm(const int n, const double *const x)
c245cf4
+{
c245cf4
 /*     This function calculates the Euclidean norm of an n-vector x.
c245cf4
  *
c245cf4
- *     The Euclidean norm is computed by accumulating the sum of squares
c245cf4
- *     in three different sums. The sums of squares for the small and large
c245cf4
- *     components are scaled so that no overflows occur. Non-destructive
c245cf4
- *     underflows are permitted. Underflows and overflows do not occur in
c245cf4
- *     the computation of the unscaled sum of squares for the intermediate
c245cf4
- *     components. The definitions of small, intermediate and large components
c245cf4
+ *     The Euclidean norm is computed by accumulating the sum of
c245cf4
+ *     squares in three different sums. The sums of squares for the
c245cf4
+ *     small and large components are scaled so that no overflows
c245cf4
+ *     occur. Non-destructive underflows are permitted. Underflows
c245cf4
+ *     and overflows do not occur in the computation of the unscaled
c245cf4
+ *     sum of squares for the intermediate components.
c245cf4
+ *     The definitions of small, intermediate and large components
c245cf4
  *     depend on two constants, LM_SQRT_DWARF and LM_SQRT_GIANT. The main
c245cf4
- *     restrictions on these constants are that LM_SQRT_DWARF**2 not underflow
c245cf4
- *     and LM_SQRT_GIANT**2 not overflow.
c245cf4
+ *     restrictions on these constants are that LM_SQRT_DWARF**2 not
c245cf4
+ *     underflow and LM_SQRT_GIANT**2 not overflow.
c245cf4
  *
c245cf4
  *     Parameters:
c245cf4
  *
c245cf4
@@ -1067,9 +1160,8 @@
c245cf4
  *
c245cf4
  *      x is an INPUT array of length n.
c245cf4
  */
c245cf4
-{
c245cf4
     int i;
c245cf4
-    double agiant, s1, s2, s3, xabs, x1max, x3max;
c245cf4
+    double agiant, s1, s2, s3, xabs, x1max, x3max, temp;
c245cf4
 
c245cf4
     s1 = 0;
c245cf4
     s2 = 0;
c245cf4
@@ -1078,27 +1170,33 @@
c245cf4
     x3max = 0;
c245cf4
     agiant = LM_SQRT_GIANT / n;
c245cf4
 
c245cf4
-    /** Sum squares. **/
c245cf4
+    /** sum squares. **/
c245cf4
+
c245cf4
     for (i = 0; i < n; i++) {
c245cf4
         xabs = fabs(x[i]);
c245cf4
         if (xabs > LM_SQRT_DWARF) {
c245cf4
-            if (xabs < agiant) {
c245cf4
-                s2 += SQR(xabs);
c245cf4
-            } else if (xabs > x1max) {
c245cf4
-                s1 = 1 + s1 * SQR(x1max / xabs);
c245cf4
+            if ( xabs < agiant ) {
c245cf4
+                s2 += xabs * xabs;
c245cf4
+            } else if ( xabs > x1max ) {
c245cf4
+                temp = x1max / xabs;
c245cf4
+                s1 = 1 + s1 * SQR(temp);
c245cf4
                 x1max = xabs;
c245cf4
             } else {
c245cf4
-                s1 += SQR(xabs / x1max);
c245cf4
+                temp = xabs / x1max;
c245cf4
+                s1 += SQR(temp);
c245cf4
             }
c245cf4
-        } else if (xabs > x3max) {
c245cf4
-            s3 = 1 + s3 * SQR(x3max / xabs);
c245cf4
+        } else if ( xabs > x3max ) {
c245cf4
+            temp = x3max / xabs;
c245cf4
+            s3 = 1 + s3 * SQR(temp);
c245cf4
             x3max = xabs;
c245cf4
         } else if (xabs != 0) {
c245cf4
-            s3 += SQR(xabs / x3max);
c245cf4
+            temp = xabs / x3max;
c245cf4
+            s3 += SQR(temp);
c245cf4
         }
c245cf4
     }
c245cf4
 
c245cf4
-    /** Calculate the norm. **/
c245cf4
+    /** calculation of norm. **/
c245cf4
+
c245cf4
     if (s1 != 0)
c245cf4
         return x1max * sqrt(s1 + (s2 / x1max) / x1max);
c245cf4
     else if (s2 != 0)
c245cf4
@@ -1110,3 +1208,80 @@
c245cf4
         return x3max * sqrt(s3);
c245cf4
 
c245cf4
 } /*** lm_enorm. ***/
c245cf4
+
c245cf4
+
c245cf4
+/*****************************************************************************/
c245cf4
+/*  lm_fnorm (Euclidean norm of difference)                                                */
c245cf4
+/*****************************************************************************/
c245cf4
+
c245cf4
+double lm_fnorm(const int n, const double *const x, const double *const y)
c245cf4
+{
c245cf4
+/*     This function calculates the Euclidean norm of an n-vector x-y.
c245cf4
+ *
c245cf4
+ *     The Euclidean norm is computed by accumulating the sum of
c245cf4
+ *     squares in three different sums. The sums of squares for the
c245cf4
+ *     small and large components are scaled so that no overflows
c245cf4
+ *     occur. Non-destructive underflows are permitted. Underflows
c245cf4
+ *     and overflows do not occur in the computation of the unscaled
c245cf4
+ *     sum of squares for the intermediate components.
c245cf4
+ *     The definitions of small, intermediate and large components
c245cf4
+ *     depend on two constants, LM_SQRT_DWARF and LM_SQRT_GIANT. The main
c245cf4
+ *     restrictions on these constants are that LM_SQRT_DWARF**2 not
c245cf4
+ *     underflow and LM_SQRT_GIANT**2 not overflow.
c245cf4
+ *
c245cf4
+ *     Parameters:
c245cf4
+ *
c245cf4
+ *      n is a positive integer INPUT variable.
c245cf4
+ *
c245cf4
+ *      x, y are INPUT arrays of length n.
c245cf4
+ */
c245cf4
+    if (!y)
c245cf4
+        return lm_enorm(n, x);
c245cf4
+    int i;
c245cf4
+    double agiant, s1, s2, s3, xabs, x1max, x3max, temp;
c245cf4
+
c245cf4
+    s1 = 0;
c245cf4
+    s2 = 0;
c245cf4
+    s3 = 0;
c245cf4
+    x1max = 0;
c245cf4
+    x3max = 0;
c245cf4
+    agiant = LM_SQRT_GIANT / n;
c245cf4
+
c245cf4
+    /** sum squares. **/
c245cf4
+
c245cf4
+    for (i = 0; i < n; i++) {
c245cf4
+        xabs = fabs(x[i]-y[i]);
c245cf4
+        if (xabs > LM_SQRT_DWARF) {
c245cf4
+            if ( xabs < agiant ) {
c245cf4
+                s2 += xabs * xabs;
c245cf4
+            } else if ( xabs > x1max ) {
c245cf4
+                temp = x1max / xabs;
c245cf4
+                s1 = 1 + s1 * SQR(temp);
c245cf4
+                x1max = xabs;
c245cf4
+            } else {
c245cf4
+                temp = xabs / x1max;
c245cf4
+                s1 += SQR(temp);
c245cf4
+            }
c245cf4
+        } else if ( xabs > x3max ) {
c245cf4
+            temp = x3max / xabs;
c245cf4
+            s3 = 1 + s3 * SQR(temp);
c245cf4
+            x3max = xabs;
c245cf4
+        } else if (xabs != 0) {
c245cf4
+            temp = xabs / x3max;
c245cf4
+            s3 += SQR(temp);
c245cf4
+        }
c245cf4
+    }
c245cf4
+
c245cf4
+    /** calculation of norm. **/
c245cf4
+
c245cf4
+    if (s1 != 0)
c245cf4
+        return x1max * sqrt(s1 + (s2 / x1max) / x1max);
c245cf4
+    else if (s2 != 0)
c245cf4
+        if (s2 >= x3max)
c245cf4
+            return sqrt(s2 * (1 + (x3max / s2) * (x3max * s3)));
c245cf4
+        else
c245cf4
+            return sqrt(x3max * ((s2 / x3max) + (x3max * s3)));
c245cf4
+    else
c245cf4
+        return x3max * sqrt(s3);
c245cf4
+
c245cf4
+} /*** lm_fnorm. ***/
c245cf4
diff --git a/src/external/lmfit/lmmin.h b/src/external/lmfit/lmmin.h
c245cf4
index 17b4880..d2ccfae 100644
c245cf4
--- a/src/external/lmfit/lmmin.h
c245cf4
+++ b/src/external/lmfit/lmmin.h
c245cf4
@@ -17,9 +17,15 @@
c245cf4
 
c245cf4
 #include "lmstruct.h"
c245cf4
 
c245cf4
-/*! \brief
c245cf4
- * Levenberg-Marquardt minimization.
c245cf4
- *
c245cf4
+/* Levenberg-Marquardt minimization. */
c245cf4
+void lmmin(
c245cf4
+    const int n_par, double* par, const int m_dat, const double* y,
c245cf4
+    const void* data,
c245cf4
+    void (*evaluate)(
c245cf4
+        const double* par, const int m_dat, const void* data,
c245cf4
+        double* fvec, int* userbreak),
c245cf4
+    const lm_control_struct* control, lm_status_struct* status);
c245cf4
+/*
c245cf4
  *   This routine contains the core algorithm of our library.
c245cf4
  *
c245cf4
  *   It minimizes the sum of the squares of m nonlinear functions
c245cf4
@@ -29,14 +35,16 @@
c245cf4
  *
c245cf4
  *   Parameters:
c245cf4
  *
c245cf4
- * \param[in] n_par The number of variables (INPUT, positive integer).
c245cf4
- * \param par The parameters to be fitted
c245cf4
- *      x is the solution vector (INPUT/OUTPUT, array of length n).
c245cf4
+ *      n_par is the number of variables (INPUT, positive integer).
c245cf4
+ *
c245cf4
+ *      par is the solution vector (INPUT/OUTPUT, array of length n).
c245cf4
  *        On input it must be set to an estimated solution.
c245cf4
  *        On output it yields the final estimate of the solution.
c245cf4
  *
c245cf4
- *      m is the number of functions to be minimized (INPUT, positive integer).
c245cf4
+ *      m_dat is the number of functions to be minimized (INPUT, positive integer).
c245cf4
  *        It must fulfill m>=n.
c245cf4
+ *
c245cf4
+ *      y contains data to be fitted. Use a null pointer if there are no data.
c245cf4
  *
c245cf4
  *      data is a pointer that is ignored by lmmin; it is however forwarded
c245cf4
  *        to the user-supplied functions evaluate and printout.
c245cf4
@@ -56,9 +64,9 @@
c245cf4
  *      status contains OUTPUT variables that inform about the fit result,
c245cf4
  *        as declared and explained in lmstruct.h
c245cf4
  */
c245cf4
-void lmmin( const int n_par, double *par, const int m_dat, const void *data,
c245cf4
-            void (*evaluate) (const double *par, const int m_dat, const void *data,
c245cf4
-                              double *fvec, int *userbreak),
c245cf4
-            const lm_control_struct *control, lm_status_struct *status );
c245cf4
+
c245cf4
+/* Refined calculation of Eucledian norm. */
c245cf4
+double lm_enorm(const int, const double*);
c245cf4
+double lm_fnorm(const int, const double*, const double*);
c245cf4
 
c245cf4
 #endif /* LMMIN_H */
c245cf4
diff --git a/src/external/lmfit/lmstruct.h b/src/external/lmfit/lmstruct.h
c245cf4
index d545ff1..1f513b3 100644
c245cf4
--- a/src/external/lmfit/lmstruct.h
c245cf4
+++ b/src/external/lmfit/lmstruct.h
c245cf4
@@ -39,23 +39,23 @@
c245cf4
                          stepbound itself. In most cases stepbound should lie
c245cf4
                          in the interval (0.1,100.0). Generally, the value
c245cf4
                          100.0 is recommended. */
c245cf4
-    int   patience;   /* Used to set the maximum number of function evaluations
c245cf4
+    int patience;     /* Used to set the maximum number of function evaluations
c245cf4
                          to patience*(number_of_parameters+1). */
c245cf4
-    int   scale_diag; /* If 1, the variables will be rescaled internally.
c245cf4
+    int scale_diag;   /* If 1, the vari