2026-01-26  Release 3
Summary:
* Change build system from handwritten Makefiles to CMake.
* Add support for NLopt SLSQP as the NLP solver. Make it the default in CMake.
* Add support for DONLP3 (reentrant C++ version of DONLP2) as the NLP solver.
* Add support for dynamic allocation so that problems can be loaded at runtime.
* Eliminate global/static variables to make BBOWDA fully reentrant.
* Add a reentrant, callback-driven procedural function interface to BBOWDA.
* Build a libbbowda library making that interface available as an API.
* Add a reentrant object-oriented C++ binding to BBOWDA (bbowdapp).
* Build a libbbowdapp library making that interface available as an API.
* Add Doxygen documentation for the public C and C++ API.
* Add Java and Python 3 bindings to BBOWDA (actually to bbowdapp) using SWIG.
* Add Sphinx documentation for the Python binding API.
* Add Javadoc documentation for the Java binding API.
* Automatically find system copies of lp_solve, Ipopt, NLopt, SWIG, Python 3,
  Sphinx, Java.
* Update license exception for new dependency licenses.
Full list of changes:
* Makefile, Makefile.ipopt: Delete. Replaced by CMakeLists.txt.
* CMakeLists.txt: New build system. Allows selecting the NLP solver with a flag
  instead of having 2 or 3 separate makefiles. Also finds libraries more
  portably. System copies of lp_solve, Ipopt (instead of a relative path to a
  build directory), and NLopt (new NLP solver option) are now located
  automatically. The default NLP solver is now NLopt SLSQP because it is the
  most efficient FOSS NLP solver for the low-dimensional NLPs (surrogate and
  density models) used in BBOWDA. DONLP2 has licensing issues (and
  CMakeLists.txt now warns about that), and Ipopt has performance issues, NLopt
  has neither.
* README.txt: Make much more verbose and document the CMake options.
* bbowda.kdev4: New KDevelop project.
* covar.c, covar.h: Replace static arrays with pointers, using macros casting
  them to pointers to C99 dynamically-sized arrays to handle the variable-size
  multi-dimensional arrays. Add alloc_covar method.
