#pragma once
/*
 *  $Id: nl-fitter.h 29758 2026-04-09 12:52:11Z yeti-dn $
 *  Copyright (C) 2000-2003 Martin Siler.
 *  Copyright (C) 2004-2026 David Necas (Yeti), Petr Klapetek.
 *  E-mail: yeti@gwyddion.net, klapetek@gwyddion.net.
 *
 *  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public
 *  License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any
 *  later version.
 *
 *  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 *  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 *  details.
 *
 *  You should have received a copy of the GNU General Public License along with this program; if not, write to the
 *  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#ifndef __GWY_NL_FITTER_H__
#define __GWY_NL_FITTER_H__

#include <glib.h>
#include <libgwyddion/utils.h>

G_BEGIN_DECLS

typedef enum {
    GWY_NLFIT_PARAM_ANGLE  = 1 << 0,
    GWY_NLFIT_PARAM_ABSVAL = 1 << 1,
} GwyNLFitParamFlags;

typedef  gdouble (*GwyNLFitFunc)(gdouble x,
                                 const gdouble *param,
                                 gpointer user_data,
                                 gboolean *success);

typedef  void (*GwyNLFitDerFunc)(gdouble x,
                                 const gdouble *param,
                                 const gboolean *fixed_param,
                                 GwyNLFitFunc func,
                                 gpointer user_data,
                                 gdouble *der,
                                 gboolean *success);

typedef  gdouble (*GwyNLFitIdxFunc)(guint i,
                                    const gdouble *param,
                                    gpointer user_data,
                                    gboolean *success);

typedef  void (*GwyNLFitIdxDiffFunc)(guint i,
                                     const gdouble *param,
                                     const gboolean *fixed_param,
                                     GwyNLFitIdxFunc func,
                                     gpointer user_data,
                                     gdouble *der,
                                     gboolean *success);

typedef struct _GwyNLFitter GwyNLFitter;

struct _GwyNLFitter {
    GwyNLFitFunc fmarq;  /* fitting function */
    GwyNLFitDerFunc dmarq;  /* fitting function derivations */
    gint maxiter;  /* max number of iterations */
    gboolean eval;  /* success? */
    gdouble *covar; /* covariance matrix  */
    gdouble dispersion; /* dispersion */
    gdouble mfi;    /* fitting parameters --
                       fi, decrease, increase of lambda, minimum lambda */
    gdouble mdec;
    gdouble minc;
    gdouble mtol;
};

GwyNLFitter*   gwy_nl_fitter_new               (GwyNLFitFunc func,
                                                GwyNLFitDerFunc diff);
GwyNLFitter*   gwy_nl_fitter_new_idx           (GwyNLFitIdxFunc func,
                                                GwyNLFitIdxDiffFunc diff);
void           gwy_nl_fitter_free              (GwyNLFitter *nlfit);
GwyNLFitter*   gwy_nl_fitter_copy              (GwyNLFitter *nlfit);
gdouble        gwy_nl_fitter_fit               (GwyNLFitter *nlfit,
                                                gint ndata,
                                                const gdouble *x,
                                                const gdouble *y,
                                                gint nparam,
                                                gdouble *param,
                                                gpointer user_data);
gdouble        gwy_nl_fitter_fit_full          (GwyNLFitter *nlfit,
                                                gint ndata,
                                                const gdouble *x,
                                                const gdouble *y,
                                                const gdouble *weight,
                                                gint nparam,
                                                gdouble *param,
                                                const gboolean *fixed_param,
                                                const gint *link_map,
                                                gpointer user_data);
gdouble        gwy_nl_fitter_fit_idx           (GwyNLFitter *nlfit,
                                                guint ndata,
                                                guint nparam,
                                                gdouble *param,
                                                gpointer user_data);
gdouble        gwy_nl_fitter_fit_idx_full      (GwyNLFitter *nlfit,
                                                guint ndata,
                                                guint nparam,
                                                gdouble *param,
                                                const gboolean *fixed_param,
                                                const gint *link_map,
                                                gpointer user_data);
gint           gwy_nl_fitter_get_max_iterations(GwyNLFitter *nlfit);
void           gwy_nl_fitter_set_max_iterations(GwyNLFitter *nlfit,
                                                gint maxiter);
gboolean       gwy_nl_fitter_succeeded         (GwyNLFitter *nlfit);
gdouble        gwy_nl_fitter_get_dispersion    (GwyNLFitter *nlfit);
gdouble        gwy_nl_fitter_get_correlations  (GwyNLFitter *nlfit,
                                                gint par1,
                                                gint par2);
gboolean       gwy_nl_fitter_get_eval          (GwyNLFitter *nlfit);
const gdouble* gwy_nl_fitter_get_covar         (GwyNLFitter *nlfit);
gint           gwy_nl_fitter_get_n_param       (GwyNLFitter *nlfit);
gdouble        gwy_nl_fitter_get_sigma         (GwyNLFitter *nlfit,
                                                gint par);
void           gwy_nl_fitter_set_callbacks     (GwyNLFitter *nlfit,
                                                GwySetFractionFunc set_fraction,
                                                GwySetMessageFunc set_message);
void           gwy_nl_fitter_diff              (gdouble x,
                                                gint nparam,
                                                const gdouble *param,
                                                const gboolean *fixed_param,
                                                GwyNLFitFunc func,
                                                gpointer user_data,
                                                gdouble *der,
                                                gboolean *success);
void           gwy_nl_fitter_diff_idx          (guint i,
                                                gint nparam,
                                                const gdouble *param,
                                                const gboolean *fixed_param,
                                                GwyNLFitIdxFunc func,
                                                gpointer user_data,
                                                gdouble *der,
                                                gboolean *success);
gint           gwy_nl_fitter_map_free_params   (const gboolean *fixed_param,
                                                gint n,
                                                gint *id_map);

G_END_DECLS

#endif

/* vim: set cin columns=120 tw=118 et ts=4 sw=4 cino=>1s,e0,n0,f0,{0,}0,^0,\:1s,=0,g1s,h0,t0,+1s,c3,(0,u0 : */
