varpro 0.14.0

A straightforward nonlinear least-squares fitting library which uses the Variable Projection algorithm.
Documentation
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/katex.min.css" integrity="sha384-zB1R0rpPzHqg7Kpt0Aljp8JPLqbXI3bhnPWROx27a9N0Ll6ZP/+DiW/UqRcLbRjq" crossorigin="anonymous">
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/katex.min.js" integrity="sha384-y23I5Q6l+B6vatafAwxRu/0oK/79VlbSz7Q9aiSZUvyWYIYsd+qj+o24G5ZU2zJz" crossorigin="anonymous"></script>
<style type="text/css">
.katex { font-size: 1.07em; }
</style>
<script>
    "use strict";
    document.addEventListener("DOMContentLoaded", function () {
              var maths = document.getElementsByClassName("language-math");
              for (var i=0; i<maths.length; i++) {
                            var el = maths[i];
                            katex.render(el.innerText, el, {displayMode: true});
    
              }

            // inline blocks
            document.querySelectorAll(':not(pre) > code').forEach((el) => {
                      let text = el.innerText;
                      if (!text.startsWith('$') || !text.endsWith('$')) {
                                  return;
                                }
                      let span = document.createElement("span");
                      katex.render(text.substr(1, text.length - 2), span, {displayMode: false, throwOnError: false});
                      el.parentNode.replaceChild(span, el);
                    });

            // comment in code
            document.querySelectorAll('pre span.comment').forEach((el) => {
                      let html = el.innerText;
                      let children = [];
                      let offset = 0;
                      [...html.matchAll(/(?:[^\$]|^)(\$(?:\\.|[^\$])+\$)(?!\$)/g)].forEach((match) => {
                                  let textBefore = html.substring(offset, match.index + 1);
                                  children.push(document.createTextNode(textBefore));
                                  let math = match[1].substring(1, match[1].length - 1);
                                  let span = document.createElement("span");
                                  katex.render(math, span, {displayMode: false, throwOnError: false});
                                  children.push(span);
                                  offset = match.index + match[0].length;
                                });
                      if (offset == 0) {
                                  return;
                                }
                      let textAfter = html.substring(offset);
                      if (textAfter.length > 0) {
                                  children.push(document.createTextNode(textAfter));
                                }
                      while (el.firstChild) { el.firstChild.remove(); }
                      children.forEach((child) => el.appendChild(child));
                    });
      });
</script>