* eqconst.c, eqconst.h: Replace static arrays likewise. Make
  GLOBAL_SEARCH_IGNORES_EQ_CONSTRAINTS a variable instead of a #defined constant
  (i.e., check it with if instead of #ifdef).
* eval.c, eval.h, gmmem.c, gmmem.h, ipopt.c, userfu.c, nlopt.h: Replace static
  arrays likewise.
* probldim.h: Delete. The constants previously #defined here are now runtime
  variables declared extern in problem.h and defined in problem.c.
* problem.h: Declare extern variables for the former probldim.h constants.
  Replace static arrays likewise to covar.c etc. Declare init_problem method.
* problem.c: Implement the former probldim.h constants as C constants and retain
  the empty init_problem and the evaluate_F C function. That code is designed to
  be edited directly to implement a problem in C.
* main.c: Call init_problem() before init_points(). Adapt to the dimensions
  being variable. Call alloc_covar() before the optimization loop.
* download_donlp2.sh: New download script for donlp2_intv_dyn.
* nlp_nlopt.c, nlp_nlopt.h: New files. NLopt SLSQP backend.
* Rename userfu.c to nlp_donlp2.c, donlp2.h to nlp_donlp2.h, ipopt.c to
  nlp_ipopt.c, and ipopt.h to nlp_ipopt.h.
* nlpopt.h: Include nlp_nlopt.h instead of nlp_donlp2.h/nlp_ipopt.h if USE_NLOPT
  is defined (by CMakeLists.txt with the default -DNLP_SOLVER=NLopt).
* license.txt: Update for the new MUMPS license (CeCILL-C v1). Clarify the "or
  (at your option) any later version" clauses with an example explicitly
  mentioning that the EPL 2.0 used by the latest Ipopt is allowed. Update the
  license headers in all source files to match the license.txt changes.
* Move download_donlp2.sh, nlp_donlp2.c, nlp_donlp2.h, patches/donlp2-fmin.diff,
  and patches/donlp2-use-float.h.diff to a new nlp_donlp2/ directory, and the
  DONLP2 files extracted from donlp2_intv_dyn.tar.gz to a new
  nlp_donlp2/donlp2_intv_dyn/ sub directory.
* .gitignore: Update accordingly (ignore /nlp_donlp2/donlp2_intv_dyn/ instead of
   individual DONLP2 files under /.)
* Move nlp_ipopt.c, nlp_ipopt.h, patches/ipopt-fix-makefiles.diff, and
  patches/Makefile.inc to a new nlp_ipopt/ directory.
* Move nlp_nlopt.c, nlp_nlopt.h, and patches/nlopt-2.8.0-fix-slsqp.patch to a
  new nlp_nlopt/ directory.
* nlp_donlp2.h. nlp_ipopt.h, nlp_nlopt.h: Move declaration of solve_nlp to the
  common nlpopt.h. Convert the macro in nlp_donlp2.h to a real function in
  nlp_donlp2.c, also allowing to avoid exposing donlp2() and optite.
* nlp_*/nlp_*.c, nlpopt.h: Make the global variables optimum_x,
  optimization_problem, and ignore_constraints parameters of the solve_nlp
  function instead.
* nlp_donlp2/nlp_donlp2.c (solve_nlp): Save them to static variables so that the
  callbacks called by donlp2 (including user_init_size and user_init) can use
  them.
* nlp_ipopt/nlp_ipopt.c (eval_g_1, eval_jac_g_1, eval_h_1): Use the passed m
  instead of ignore_constraints and num_estimate_constraints.
* main.c: Adapt the calls accordingly.
* covar.c, covar.h, eqconst.c, eqconst.h, eval.c, eval.h, gmmem.c, gmmem.h,
  main.c, nlp_*/nlp_*.c, nlpopt.h: Move all the global and static variables
  (remaining after the above) to structs. Add the required structs as function
  arguments to the functions requiring them, and add new free_covar (covar.c),
  alloc_eqc_estimates, and free_eqc_estimates (eqconst.c) methods. Change the
  macros that typecast simple pointers to pointers to multi-dimensional
  variable-size arrays to take the struct pointer as an argument; C syntax
  unfortunately does not allow a macro to hide the typecast completely
  transparently for struct members, as was possible for the global variables.
  Adapt the calls and variable references accordingly to all these changes.
* gmmem.c (free_gmm): Also free the struct GMM itself (as for the newly
  added free_* methods).
* problem.h, problem.c (DIMX, DIMY, DIMY_EQ, NUMINITPTS, c, xlow, xup, Flow,
  Fup, initpts_p): Move these global variables to a new struct bbowda_problem.
  Lowercase the names (except Flow, Fup).
  (DIMX, DIMY, DIMY_EQ): Since these dimensions are used so frequently, add
  macros for them expanding to (problem->dimx) etc.
  (MAXPTS, DOUBLE OPTIMUM_TOL, GLOBAL_SEARCH_IGNORES_EQ_CONSTRAINTS,
  ESTIMATE_CONSTRAINT_TOL): Move these global variables to a new struct
  bbowda_params. Lowercase the names.
  (init_problem): Return a void *user_data for evaluate_F.
  (evaluate_F): Take new const struct bbowda_problem *problem and void
  *user_data arguments.
* problem.c, covar.c, covar.h, eqconst.c, eqconst.h, eval.c, eval.h, gmmem.c,
  gmmem.h, main.c, nlp_*/nlp_*.c, nlpopt.h: Pass const struct bbowda_problem
  *problem wherever needed (many places), and individual parameters from
  bbowda_params wherever those are needed.
* covar.c (build_local_regcovar_model, compare_yeq): Adapt to use qsort_r
  (POSIX) or qsort_s (W32/W64), needed to pass the problem pointer to the
  callback.
* eqconst.c, eqconst.h (compute_global_eq_cst_estimates_around): Always actually
  add the equality constraint estimates, let the caller handle the
  global_search_ignores_eq_constraints parameter. Return void instead of struct
  estimate_constraints * (see eqc_get_estimatec below).
  (eqc_get_estimatec): New function. Takes a struct eqc_estimates * and returns
  the corresponding struct estimate_constraints *.
* main.c (main): Only call compute_1st_global_eq_cst_estimates if
  !params->global_search_ignores_eq_constraints. Call eqc_get_estimatec
  explicitly and unconditionally. Pass NULL instead of eqc to new_point if
  params->global_search_ignores_eq_constraints so that it will not call
  compute_global_eq_cst_estimates_around.
* nlpopt.h, nlp_*/nlp_*.c (solve_nlp): Rename the void *problem_data argument to
  void *data to prevent a name conflict.
* nlp_nlopt/nlp_ipopt.c (solve_nlp): Rename the local variable problem to
  ipopt_problem to prevent a name conflict.
* nlp_nlopt/nlp_nlopt.c (solve_nlp): Use alloca instead of compound literals to
  allocate temporary user data structures. They need to live until the end of
  solve_nlp, not just the end of the nested scope. Rename the local variable
  problem to opt to prevent a name conflict.
* nlp_donlp3/donlp3_c_binding/{CMakeLists.txt,donlp3_c_binding.{cc,h}}: New
  files. C binding for DONLP3, the reentrant C++ version of DONLP2.
* nlp_donlp3/nlp_donlp3.c, nlp_donlp3/nlp_donlp3.h: New files. DONLP3 backend.
* CMakeLists.txt: Add support for it.
* nlpopt.h: Include nlp_donlp3.h instead of nlp_donlp2.h if USE_DONLP3 is
  defined (by CMakeLists.txt with -DNLP_SOLVER=donlp3).
* eval.c, eval.h (init_points, new_point, extrapolate_point): Add evaluate_F
  function pointer argument.
* main.c (main): Factor out a bbowda function. Include "bbowda.h".
  (enable_global_search, bbowda): Move to...
* bbowda.c: ... this new file.
  (bbowda): Take an additional evaluate_F function pointer argument and pass it
  to the eval.c functions.
* bbowda.h: New header file, declaring the bbowda function.
* CMakeLists.txt: Add bbowda.c to SOURCES.
* problem.h (struct bbowda_problem, struct bbowda_params): Move these structures
  to bbowda.h. They are part of the BBOWDA API and as such should be declared in
  bbowda.h.
* problem.c: Delete. Move its contents to...
* main.c: ...here. Do not include "problem.h". Make all functions except main
  static.
  (init_problem, evaluate_F): Do not use the DIMX, DIMY, and DIMY_EQ convenience
  macros defined in problem.h. These are considered internal to BBOWDA, the
  public API must not pollute the namespace that way. Just explicitly use
  problem->dimx, problem->dimy, resp. problem->dimy_eq instead.
* CMakeLists.txt: Remove problem.c from SOURCES. Replace reference to problem.c
  in a message with main.c.
* README.txt: Replace all references to problem.c with main.c.
* CMakeLists.txt: Build a libbbowda library and link the example exe to it.
* README.txt: Mention it in the "HOW_TO_USE" section.
* bbowda.h: Make C++-safe (add extern "C" {} #ifdef __cplusplus).
* main.c: Remove unused #include <math.h>.
* bbowdapp/bbowdapp.hh, bbowdapp/bbowdapp.cc: New files. Object-oriented C++
  binding for bbowda.
* bbowdapp/main.cc: New file, port of main.c to C++/bbowdapp.
* bbowdapp/CMakeLists.txt: New file. Builds libbbowdapp and bbowdapp_example.
* CMakeLists.txt: Add WITH_CXX option, defaulting to ON. Add BBOWDA_SHARED
  option replacing BUILD_SHARED_LIBS, so that it can be defined separately
  from BBOWDAPP_SHARED. (E.g., if you have only C++ client programs, you may
  want to define BBOWDA_SHARED=OFF and BBOWDAPP_SHARED=ON to get a single
  libbbowdapp.so statically linked to libbbowda.a.) Install libbbowda. Rename
  exe to bbowda_example and install it to ${CMAKE_INSTALL_BINDIR} instead of
  hardcoded bin. Add bbowdapp subdirectory if(WITH_CXX).
* README.txt: Update CMake options and rewrite "HOW TO USE" section.
* DOUBLE (taken from the NLP solver) replaced with plain double throughout the
  code, because it is always double in practice anyway (but CMakeLists.txt now
  makes CMake check it to be sure) and because implementation details of the
  underlying NLP solver should not be leaked in the API. This allows removing
  unnecessary #include "nlpopt.h" in many places.
* nlp_*/nlp_*.h: Do not #include NLP solver headers, #include them directly in
  nlp_*/nlp_*.c instead. They were needed only to provide DOUBLE, TRUE, FALSE.
* nlp_nlopt/nlp_nlopt.h: Remove #define DOUBLE Number, #define TRUE 1, and
  #define FALSE 0.
* bbowda.c: #include <stdbool.h> and replace TRUE with true, FALSE with false
  everywhere.
* eqconst.c: Remove no longer needed #undef TRUE and #undef FALSE.
* CMakeLists.txt: Add WITH_DOXYGEN option, defaulting to ON. If enabled, find
  Doxygen and use doxygen_add_docs to build the Doxygen documentation.
* bbowda.h: Add a Doxygen @mainpage. Add Doxygen comments to everything in the
  public API.
* bbowdapp/bbowdapp.hh: Add Doxygen comments to everything in the public API.
  Add a normal comment to the private helper, not part of the API.
* CMakeLists.txt: If WITH_DOXYGEN, find PDFLaTeX and make, set
  DOXYGEN_GENERATE_LATEX to YES, and invoke make in the latex directory as a
  POST_BUILD command for the doc target.
*  bbowdapp/CMakeLists.txt: Add WITH_PYTHON and WITH_JAVA options, building the
   SWIG Python 3 resp. Java bindings for bbowdapp, defaulting to ON. Add a
   WITH_SWIG variable defined as (WITH_PYTHON OR WITH_JAVA), and if(WITH_SWIG),
   add_subdirectory(swig).
* README.txt: Document the new WITH_JAVA and WITH_PYTHON CMake flags.
* CMakeLists.txt: Reorder option statements for consistency.
* bbowdapp/bbowdapp.hh (OptimizationProblem::OptimizationProblem (both
  overloads)): Add optional argument copyVectors=true (whether to copy the
  vectors). Only enable the delegating template overload #if __cplusplus >=
  201103L, because delegating constructors are not available below C++11 (and
  copy&paste as an alternative is not desirable because we want the necessarily
  inline template to call the out-of-line normal constructor due to binary
  compatibility concerns).
  (OptimizationProblem::~OptimizationProblem): Add virtual destructor.
  (m_freeVectors): New private member variable of type bool.
* bbowdapp/bbowdapp.cc (dvecdup): New static helper function. Duplicates a
  double[] array with specified dimension.
  (OptimizationProblem::OptimizationProblem): Add the copyVectors argument to
  match the prototype in bbowdapp.h. if (copyVectors), call dvecdup on all the
  passed double[] arguments (with their expected dimensions) before setting the
  inherited bbowda_problem members to them. Initialize m_freeVectors to
  copyVectors.
  (OptimizationProblem::~OptimizationProblem): if (m_freeVectors), delete[] all
  the double[] members inherited from bbowda_problem.
* bbowdapp/main.cc (initpts_data): Use a 1D array of dimension [NUM_INIT_PTS *
  DIM_X] instead of a 2D array of dimensions [NUM_INIT_PTS][DIM_X]. That way,
  the example does not require C++11, and it does not really matter because the
  array is empty anyway.
  (Problem::Problem): Pass copyVectors=false to the superclass
  Bbowda::OptimizationProblem constructor, in order to opt out of the copying
  that is not needed here.
* bbowdapp/swig/CMakeLists.txt: New file. Builds the SWIG bindings and
  optionally (WITH_PYTHON_SPHINX and WITH_JAVA_JAVADOC options) the API
  documentation for them.
* bbowdapp/swig/glob_java.cmake: New file. Helper CMake script that is invoked
  at build (make) time, not at configure (cmake) time. It is invoked by an
  add_custom_command in the main bbowdapp/swig/CMakeLists.txt that calls cmake
  -P on it. Globs the *.java files produced by SWIG and writes the result to
  java_sources.txt.
* bbowdapp/swig/bbowda.i: New file. The SWIG interface file for the Java and
  Python bindings. Contains both common parts and parts under #ifdef SWIGJAVA
  resp. #ifdef SWIGPYTHON. Also contains Doxygen comments (for the SWIG Doxygen
  translation) and some manual Python docstrings and javadocs.
* bbowdapp/swig/bbowda-python.dist-info.in: New file. Template for
  bbowda-${BBOWDA_RELEASE}.dist-info.
* bbowdapp/swig/example.java: New file. Java port of the BBOWDA Rosenbrock
  example.
* bbowdapp/swig/example.java.mf: New file. MANIFEST.MF template for the example
  JAR (bbowda_java_example.jar). Specifies Class-Path: bbowda.jar.
* bbowdapp/swig/example.py: New file. Python port of the BBOWDA Rosenbrock
  example.
* main.c: Rename to example.c.
* bbowdapp/main.cc: Rename to example.cc.
* CMakeLists.txt, bbowdapp/CMakeLists.txt, README.txt: Update accordingly.
* buildscripts: New directory. Build scripts for portable JNI binaries.
* bbowdapp/swig/cmake/FindSphinx.cmake: Import from
  https://github.com/k0ekk0ek/cmake-sphinx. Merge LICENSE into this file. Add
  introductory comment. Fix the import line in the check for Sphinx extensions
  so that the check actually passes.
* bbowdapp/swig/sphinx/conf.py: New file. Configuration file for Sphinx.
* bbowdapp/swig/sphinx/index.rst: New file. Root document for Sphinx.
* CMakeLists.txt: Add option WITH_DOXYGEN_PDF, default OFF, and build the
  Doxygen LaTeX PDF only if it is ON.
* bbowdapp/swig/CMakeLists.txt: Add options WITH_JAVA_JAVADOC_PDF and
  WITH_PYTHON_SPHINX_PDF, default OFF, and build the Java Javadoc PDF resp. the
  Python Sphinx LaTeX PDF if the respective option is ON.
* README.txt: Document the new options.

2011-05-14  Release 2
* eval.c: fix missing #endif resulting from the code cleanup for the release
* patches/donlp2-fmin.diff: new patch, fixes donlp2 compilation
* Makefile, Makefile.ipopt: use the system lp_solve library
* eqconst.c: use #include <lp_lib.h> (system) instead of #include "lp_lib.h"
* patches/lpsolve-5.5-enable-debug.diff: drop, should be handled by the system
* patches/Makefile.inc: update for MUMPS 4.10.0
* patches/MUMPS-4.7.3-fix-uninitialized.diff: drop, fixed in newer MUMPS
* Makefile.ipopt: update to use Ipopt 3.9.3
* patches/ipopt-fix-makefiles.diff: update for Ipopt 3.9.3
* patches/ipopt-3.3.1-fix-with-mumps-dir.diff: drop, fixed in newer Ipopt
  Note: Use --with-mumps-lib="-LMUMPS_4.10.0/lib -ldmumps -lmumps_common -lpord
                              -LMUMPS_4.10.0/libseq -lmpiseq"
        --with-mumps-incdir="MUMPS_4.10.0/include -IMUMPS_4.10.0/libseq" instead
        of --with-mumps-dir with current versions of Ipopt.
  Another note: Use COIN_SKIP_PROJECTS=HSL to avoid building HSL stuff.
* licenses.txt: update reproduced copy of the MUMPS Conditions of Use
* licenses.txt, *.c, *.h: clarify that upstream's trivial changes to the MUMPS
                          Conditions of Use don't make them a different license
* licenses.txt, *.c, *.h: allow linking with code under the Eclipse Public
                          License, used by current versions of Ipopt

2007-11-15  Release 1
* initial release as documented in my diploma thesis
