File indexing completed on 2024-05-05 16:00:17

0001 /***************************************************************************
0002     File                 : FitTest.cpp
0003     Project              : LabPlot
0004     Description          : Tests for data fitting
0005     --------------------------------------------------------------------
0006     Copyright            : (C) 2017 Alexander Semke (alexander.semke@web.de)
0007     Copyright            : (C) 2018 Stefan Gerlach (stefan.gerlach@uni.kn)
0008  ***************************************************************************/
0009 
0010 /***************************************************************************
0011  *                                                                         *
0012  *  This program is free software; you can redistribute it and/or modify   *
0013  *  it under the terms of the GNU General Public License as published by   *
0014  *  the Free Software Foundation; either version 2 of the License, or      *
0015  *  (at your option) any later version.                                    *
0016  *                                                                         *
0017  *  This program is distributed in the hope that it will be useful,        *
0018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
0019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
0020  *  GNU General Public License for more details.                           *
0021  *                                                                         *
0022  *   You should have received a copy of the GNU General Public License     *
0023  *   along with this program; if not, write to the Free Software           *
0024  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
0025  *   Boston, MA  02110-1301  USA                                           *
0026  *                                                                         *
0027  ***************************************************************************/
0028 
0029 #include "FitTest.h"
0030 #include "backend/core/column/Column.h"
0031 #include "backend/worksheet/plots/cartesian/XYFitCurve.h"
0032 
0033 extern "C" {
0034 #include "backend/nsl/nsl_sf_stats.h"
0035 #include "backend/nsl/nsl_stats.h"
0036 }
0037 
0038 //##############################################################################
0039 //#################  linear regression with NIST datasets ######################
0040 //##############################################################################
0041 void FitTest::testLinearNorris() {
0042     //NIST data for Norris dataset
0043     QVector<double> xData = {0.2,337.4,118.2,884.6,10.1,226.5,666.3,996.3,448.6,777.0,558.2,0.4,0.6,775.5,666.9,338.0,447.5,11.6,556.0,228.1,
0044         995.8,887.6,120.2,0.3,0.3,556.8,339.1,887.2,999.0,779.0,11.1,118.3,229.2,669.1,448.9,0.5};
0045     QVector<double> yData = {0.1,338.8,118.1,888.0,9.2,228.1,668.5,998.5,449.1,778.9,559.2,0.3,0.1,778.1,668.8,339.3,448.9,10.8,557.7,228.3,
0046         998.0,888.8,119.6,0.3,0.6,557.6,339.3,888.0,998.5,778.9,10.2,117.6,228.9,668.4,449.2,0.2};
0047 
0048     //data source columns
0049     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
0050     xDataColumn.replaceValues(0, xData);
0051 
0052     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
0053     yDataColumn.replaceValues(0, yData);
0054 
0055     XYFitCurve fitCurve("fit");
0056     fitCurve.setXDataColumn(&xDataColumn);
0057     fitCurve.setYDataColumn(&yDataColumn);
0058 
0059     //prepare the fit
0060     XYFitCurve::FitData fitData = fitCurve.fitData();
0061     fitData.modelCategory = nsl_fit_model_basic;
0062     fitData.modelType = nsl_fit_model_polynomial;
0063     fitData.degree = 1;
0064     XYFitCurve::initFitData(fitData);
0065     fitCurve.setFitData(fitData);
0066 
0067     //perform the fit
0068     fitCurve.recalculate();
0069     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
0070 
0071     //check the results
0072     QCOMPARE(fitResult.available, true);
0073     QCOMPARE(fitResult.valid, true);
0074 
0075     const int np = fitData.paramNames.size();
0076     QCOMPARE(np, 2);
0077 
0078     QCOMPARE(fitResult.paramValues.at(0), -0.262323073774029);
0079     QCOMPARE(fitResult.errorValues.at(0), 0.232818234301152);
0080     QCOMPARE(fitResult.paramValues.at(1), 1.00211681802045);
0081     QCOMPARE(fitResult.errorValues.at(1), 0.429796848199937e-3);
0082 
0083     QCOMPARE(fitResult.rsd, 0.884796396144373);
0084     QCOMPARE(fitResult.rsquare, 0.999993745883712);
0085     QCOMPARE(fitResult.sse, 26.6173985294224);
0086     QCOMPARE(fitResult.rms, 0.782864662630069);
0087     DEBUG(std::setprecision(15) << fitResult.fdist_F);  // result: 5436385.54083098
0088     FuzzyCompare(fitResult.fdist_F, 5436385.54079785, 1.e-9);
0089 }
0090 
0091 void FitTest::testLinearPontius() {
0092     //NIST data for Pontius dataset
0093     QVector<int> xData = {150000,300000,450000,600000,750000,900000,1050000,1200000,1350000,1500000,1650000,1800000,1950000,2100000,
0094         2250000,2400000,2550000,2700000,2850000,3000000,150000,300000,450000,600000,750000,900000,1050000,1200000,1350000,1500000,
0095         1650000,1800000,1950000,2100000,2250000,2400000,2550000,2700000,2850000,3000000};
0096     QVector<double> yData = {.11019,.21956,.32949,.43899,.54803,.65694,.76562,.87487,.98292,1.09146,1.20001,1.30822,1.41599,1.52399,
0097         1.63194,1.73947,1.84646,1.95392,2.06128,2.16844,.11052,.22018,.32939,.43886,.54798,.65739,.76596,.87474,
0098         .98300,1.09150,1.20004,1.30818,1.41613,1.52408,1.63159,1.73965,1.84696,1.95445,2.06177,2.16829};
0099 
0100     //data source columns
0101     Column xDataColumn("x", AbstractColumn::ColumnMode::Integer);
0102     xDataColumn.replaceInteger(0, xData);
0103 
0104     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
0105     yDataColumn.replaceValues(0, yData);
0106 
0107     XYFitCurve fitCurve("fit");
0108     fitCurve.setXDataColumn(&xDataColumn);
0109     fitCurve.setYDataColumn(&yDataColumn);
0110 
0111     //prepare the fit
0112     XYFitCurve::FitData fitData = fitCurve.fitData();
0113     fitData.modelCategory = nsl_fit_model_basic;
0114     fitData.modelType = nsl_fit_model_polynomial;
0115     fitData.degree = 2;
0116     XYFitCurve::initFitData(fitData);
0117     fitCurve.setFitData(fitData);
0118 
0119     //perform the fit
0120     fitCurve.recalculate();
0121     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
0122 
0123     //check the results
0124     QCOMPARE(fitResult.available, true);
0125     QCOMPARE(fitResult.valid, true);
0126 
0127     const int np = fitData.paramNames.size();
0128     QCOMPARE(np, 3);
0129 
0130     QCOMPARE(fitResult.paramValues.at(0), 0.673565789473684e-3);
0131     QCOMPARE(fitResult.errorValues.at(0), 0.107938612033077e-3);
0132     QCOMPARE(fitResult.paramValues.at(1), 0.732059160401003e-6);
0133     QCOMPARE(fitResult.errorValues.at(1), 0.157817399981659e-9);
0134     QCOMPARE(fitResult.paramValues.at(2), -0.316081871345029e-14);
0135     QCOMPARE(fitResult.errorValues.at(2), 0.486652849992036e-16);
0136 
0137     QCOMPARE(fitResult.rsd, 0.205177424076185e-3);
0138     QCOMPARE(fitResult.rsquare, 0.999999900178537);
0139     QCOMPARE(fitResult.sse, 0.155761768796992e-5);
0140     QCOMPARE(fitResult.rms, 0.420977753505385e-7);
0141     DEBUG(std::setprecision(15) << fitResult.fdist_F);  // result: 185330865.884471
0142     FuzzyCompare(fitResult.fdist_F, 185330865.995752, 1.e-9);
0143 }
0144 
0145 void FitTest::testLinearNoInt1() {
0146     //NIST data for NoInt1 dataset
0147     QVector<int> xData = {60,61,62,63,64,65,66,67,68,69,70};
0148     QVector<int> yData = {130,131,132,133,134,135,136,137,138,139,140};
0149 
0150     //data source columns
0151     Column xDataColumn("x", AbstractColumn::ColumnMode::Integer);
0152     xDataColumn.replaceInteger(0, xData);
0153 
0154     Column yDataColumn("y", AbstractColumn::ColumnMode::Integer);
0155     yDataColumn.replaceInteger(0, yData);
0156 
0157     XYFitCurve fitCurve("fit");
0158     fitCurve.setXDataColumn(&xDataColumn);
0159     fitCurve.setYDataColumn(&yDataColumn);
0160 
0161     //prepare the fit
0162     XYFitCurve::FitData fitData = fitCurve.fitData();
0163     fitData.modelCategory = nsl_fit_model_custom;
0164     XYFitCurve::initFitData(fitData);
0165     fitData.model = "b1*x";
0166     fitData.paramNames << "b1";
0167     const int np = fitData.paramNames.size();
0168     fitData.paramStartValues << 1.;
0169     fitData.paramLowerLimits << -std::numeric_limits<double>::max();
0170     fitData.paramUpperLimits << std::numeric_limits<double>::max();
0171     //fitData.eps = 1.e-15;
0172     fitCurve.setFitData(fitData);
0173 
0174     //perform the fit
0175     fitCurve.recalculate();
0176     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
0177 
0178     //check the results
0179     QCOMPARE(fitResult.available, true);
0180     QCOMPARE(fitResult.valid, true);
0181 
0182     QCOMPARE(np, 1);
0183 
0184     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 2.07438016513166
0185     FuzzyCompare(fitResult.paramValues.at(0), 2.07438016528926, 1.e-9);
0186     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 0.0165289256079047
0187     FuzzyCompare(fitResult.errorValues.at(0), 0.165289256198347e-1, 1.e-9);
0188 
0189     QCOMPARE(fitResult.rsd, 3.56753034006338);
0190     QCOMPARE(fitResult.sse, 127.272727272727);
0191     QCOMPARE(fitResult.rms, 12.7272727272727);
0192     QCOMPARE(fitResult.rsquare, 0.999365492298663);
0193     DEBUG(std::setprecision(15) << fitResult.fdist_F);  // result: 15750.2500000027
0194     QCOMPARE(fitResult.fdist_F, 15750.25);
0195 }
0196 
0197 void FitTest::testLinearNoInt1_2() {
0198     //NIST data for NoInt1 dataset
0199     QVector<int> xData = {60,61,62,63,64,65,66,67,68,69,70};
0200     QVector<int> yData = {130,131,132,133,134,135,136,137,138,139,140};
0201 
0202     //data source columns
0203     Column xDataColumn("x", AbstractColumn::ColumnMode::Integer);
0204     xDataColumn.replaceInteger(0, xData);
0205 
0206     Column yDataColumn("y", AbstractColumn::ColumnMode::Integer);
0207     yDataColumn.replaceInteger(0, yData);
0208 
0209     XYFitCurve fitCurve("fit");
0210     fitCurve.setXDataColumn(&xDataColumn);
0211     fitCurve.setYDataColumn(&yDataColumn);
0212 
0213     //prepare the fit
0214     XYFitCurve::FitData fitData = fitCurve.fitData();
0215     fitData.modelCategory = nsl_fit_model_basic;
0216     fitData.modelType = nsl_fit_model_polynomial;
0217     fitData.degree = 1;
0218     XYFitCurve::initFitData(fitData);
0219     fitData.paramStartValues[0] = 0;
0220     fitData.paramFixed[0] = true;
0221     fitCurve.setFitData(fitData);
0222 
0223     //perform the fit
0224     fitCurve.recalculate();
0225     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
0226 
0227     //check the results
0228     QCOMPARE(fitResult.available, true);
0229     QCOMPARE(fitResult.valid, true);
0230 
0231     const int np = fitData.paramNames.size();
0232     QCOMPARE(np, 2);
0233 
0234     QCOMPARE(fitResult.paramValues.at(0), 0.);
0235     QCOMPARE(fitResult.paramValues.at(1), 2.07438016528926);
0236     QCOMPARE(fitResult.errorValues.at(1), 0.165289256198347e-1);
0237 
0238     QCOMPARE(fitResult.rsd, 3.56753034006338);
0239     QCOMPARE(fitResult.sse, 127.272727272727);
0240     QCOMPARE(fitResult.rms, 12.7272727272727);
0241     QCOMPARE(fitResult.rsquare, 0.999365492298663);
0242     DEBUG(std::setprecision(15) << fitResult.fdist_F);  // result: 15760.25
0243     QCOMPARE(fitResult.fdist_F, 15750.25);
0244 }
0245 
0246 void FitTest::testLinearNoInt2() {
0247     //NIST data for NoInt2 dataset
0248     QVector<int> xData = {4,5,6};
0249     QVector<int> yData = {3,4,4};
0250 
0251     //data source columns
0252     Column xDataColumn("x", AbstractColumn::ColumnMode::Integer);
0253     xDataColumn.replaceInteger(0, xData);
0254 
0255     Column yDataColumn("y", AbstractColumn::ColumnMode::Integer);
0256     yDataColumn.replaceInteger(0, yData);
0257 
0258     XYFitCurve fitCurve("fit");
0259     fitCurve.setXDataColumn(&xDataColumn);
0260     fitCurve.setYDataColumn(&yDataColumn);
0261 
0262     //prepare the fit
0263     XYFitCurve::FitData fitData = fitCurve.fitData();
0264     fitData.modelCategory = nsl_fit_model_custom;
0265     XYFitCurve::initFitData(fitData);
0266     fitData.model = "c * x";
0267     fitData.paramNames << "c";
0268     const int np = fitData.paramNames.size();
0269     fitData.paramStartValues << 1.;
0270     fitData.paramLowerLimits << -std::numeric_limits<double>::max();
0271     fitData.paramUpperLimits << std::numeric_limits<double>::max();
0272     //fitData.eps = 1.e-15;
0273     fitCurve.setFitData(fitData);
0274 
0275     //perform the fit
0276     fitCurve.recalculate();
0277     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
0278 
0279     //check the results
0280     QCOMPARE(fitResult.available, true);
0281     QCOMPARE(fitResult.valid, true);
0282 
0283     QCOMPARE(np, 1);
0284 
0285     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 0.727272727152573
0286     FuzzyCompare(fitResult.paramValues.at(0), 0.727272727272727, 1.e-9);
0287     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 0.0420827316561797
0288     FuzzyCompare(fitResult.errorValues.at(0), 0.420827318078432E-01, 1.e-8);
0289 
0290     QCOMPARE(fitResult.rsd, 0.369274472937998);
0291     QCOMPARE(fitResult.sse, 0.272727272727273);
0292     QCOMPARE(fitResult.rms, 0.136363636363636);
0293 // can not detect that intercept is zero for a custom linear model
0294     DEBUG(std::setprecision(15) << fitResult.rsquare);  // result: 0.590909090909091
0295 //  QCOMPARE(fitResult.rsquare, 0.993348115299335);
0296     DEBUG(std::setprecision(15) << fitResult.fdist_F);  // result: 2.88888888888889
0297 //  FuzzyCompare(fitResult.fdist_F, 298.666666666667, 1.);
0298 }
0299 
0300 void FitTest::testLinearNoInt2_2() {
0301     //NIST data for NoInt2 dataset
0302     QVector<int> xData = {4,5,6};
0303     QVector<int> yData = {3,4,4};
0304 
0305     //data source columns
0306     Column xDataColumn("x", AbstractColumn::ColumnMode::Integer);
0307     xDataColumn.replaceInteger(0, xData);
0308 
0309     Column yDataColumn("y", AbstractColumn::ColumnMode::Integer);
0310     yDataColumn.replaceInteger(0, yData);
0311 
0312     XYFitCurve fitCurve("fit");
0313     fitCurve.setXDataColumn(&xDataColumn);
0314     fitCurve.setYDataColumn(&yDataColumn);
0315 
0316     //prepare the fit
0317     XYFitCurve::FitData fitData = fitCurve.fitData();
0318     fitData.modelCategory = nsl_fit_model_basic;
0319     fitData.modelType = nsl_fit_model_polynomial;
0320     fitData.degree = 1;
0321     XYFitCurve::initFitData(fitData);
0322     fitData.paramStartValues[0] = 0;
0323     fitData.paramFixed[0] = true;
0324     fitCurve.setFitData(fitData);
0325 
0326     //perform the fit
0327     fitCurve.recalculate();
0328     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
0329 
0330     //check the results
0331     QCOMPARE(fitResult.available, true);
0332     QCOMPARE(fitResult.valid, true);
0333 
0334     const int np = fitData.paramNames.size();
0335     QCOMPARE(np, 2);
0336 
0337     QCOMPARE(fitResult.paramValues.at(0), 0.);
0338     QCOMPARE(fitResult.paramValues.at(1),  0.727272727272727);
0339     QCOMPARE(fitResult.errorValues.at(1), 0.420827318078432e-1);
0340 
0341     QCOMPARE(fitResult.rsd, 0.369274472937998);
0342     QCOMPARE(fitResult.sse, 0.272727272727273);
0343     QCOMPARE(fitResult.rms, 0.136363636363636);
0344     QCOMPARE(fitResult.rsquare, 0.993348115299335);
0345     DEBUG(std::setprecision(15) << fitResult.fdist_F);  // result: 300.666666666667
0346     QCOMPARE(fitResult.fdist_F, 298.666666666667);
0347 }
0348 
0349 void FitTest::testLinearFilip() {
0350     //NIST data for Filip dataset
0351     QVector<double> xData = {-6.860120914,-4.324130045,-4.358625055,-4.358426747,-6.955852379,-6.661145254,-6.355462942,-6.118102026,
0352         -7.115148017,-6.815308569,-6.519993057,-6.204119983,-5.853871964,-6.109523091,-5.79832982,-5.482672118,-5.171791386,-4.851705903,
0353         -4.517126416,-4.143573228,-3.709075441,-3.499489089,-6.300769497,-5.953504836,-5.642065153,-5.031376979,-4.680685696,-4.329846955,
0354         -3.928486195,-8.56735134,-8.363211311,-8.107682739,-7.823908741,-7.522878745,-7.218819279,-6.920818754,-6.628932138,-6.323946875,
0355         -5.991399828,-8.781464495,-8.663140179,-8.473531488,-8.247337057,-7.971428747,-7.676129393,-7.352812702,-7.072065318,-6.774174009,
0356         -6.478861916,-6.159517513,-6.835647144,-6.53165267,-6.224098421,-5.910094889,-5.598599459,-5.290645224,-4.974284616,-4.64454848,
0357         -4.290560426,-3.885055584,-3.408378962,-3.13200249,-8.726767166,-8.66695597,-8.511026475,-8.165388579,-7.886056648,-7.588043762,
0358         -7.283412422,-6.995678626,-6.691862621,-6.392544977,-6.067374056,-6.684029655,-6.378719832,-6.065855188,-5.752272167,-5.132414673,
0359         -4.811352704,-4.098269308,-3.66174277,-3.2644011};
0360     QVector<double> yData = {0.8116,0.9072,0.9052,0.9039,0.8053,0.8377,0.8667,0.8809,0.7975,0.8162,0.8515,0.8766,0.8885,0.8859,0.8959,0.8913,
0361         0.8959,0.8971,0.9021,0.909,0.9139,0.9199,0.8692,0.8872,0.89,0.891,0.8977,0.9035,0.9078,0.7675,0.7705,0.7713,0.7736,0.7775,0.7841,
0362         0.7971,0.8329,0.8641,0.8804,0.7668,0.7633,0.7678,0.7697,0.77,0.7749,0.7796,0.7897,0.8131,0.8498,0.8741,0.8061,0.846,0.8751,0.8856,
0363         0.8919,0.8934,0.894,0.8957,0.9047,0.9129,0.9209,0.9219,0.7739,0.7681,0.7665,0.7703,0.7702,0.7761,0.7809,0.7961,0.8253,0.8602,
0364         0.8809,0.8301,0.8664,0.8834,0.8898,0.8964,0.8963,0.9074,0.9119,0.9228};
0365 
0366     //data source columns
0367     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
0368     xDataColumn.replaceValues(0, xData);
0369 
0370     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
0371     yDataColumn.replaceValues(0, yData);
0372 
0373     XYFitCurve fitCurve("fit");
0374     fitCurve.setXDataColumn(&xDataColumn);
0375     fitCurve.setYDataColumn(&yDataColumn);
0376 
0377     //prepare the fit
0378     XYFitCurve::FitData fitData = fitCurve.fitData();
0379     fitData.modelCategory = nsl_fit_model_basic;
0380     fitData.modelType = nsl_fit_model_polynomial;
0381     fitData.degree = 10;
0382     fitData.eps = 1.e-8;
0383     XYFitCurve::initFitData(fitData);
0384     const int np = fitData.paramNames.size();
0385     fitCurve.setFitData(fitData);
0386 
0387     //perform the fit
0388     fitCurve.recalculate();
0389     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
0390 
0391     //check the results
0392     QCOMPARE(fitResult.available, true);
0393     QCOMPARE(fitResult.valid, true);
0394 
0395     QCOMPARE(np, 11);
0396 
0397     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: -1467.48962615175
0398     FuzzyCompare(fitResult.paramValues.at(0), -1467.48961422980, 1.e-5);
0399     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 298.084524514884
0400     FuzzyCompare(fitResult.errorValues.at(0), 298.084530995537, 1.e-7);
0401     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: -2772.1796150428
0402     FuzzyCompare(fitResult.paramValues.at(1), -2772.17959193342, 1.e-5);
0403     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 559.779853249694
0404     FuzzyCompare(fitResult.errorValues.at(1), 559.779865474950, 1.e-7);
0405     DEBUG(std::setprecision(15) << fitResult.paramValues.at(2));    // result: -2316.37110148409
0406     FuzzyCompare(fitResult.paramValues.at(2), -2316.37108160893, 1.e-5);
0407     DEBUG(std::setprecision(15) << fitResult.errorValues.at(2));    // result: 466.477561928144
0408     FuzzyCompare(fitResult.errorValues.at(2), 466.477572127796, 1.e-7);
0409     DEBUG(std::setprecision(15) << fitResult.paramValues.at(3));    // result: -1127.97395097195
0410     FuzzyCompare(fitResult.paramValues.at(3), -1127.97394098372, 1.e-5);
0411     DEBUG(std::setprecision(15) << fitResult.errorValues.at(3));    // result: 227.204269523115
0412     FuzzyCompare(fitResult.errorValues.at(3), 227.204274477751, 1.e-6);
0413     DEBUG(std::setprecision(15) << fitResult.paramValues.at(4));    // result: -354.478236951913
0414     FuzzyCompare(fitResult.paramValues.at(4), -354.478233703349, 1.e-5);
0415     DEBUG(std::setprecision(15) << fitResult.errorValues.at(4));    // result: 71.6478645361214
0416     FuzzyCompare(fitResult.errorValues.at(4), 71.6478660875927, 1.e-7);
0417     DEBUG(std::setprecision(15) << fitResult.paramValues.at(5));    // result: -75.1242024539908
0418     FuzzyCompare(fitResult.paramValues.at(5), -75.1242017393757, 1.e-5);
0419     DEBUG(std::setprecision(15) << fitResult.errorValues.at(5));    // result: 15.289717547564
0420     FuzzyCompare(fitResult.errorValues.at(5), 15.2897178747400, 1.e-7);
0421     DEBUG(std::setprecision(15) << fitResult.paramValues.at(6));    // result: -10.875318143236
0422     FuzzyCompare(fitResult.paramValues.at(6), -10.8753180355343, 1.e-5);
0423     DEBUG(std::setprecision(15) << fitResult.errorValues.at(6));    // result: 2.23691155110776
0424     FuzzyCompare(fitResult.errorValues.at(6), 2.23691159816033, 1.e-7);
0425     DEBUG(std::setprecision(15) << fitResult.paramValues.at(7));    // result: -1.06221499687347
0426     FuzzyCompare(fitResult.paramValues.at(7), -1.06221498588947, 1.e-5);
0427     DEBUG(std::setprecision(15) << fitResult.errorValues.at(7));    // result: 0.221624317377432
0428     FuzzyCompare(fitResult.errorValues.at(7), 0.221624321934227, 1.e-7);
0429     DEBUG(std::setprecision(15) << fitResult.paramValues.at(8));    // result: -0.0670191161850038
0430     FuzzyCompare(fitResult.paramValues.at(8), -0.670191154593408E-01, 1.e-5);
0431     DEBUG(std::setprecision(15) << fitResult.errorValues.at(8));    // result: 0.0142363760310402
0432     FuzzyCompare(fitResult.errorValues.at(8), 0.142363763154724E-01, 1.e-7);
0433     DEBUG(std::setprecision(15) << fitResult.paramValues.at(9));    // result: -0.00246781081080665
0434     FuzzyCompare(fitResult.paramValues.at(9), -0.246781078275479E-02, 1.e-5);
0435     DEBUG(std::setprecision(15) << fitResult.errorValues.at(9));    // result: 0.000535617398555022
0436     FuzzyCompare(fitResult.errorValues.at(9), 0.535617408889821E-03, 1.e-7);
0437     DEBUG(std::setprecision(15) << fitResult.paramValues.at(10));   // result: -4.02962529900222e-05
0438     FuzzyCompare(fitResult.paramValues.at(10), -0.402962525080404E-04, 1.e-5);
0439     DEBUG(std::setprecision(15) << fitResult.errorValues.at(10));   // result: 8.96632820770946e-06
0440     FuzzyCompare(fitResult.errorValues.at(10), 0.896632837373868E-05, 1.e-7);
0441 
0442     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 0.00334801050105949
0443     FuzzyCompare(fitResult.rsd, 0.334801051324544E-02, 1.e-7);
0444     DEBUG(std::setprecision(15) << fitResult.rsquare);  // result: 0.996727416209443
0445     FuzzyCompare(fitResult.rsquare, 0.996727416185620, 1.e-9);
0446     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 0.00079585137637953
0447     FuzzyCompare(fitResult.sse, 0.795851382172941E-03, 1.e-7);
0448     DEBUG(std::setprecision(15) << fitResult.rms);  // result: 1.12091743152047e-05
0449     FuzzyCompare(fitResult.rms, 0.112091743968020E-04, 1.e-7);
0450     DEBUG(std::setprecision(15) << fitResult.fdist_F);  // result: 2162.43960297897
0451     FuzzyCompare(fitResult.fdist_F, 2162.43954511489, 1.e-7);
0452 }
0453 
0454 
0455 void FitTest::testLinearWampler1() {
0456     //NIST data for Wampler1 dataset
0457     QVector<int> xData = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
0458     QVector<int> yData = {1,6,63,364,1365,3906,9331,19608,37449,66430,111111,
0459         177156,271453,402234,579195,813616,1118481,1508598,2000719,2613660,3368421};
0460 
0461     //data source columns
0462     Column xDataColumn("x", AbstractColumn::ColumnMode::Integer);
0463     xDataColumn.replaceInteger(0, xData);
0464 
0465     Column yDataColumn("y", AbstractColumn::ColumnMode::Integer);
0466     yDataColumn.replaceInteger(0, yData);
0467 
0468     XYFitCurve fitCurve("fit");
0469     fitCurve.setXDataColumn(&xDataColumn);
0470     fitCurve.setYDataColumn(&yDataColumn);
0471 
0472     //prepare the fit
0473     XYFitCurve::FitData fitData = fitCurve.fitData();
0474     fitData.modelCategory = nsl_fit_model_basic;
0475     fitData.modelType = nsl_fit_model_polynomial;
0476     fitData.degree = 5;
0477     XYFitCurve::initFitData(fitData);
0478     fitCurve.setFitData(fitData);
0479 
0480     //perform the fit
0481     fitCurve.recalculate();
0482     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
0483 
0484     //check the results
0485     QCOMPARE(fitResult.available, true);
0486     QCOMPARE(fitResult.valid, true);
0487 
0488     const int np = fitData.paramNames.size();
0489     QCOMPARE(np, 6);
0490 
0491     for (int i = 0; i < np; i++) {
0492         const double paramValue = fitResult.paramValues.at(i);
0493         const double errorValue = fitResult.errorValues.at(i);
0494         QCOMPARE(paramValue, 1.0);
0495         QCOMPARE(errorValue, 0.0);
0496     }
0497 
0498     QCOMPARE(fitResult.rsd, 0.0);
0499     QCOMPARE(fitResult.rsquare,  1.0);
0500     QCOMPARE(fitResult.sse, 0.0);
0501     QCOMPARE(fitResult.rms, 0.0);
0502     QVERIFY(std::isinf(fitResult.fdist_F));
0503 }
0504 
0505 void FitTest::testLinearWampler2() {
0506     //NIST data for Wampler2 dataset
0507     QVector<int> xData = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
0508     QVector<double> yData = {1.00000,1.11111,1.24992,1.42753,1.65984,1.96875,2.38336,2.94117,3.68928,4.68559,
0509         6.00000,7.71561,9.92992,12.75603,16.32384,20.78125,26.29536,33.05367,41.26528,51.16209,63.00000};
0510 
0511     //data source columns
0512     Column xDataColumn("x", AbstractColumn::ColumnMode::Integer);
0513     xDataColumn.replaceInteger(0, xData);
0514 
0515     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
0516     yDataColumn.replaceValues(0, yData);
0517 
0518     XYFitCurve fitCurve("fit");
0519     fitCurve.setXDataColumn(&xDataColumn);
0520     fitCurve.setYDataColumn(&yDataColumn);
0521 
0522     //prepare the fit
0523     XYFitCurve::FitData fitData = fitCurve.fitData();
0524     fitData.modelCategory = nsl_fit_model_basic;
0525     fitData.modelType = nsl_fit_model_polynomial;
0526     fitData.degree = 5;
0527     XYFitCurve::initFitData(fitData);
0528     fitCurve.setFitData(fitData);
0529 
0530     //perform the fit
0531     fitCurve.recalculate();
0532     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
0533 
0534     //check the results
0535     qDebug() << "STATUS " << fitResult.status;
0536     QCOMPARE(fitResult.available, true);
0537     QCOMPARE(fitResult.valid, true);
0538 
0539     const int np = fitData.paramNames.size();
0540     QCOMPARE(np, 6);
0541 
0542     for (int i = 0; i < np; i++) {
0543         DEBUG(std::setprecision(15) << fitResult.paramValues.at(i));
0544     }
0545     QCOMPARE(fitResult.paramValues.at(0), 1.0);
0546     QCOMPARE(fitResult.paramValues.at(1), 0.1);
0547     QCOMPARE(fitResult.paramValues.at(2), 0.01);
0548     QCOMPARE(fitResult.paramValues.at(3), 0.001);
0549     QCOMPARE(fitResult.paramValues.at(4), 0.0001);
0550     QCOMPARE(fitResult.paramValues.at(5), 0.00001);
0551     for (int i = 0; i < np; i++) {
0552         const double errorValue = fitResult.errorValues.at(i);
0553         DEBUG(std::setprecision(15) << errorValue); // max. result: 2.32794076549904e-15
0554         FuzzyCompare(errorValue, 0., 1.e-14);
0555     }
0556 
0557     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 2.32458538254974e-15
0558     FuzzyCompare(fitResult.rsd, 0., 1.e-14);
0559     QCOMPARE(fitResult.rsquare, 1.);
0560     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 8.1055458011459e-29
0561     FuzzyCompare(fitResult.sse, 0., 1.e-15);
0562     DEBUG(std::setprecision(15) << fitResult.rms);  // result: 5.40369720076393e-30
0563     FuzzyCompare(fitResult.rms, 0., 1.e-15);
0564     DEBUG(std::setprecision(15) << fitResult.fdist_F);  // result: 2.44385217688297e+32
0565     QVERIFY(fitResult.fdist_F > 1.e+32);
0566 }
0567 
0568 void FitTest::testLinearWampler3() {
0569     //NIST data for Wampler3 dataset
0570     QVector<int> xData = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
0571     QVector<double> yData = {760.,-2042.,2111.,-1684.,3888.,1858.,11379.,17560.,39287.,64382.,113159.,
0572         175108.,273291.,400186.,581243.,811568.,1121004.,1506550.,2002767.,2611612.,3369180.};
0573 
0574     //data source columns
0575     Column xDataColumn("x", AbstractColumn::ColumnMode::Integer);
0576     xDataColumn.replaceInteger(0, xData);
0577 
0578     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
0579     yDataColumn.replaceValues(0, yData);
0580 
0581     XYFitCurve fitCurve("fit");
0582     fitCurve.setXDataColumn(&xDataColumn);
0583     fitCurve.setYDataColumn(&yDataColumn);
0584 
0585     //prepare the fit
0586     XYFitCurve::FitData fitData = fitCurve.fitData();
0587     fitData.modelCategory = nsl_fit_model_basic;
0588     fitData.modelType = nsl_fit_model_polynomial;
0589     fitData.degree = 5;
0590     XYFitCurve::initFitData(fitData);
0591     fitCurve.setFitData(fitData);
0592 
0593     //perform the fit
0594     fitCurve.recalculate();
0595     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
0596 
0597     //check the results
0598     QCOMPARE(fitResult.available, true);
0599     QCOMPARE(fitResult.valid, true);
0600 
0601     const int np = fitData.paramNames.size();
0602     QCOMPARE(np, 6);
0603 
0604     for (int i = 0; i < np; i++) {
0605         const double paramValue = fitResult.paramValues.at(i);
0606         QCOMPARE(paramValue, 1.0);
0607     }
0608     QCOMPARE(fitResult.errorValues.at(0), 2152.32624678170);
0609     QCOMPARE(fitResult.errorValues.at(1), 2363.55173469681);
0610     QCOMPARE(fitResult.errorValues.at(2), 779.343524331583);
0611     QCOMPARE(fitResult.errorValues.at(3), 101.475507550350);
0612     QCOMPARE(fitResult.errorValues.at(4), 5.64566512170752);
0613     QCOMPARE(fitResult.errorValues.at(5), 0.112324854679312);
0614 
0615     QCOMPARE(fitResult.rsd, 2360.14502379268);
0616     QCOMPARE(fitResult.rsquare, 0.999995559025820);
0617     QCOMPARE(fitResult.sse, 83554268.0000000);
0618     QCOMPARE(fitResult.rms, 5570284.53333333);
0619     DEBUG(std::setprecision(15) << fitResult.fdist_F);  // result: 675524.458247789
0620     FuzzyCompare(fitResult.fdist_F, 675524.458240122, 1.e-7);
0621 }
0622 
0623 void FitTest::testLinearWampler4() {
0624     //NIST data for Wampler4 dataset
0625     QVector<int> xData = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
0626     QVector<int> yData = {75901,-204794,204863,-204436,253665,-200894,214131,-185192,221249,-138370,
0627         315911,-27644,455253,197434,783995,608816,1370781,1303798,2205519,2408860,3444321};
0628 
0629     //data source columns
0630     Column xDataColumn("x", AbstractColumn::ColumnMode::Integer);
0631     xDataColumn.replaceInteger(0, xData);
0632 
0633     Column yDataColumn("y", AbstractColumn::ColumnMode::Integer);
0634     yDataColumn.replaceInteger(0, yData);
0635 
0636     XYFitCurve fitCurve("fit");
0637     fitCurve.setXDataColumn(&xDataColumn);
0638     fitCurve.setYDataColumn(&yDataColumn);
0639 
0640     //prepare the fit
0641     XYFitCurve::FitData fitData = fitCurve.fitData();
0642     fitData.modelCategory = nsl_fit_model_basic;
0643     fitData.modelType = nsl_fit_model_polynomial;
0644     fitData.degree = 5;
0645     XYFitCurve::initFitData(fitData);
0646     fitCurve.setFitData(fitData);
0647 
0648     //perform the fit
0649     fitCurve.recalculate();
0650     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
0651 
0652     //check the results
0653     QCOMPARE(fitResult.available, true);
0654     QCOMPARE(fitResult.valid, true);
0655 
0656     const int np = fitData.paramNames.size();
0657     QCOMPARE(np, 6);
0658 
0659     FuzzyCompare(fitResult.paramValues.at(0), 1.0, 3.e-9);  // i386: 1.00000000223515
0660     FuzzyCompare(fitResult.paramValues.at(1), 1.0, 5.e-9);  // i386: 0.999999995021441
0661     FuzzyCompare(fitResult.paramValues.at(2), 1.0, 2.e-9);  // i386: 1.00000000188395
0662     FuzzyCompare(fitResult.paramValues.at(3), 1.0, 1.e-9);  // i386: 0.999999999743725
0663     FuzzyCompare(fitResult.paramValues.at(4), 1.0, 2.e-11); // i386: 1.00000000001441
0664     FuzzyCompare(fitResult.paramValues.at(5), 1.0);     // i386: 0.999999999999714
0665 
0666     QCOMPARE(fitResult.errorValues.at(0), 215232.624678170);
0667     QCOMPARE(fitResult.errorValues.at(1), 236355.173469681);
0668     QCOMPARE(fitResult.errorValues.at(2), 77934.3524331583);
0669     QCOMPARE(fitResult.errorValues.at(3), 10147.5507550350);
0670     QCOMPARE(fitResult.errorValues.at(4), 564.566512170752);
0671     QCOMPARE(fitResult.errorValues.at(5), 11.2324854679312);
0672 
0673     QCOMPARE(fitResult.rsd, 236014.502379268);
0674     QCOMPARE(fitResult.rsquare, 0.957478440825662);
0675     QCOMPARE(fitResult.sse, 835542680000.000);
0676     QCOMPARE(fitResult.rms, 55702845333.3333);
0677     DEBUG(std::setprecision(15) << fitResult.fdist_F);  // result: 67.5524458240122
0678     QCOMPARE(fitResult.fdist_F, 67.5524458240122);
0679 }
0680 
0681 void FitTest::testLinearWampler5() {
0682     //NIST data for Wampler5 dataset
0683     QVector<int> xData = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
0684     QVector<int> yData = {7590001,-20479994,20480063,-20479636,25231365,-20476094,20489331,-20460392,18417449,-20413570,
0685                 20591111,-20302844,18651453,-20077766,21059195,-19666384,26348481,-18971402,22480719,-17866340,10958421};
0686 
0687     //data source columns
0688     Column xDataColumn("x", AbstractColumn::ColumnMode::Integer);
0689     xDataColumn.replaceInteger(0, xData);
0690 
0691     Column yDataColumn("y", AbstractColumn::ColumnMode::Integer);
0692     yDataColumn.replaceInteger(0, yData);
0693 
0694     XYFitCurve fitCurve("fit");
0695     fitCurve.setXDataColumn(&xDataColumn);
0696     fitCurve.setYDataColumn(&yDataColumn);
0697 
0698     //prepare the fit
0699     XYFitCurve::FitData fitData = fitCurve.fitData();
0700     fitData.modelCategory = nsl_fit_model_basic;
0701     fitData.modelType = nsl_fit_model_polynomial;
0702     fitData.degree = 5;
0703     XYFitCurve::initFitData(fitData);
0704     fitCurve.setFitData(fitData);
0705 
0706     //perform the fit
0707     fitCurve.recalculate();
0708     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
0709 
0710     //check the results
0711     QCOMPARE(fitResult.available, true);
0712     QCOMPARE(fitResult.valid, true);
0713 
0714     const int np = fitData.paramNames.size();
0715     QCOMPARE(np, 6);
0716 
0717     for (int i = 0; i < np; i++) {
0718         const double paramValue = fitResult.paramValues.at(i);
0719         QCOMPARE(paramValue, 1.0);
0720     }
0721     QCOMPARE(fitResult.errorValues.at(0), 21523262.4678170);
0722     QCOMPARE(fitResult.errorValues.at(1), 23635517.3469681);
0723     QCOMPARE(fitResult.errorValues.at(2), 7793435.24331583);
0724     QCOMPARE(fitResult.errorValues.at(3), 1014755.07550350);
0725     QCOMPARE(fitResult.errorValues.at(4), 56456.6512170752);
0726     QCOMPARE(fitResult.errorValues.at(5), 1123.24854679312);
0727 
0728     QCOMPARE(fitResult.rsd, 23601450.2379268);
0729     QCOMPARE(fitResult.rsquare, 0.224668921574940E-02);
0730     QCOMPARE(fitResult.sse, 0.835542680000000E+16);
0731     QCOMPARE(fitResult.rms, 557028453333333.);
0732     DEBUG(std::setprecision(15) << fitResult.fdist_F);  // result: 0.00675524458240069
0733     QCOMPARE(fitResult.fdist_F, 0.675524458240122E-02);
0734 }
0735 
0736 // taken from https://en.wikipedia.org/wiki/Ordinary_least_squares
0737 void FitTest::testLinearWP_OLS() {
0738     //data from  The World Almanac and Book of Facts, 1975
0739     QVector<double> xData = {1.47, 1.50, 1.52, 1.55, 1.57, 1.60, 1.63, 1.65, 1.68, 1.70, 1.73, 1.75, 1.78, 1.80, 1.83};
0740     QVector<double> yData = {52.21, 53.12, 54.48, 55.84, 57.20, 58.57, 59.93, 61.29, 63.11, 64.47, 66.28, 68.10, 69.92, 72.19, 74.46};
0741 
0742     //data source columns
0743     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
0744     xDataColumn.replaceValues(0, xData);
0745 
0746     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
0747     yDataColumn.replaceValues(0, yData);
0748 
0749     XYFitCurve fitCurve("fit");
0750     fitCurve.setXDataColumn(&xDataColumn);
0751     fitCurve.setYDataColumn(&yDataColumn);
0752 
0753     //prepare the fit
0754     XYFitCurve::FitData fitData = fitCurve.fitData();
0755     fitData.modelCategory = nsl_fit_model_basic;
0756     fitData.modelType = nsl_fit_model_polynomial;
0757     fitData.degree = 2;
0758     XYFitCurve::initFitData(fitData);
0759     fitCurve.setFitData(fitData);
0760 
0761     //perform the fit
0762     fitCurve.recalculate();
0763     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
0764 
0765     //check the results
0766     QCOMPARE(fitResult.available, true);
0767     QCOMPARE(fitResult.valid, true);
0768 
0769     const int np = fitData.paramNames.size();
0770     QCOMPARE(np, 3);
0771 
0772     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 128.812803578436
0773     FuzzyCompare(fitResult.paramValues.at(0), 128.8128, 1.e-7);
0774     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 16.3082821390367
0775     FuzzyCompare(fitResult.errorValues.at(0), 16.3083, 1.e-5);
0776     DEBUG(std::setprecision(15) << fitResult.tdist_tValues.at(0));  // result: 7.89861264848368
0777     FuzzyCompare(fitResult.tdist_tValues.at(0), 7.8986, 1.e-5);
0778     DEBUG(std::setprecision(15) << fitResult.tdist_pValues.at(0));  // result: 4.28330815316414e-06
0779     FuzzyCompare(fitResult.tdist_pValues.at(0), 0., 1.e-5);
0780     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: -143.16202286476
0781     FuzzyCompare(fitResult.paramValues.at(1), -143.1620, 1.e-6);
0782     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 19.8331710430895
0783     FuzzyCompare(fitResult.errorValues.at(1), 19.8332, 1.e-5);
0784     DEBUG(std::setprecision(15) << fitResult.tdist_tValues.at(1));  // result: -7.21831231897945
0785     FuzzyCompare(fitResult.tdist_tValues.at(1), -7.2183, 1.e-5);
0786     DEBUG(std::setprecision(15) << fitResult.tdist_pValues.at(1));  // result: 1.05970640905074e-05
0787     FuzzyCompare(fitResult.tdist_pValues.at(1), 0., 2.e-5);
0788     DEBUG(std::setprecision(15) << fitResult.paramValues.at(2));    // result: 61.9603254424724
0789     FuzzyCompare(fitResult.paramValues.at(2), 61.9603, 1.e-6);
0790     DEBUG(std::setprecision(15) << fitResult.errorValues.at(2));    // result: 6.00842899301227
0791     FuzzyCompare(fitResult.errorValues.at(2), 6.0084, 1.e-5);
0792     DEBUG(std::setprecision(15) << fitResult.tdist_tValues.at(2));  // result: 10.3122339490958
0793     FuzzyCompare(fitResult.tdist_tValues.at(2), 10.3122, 1.e-5);
0794     DEBUG(std::setprecision(15) << fitResult.tdist_pValues.at(2));  // result: 2.56647515320682e-07
0795     FuzzyCompare(fitResult.tdist_pValues.at(2), 0., 1.e-6);
0796 
0797     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 0.25158650082898
0798     FuzzyCompare(fitResult.rsd, 0.2516, 1.e-4);
0799     DEBUG(std::setprecision(15) << fitResult.rsquare);  // result: 0.998904558436583
0800     FuzzyCompare(fitResult.rsquare, 0.9989, 1.e-5);
0801     DEBUG(std::setprecision(15) << fitResult.rsquareAdj);   // result: 0.99860580164656
0802     FuzzyCompare(fitResult.rsquareAdj, 0.9987, 1.e-4);
0803     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 0.759549208792447
0804     FuzzyCompare(fitResult.sse, 0.7595, 1.e-4);
0805 //  QCOMPARE(fitResult.rms, ???);   // result: 0.0632958
0806     DEBUG(std::setprecision(15) << fitResult.chisq_p);  // result: 0.999996987409119
0807 //  FuzzyCompare(fitResult.chisq_p, ???, 1.e-8);
0808     DEBUG(std::setprecision(15) << fitResult.fdist_F);  // result: 5471.2433330734
0809     FuzzyCompare(fitResult.fdist_F, 5471.2, 1.e-5);
0810     DEBUG(std::setprecision(15) << fitResult.fdist_p);  // result: 0.0
0811     QCOMPARE(fitResult.fdist_p, 0.0);
0812     DEBUG(std::setprecision(15) << fitResult.logLik);   // result: 1.0890247702592
0813     FuzzyCompare(fitResult.logLik, 1.0890, 3.e-5);
0814     DEBUG(std::setprecision(15) << fitResult.aic);  // result: 5.82195045948161
0815 // not reproducable
0816 //  FuzzyCompare(fitResult.aic, 0.2548, 2.e-6);
0817     DEBUG(std::setprecision(15) << fitResult.bic);  // result: 8.65415126389045
0818 // not reproducable
0819 //  FuzzyCompare(fitResult.bic, 0.3964, 2.e-6);
0820 }
0821 
0822 // from http://sia.webpopix.org/polynomialRegression1.html
0823 void FitTest::testLinearR_lm2() {
0824     QVector<int> xData = {4,4,7,7,8,9,10,10,10,11,11,12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,16,16,17,
0825         17,17,18,18,18,18,19,19,19,20,20,20,20,20,22,23,24,24,24,24,25};
0826     QVector<int> yData = {2,10,4,22,16,10,18,26,34,17,28,14,20,24,28,26,34,34,46,26,36,60,80,20,26,54,32,40,32,40,50,42,56,76,84,36,46,
0827                 68,32,48,52,56,64,66,54,70,92,93,120,85};
0828 
0829     //data source columns
0830     Column xDataColumn("x", AbstractColumn::ColumnMode::Integer);
0831     xDataColumn.replaceInteger(0, xData);
0832 
0833     Column yDataColumn("y", AbstractColumn::ColumnMode::Integer);
0834     yDataColumn.replaceInteger(0, yData);
0835 
0836     XYFitCurve fitCurve("fit");
0837     fitCurve.setXDataColumn(&xDataColumn);
0838     fitCurve.setYDataColumn(&yDataColumn);
0839 
0840     //prepare the fit
0841     XYFitCurve::FitData fitData = fitCurve.fitData();
0842     fitData.modelCategory = nsl_fit_model_basic;
0843     fitData.modelType = nsl_fit_model_polynomial;
0844     fitData.degree = 2;
0845     XYFitCurve::initFitData(fitData);
0846     fitCurve.setFitData(fitData);
0847 
0848     //perform the fit
0849     fitCurve.recalculate();
0850     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
0851 
0852     //check the results
0853     QCOMPARE(fitResult.available, true);
0854     QCOMPARE(fitResult.valid, true);
0855 
0856     const int np = fitData.paramNames.size();
0857     QCOMPARE(np, 3);
0858 
0859     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 2.47013778506623
0860     FuzzyCompare(fitResult.paramValues.at(0), 2.47014, 1.e-6);
0861     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 14.8171647250237
0862     FuzzyCompare(fitResult.errorValues.at(0), 14.81716, 1.e-6);
0863     DEBUG(std::setprecision(15) << fitResult.tdist_tValues.at(0));  // result: 0.16670785746848
0864     FuzzyCompare(fitResult.tdist_tValues.at(0), 0.167, 2.e-3);
0865     DEBUG(std::setprecision(15) << fitResult.tdist_pValues.at(0));  // result: 0.868315075848582
0866     FuzzyCompare(fitResult.tdist_pValues.at(0), 0.868, 1.e-3);
0867     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: 0.913287614242592
0868     FuzzyCompare(fitResult.paramValues.at(1), 0.91329, 1.e-5);
0869     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 2.03422044231195
0870     FuzzyCompare(fitResult.errorValues.at(1), 2.03422, 1.e-6);
0871     DEBUG(std::setprecision(15) << fitResult.tdist_tValues.at(1));  // result: 0.448961968548804
0872     FuzzyCompare(fitResult.tdist_tValues.at(1), 0.449, 1.e-4);
0873     DEBUG(std::setprecision(15) << fitResult.tdist_pValues.at(1));  // result: 0.655522449402813
0874     FuzzyCompare(fitResult.tdist_pValues.at(1), 0.656, 1.e-3);
0875     DEBUG(std::setprecision(15) << fitResult.paramValues.at(2));    // result: 0.0999593020698437
0876     FuzzyCompare(fitResult.paramValues.at(2), 0.09996, 1.e-5);
0877     DEBUG(std::setprecision(15) << fitResult.errorValues.at(2));    // result: 0.0659682106823392
0878     FuzzyCompare(fitResult.errorValues.at(2), 0.06597, 1.e-4);
0879     DEBUG(std::setprecision(15) << fitResult.tdist_tValues.at(2));  // result: 1.5152647166858
0880     FuzzyCompare(fitResult.tdist_tValues.at(2), 1.515, 1.e-3);
0881     DEBUG(std::setprecision(15) << fitResult.tdist_pValues.at(2));  // result: 0.136402432803739
0882     FuzzyCompare(fitResult.tdist_pValues.at(2), 0.136, 3.e-3);
0883 
0884     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 15.1760701243277
0885     FuzzyCompare(fitResult.rsd, 15.18, 1.e-3);
0886     DEBUG(std::setprecision(15) << fitResult.rsquare);  // result: 0.66733081652621
0887     FuzzyCompare(fitResult.rsquare, 0.6673, 1.e-4);
0888     DEBUG(std::setprecision(15) << fitResult.rsquareAdj);   // result: 0.645635000212702
0889     DEBUG(std::setprecision(15) << 1.-(1.-fitResult.rsquare)*(50.-1.)/(50.-np));    // result: 0.65317468105924
0890 // reference calculates 1-(1-R^2)(n-1)/(n-p)
0891     FuzzyCompare(1.-(1.-fitResult.rsquare)*(50.-1.)/(50.-np), 0.6532, 1.e-4);
0892     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 10824.71590767
0893     FuzzyCompare(fitResult.sse, 10825, 1.e-4);
0894     DEBUG(std::setprecision(15) << fitResult.rms);  // result: 230.313104418511
0895 //  QCOMPARE(fitResult.rms, ???);
0896     DEBUG(std::setprecision(15) << fitResult.logLik);   // result: -205.386034235309
0897     FuzzyCompare(fitResult.logLik, -205.386, 1.e-6);
0898     DEBUG(std::setprecision(15) << fitResult.chisq_p);  // result:
0899 //  FuzzyCompare(fitResult.chisq_p, ???, 1.e-8);
0900     DEBUG(std::setprecision(15) << fitResult.fdist_F);  // result:
0901 // reference calculates sst/rms/np
0902     DEBUG(std::setprecision(15) << fitResult.sst/fitResult.rms/np); // result: 47.0938320858956
0903     FuzzyCompare(fitResult.sst/fitResult.rms/np, 47.14, 1.e-3);
0904     DEBUG(std::setprecision(15) << fitResult.fdist_p);  // result: 0
0905     QCOMPARE(fitResult.fdist_p, 0.);        // exact: 5.852e-12
0906     DEBUG(std::setprecision(15) << fitResult.aic);  // result: 418.772068470618
0907     FuzzyCompare(fitResult.aic, 418.7721, 1.e-7);
0908     DEBUG(std::setprecision(15) << fitResult.bic);  // result: 426.42016049233
0909     FuzzyCompare(fitResult.bic, 426.4202, 1.e-7);
0910 }
0911 
0912 //##############################################################################
0913 //#############  non-linear regression with NIST datasets  #####################
0914 //##############################################################################
0915 
0916 void FitTest::testNonLinearMisra1a() {
0917     //NIST data for Misra1a dataset
0918     QVector<double> xData = {77.6E0,114.9E0,141.1E0,190.8E0,239.9E0,289.0E0,332.8E0,378.4E0,434.8E0,477.3E0,536.8E0,593.1E0,689.1E0,760.0E0};
0919     QVector<double> yData = {10.07E0,14.73E0,17.94E0,23.93E0,29.61E0,35.18E0,40.02E0,44.82E0,50.76E0,55.05E0,61.01E0,66.40E0,75.47E0,81.78E0};
0920 
0921     //data source columns
0922     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
0923     xDataColumn.replaceValues(0, xData);
0924 
0925     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
0926     yDataColumn.replaceValues(0, yData);
0927 
0928     XYFitCurve fitCurve("fit");
0929     fitCurve.setXDataColumn(&xDataColumn);
0930     fitCurve.setYDataColumn(&yDataColumn);
0931 
0932     //prepare the fit
0933     XYFitCurve::FitData fitData = fitCurve.fitData();
0934     fitData.modelCategory = nsl_fit_model_custom;
0935     XYFitCurve::initFitData(fitData);
0936     fitData.model = "b1*(1.-exp(-b2*x))";
0937     fitData.paramNames << "b1" << "b2";
0938     fitData.eps = 1.e-12;
0939     const int np = fitData.paramNames.size();
0940     fitData.paramStartValues << 500. << 0.0001;
0941     fitData.paramLowerLimits << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max();
0942     fitData.paramUpperLimits << std::numeric_limits<double>::max() << std::numeric_limits<double>::max();
0943     fitCurve.setFitData(fitData);
0944 
0945     //perform the fit
0946     fitCurve.recalculate();
0947     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
0948 
0949     //check the results
0950     QCOMPARE(fitResult.available, true);
0951     QCOMPARE(fitResult.valid, true);
0952 
0953     QCOMPARE(np, 2);
0954 
0955     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 238.942305251573
0956     FuzzyCompare(fitResult.paramValues.at(0), 2.3894212918E+02, 1.e-6);
0957     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 2.70651225218243
0958     FuzzyCompare(fitResult.errorValues.at(0), 2.7070075241E+00, 1.e-3);
0959     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: 0.000550155958419367
0960     FuzzyCompare(fitResult.paramValues.at(1), 5.5015643181E-04, 1.e-6);
0961     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 7.26565480949189e-06
0962     FuzzyCompare(fitResult.errorValues.at(1), 7.2668688436E-06, 1.e-3);
0963 
0964     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 0.101878763320394
0965     FuzzyCompare(fitResult.rsd, 1.0187876330E-01, 1.e-9);
0966     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 0.124551388988316
0967     FuzzyCompare(fitResult.sse, 1.2455138894E-01, 1.e-9);
0968 }
0969 
0970 void FitTest::testNonLinearMisra1a_2() {
0971     //NIST data for Misra1a dataset
0972     QVector<double> xData = {77.6E0,114.9E0,141.1E0,190.8E0,239.9E0,289.0E0,332.8E0,378.4E0,434.8E0,477.3E0,536.8E0,593.1E0,689.1E0,760.0E0};
0973     QVector<double> yData = {10.07E0,14.73E0,17.94E0,23.93E0,29.61E0,35.18E0,40.02E0,44.82E0,50.76E0,55.05E0,61.01E0,66.40E0,75.47E0,81.78E0};
0974 
0975     //data source columns
0976     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
0977     xDataColumn.replaceValues(0, xData);
0978 
0979     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
0980     yDataColumn.replaceValues(0, yData);
0981 
0982     XYFitCurve fitCurve("fit");
0983     fitCurve.setXDataColumn(&xDataColumn);
0984     fitCurve.setYDataColumn(&yDataColumn);
0985 
0986     //prepare the fit
0987     XYFitCurve::FitData fitData = fitCurve.fitData();
0988     fitData.modelCategory = nsl_fit_model_custom;
0989     XYFitCurve::initFitData(fitData);
0990     fitData.model = "b1*(1.-exp(-b2*x))";
0991     fitData.paramNames << "b1" << "b2";
0992     fitData.eps = 1.e-12;
0993     const int np = fitData.paramNames.size();
0994     fitData.paramStartValues << 250. << 5.e-4;
0995     fitData.paramLowerLimits << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max();
0996     fitData.paramUpperLimits << std::numeric_limits<double>::max() << std::numeric_limits<double>::max();
0997     fitCurve.setFitData(fitData);
0998 
0999     //perform the fit
1000     fitCurve.recalculate();
1001     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
1002 
1003     //check the results
1004     QCOMPARE(fitResult.available, true);
1005     QCOMPARE(fitResult.valid, true);
1006 
1007     QCOMPARE(np, 2);
1008 
1009     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 238.942305251573
1010     FuzzyCompare(fitResult.paramValues.at(0), 2.3894212918E+02, 1.e-6);
1011     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 2.70651225218243
1012     FuzzyCompare(fitResult.errorValues.at(0), 2.7070075241E+00, 1.e-3);
1013     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: 0.000550155958419367
1014     FuzzyCompare(fitResult.paramValues.at(1), 5.5015643181E-04, 1.e-6);
1015     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 7.26565480949189e-06
1016     FuzzyCompare(fitResult.errorValues.at(1), 7.2668688436E-06, 1.e-3);
1017 
1018     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 0.101878763320394
1019     FuzzyCompare(fitResult.rsd, 1.0187876330E-01, 1.e-9);
1020     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 0.124551388988316
1021     FuzzyCompare(fitResult.sse, 1.2455138894E-01, 1.e-9);
1022 }
1023 
1024 void FitTest::testNonLinearMisra1a_3() {
1025     //NIST data for Misra1a dataset
1026     QVector<double> xData = {77.6E0,114.9E0,141.1E0,190.8E0,239.9E0,289.0E0,332.8E0,378.4E0,434.8E0,477.3E0,536.8E0,593.1E0,689.1E0,760.0E0};
1027     QVector<double> yData = {10.07E0,14.73E0,17.94E0,23.93E0,29.61E0,35.18E0,40.02E0,44.82E0,50.76E0,55.05E0,61.01E0,66.40E0,75.47E0,81.78E0};
1028 
1029     //data source columns
1030     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
1031     xDataColumn.replaceValues(0, xData);
1032 
1033     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
1034     yDataColumn.replaceValues(0, yData);
1035 
1036     XYFitCurve fitCurve("fit");
1037     fitCurve.setXDataColumn(&xDataColumn);
1038     fitCurve.setYDataColumn(&yDataColumn);
1039 
1040     //prepare the fit
1041     XYFitCurve::FitData fitData = fitCurve.fitData();
1042     fitData.modelCategory = nsl_fit_model_custom;
1043     XYFitCurve::initFitData(fitData);
1044     fitData.model = "b1*(1.-exp(-b2*x))";
1045     fitData.paramNames << "b1" << "b2";
1046     fitData.eps = 1.e-12;
1047     const int np = fitData.paramNames.size();
1048     fitData.paramStartValues << 2.3894212918E+02 << 5.5015643181E-04;
1049     fitData.paramLowerLimits << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max();
1050     fitData.paramUpperLimits << std::numeric_limits<double>::max() << std::numeric_limits<double>::max();
1051     fitCurve.setFitData(fitData);
1052 
1053     //perform the fit
1054     fitCurve.recalculate();
1055     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
1056 
1057     //check the results
1058     QCOMPARE(fitResult.available, true);
1059     QCOMPARE(fitResult.valid, true);
1060 
1061     QCOMPARE(np, 2);
1062 
1063     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 238.942305251573
1064     FuzzyCompare(fitResult.paramValues.at(0), 2.3894212918E+02, 1.e-6);
1065     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 2.70651225218243
1066     FuzzyCompare(fitResult.errorValues.at(0), 2.7070075241E+00, 1.e-3);
1067     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: 0.000550155958419367
1068     FuzzyCompare(fitResult.paramValues.at(1), 5.5015643181E-04, 1.e-6);
1069     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 7.26565480949189e-06
1070     FuzzyCompare(fitResult.errorValues.at(1), 7.2668688436E-06, 1.e-3);
1071 
1072     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 0.101878763320394
1073     FuzzyCompare(fitResult.rsd, 1.0187876330E-01, 1.e-9);
1074     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 0.124551388988316
1075     FuzzyCompare(fitResult.sse, 1.2455138894E-01, 1.e-9);
1076 }
1077 
1078 
1079 void FitTest::testNonLinearMisra1b() {
1080     //NIST data for Misra1b dataset
1081     QVector<double> xData = {77.6E0,114.9E0,141.1E0,190.8E0,239.9E0,289.0E0,332.8E0,378.4E0,434.8E0,477.3E0,536.8E0,593.1E0,689.1E0,760.0E0};
1082     QVector<double> yData = {10.07E0,14.73E0,17.94E0,23.93E0,29.61E0,35.18E0,40.02E0,44.82E0,50.76E0,55.05E0,61.01E0,66.40E0,75.47E0,81.78E0};
1083 
1084     //data source columns
1085     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
1086     xDataColumn.replaceValues(0, xData);
1087 
1088     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
1089     yDataColumn.replaceValues(0, yData);
1090 
1091     XYFitCurve fitCurve("fit");
1092     fitCurve.setXDataColumn(&xDataColumn);
1093     fitCurve.setYDataColumn(&yDataColumn);
1094 
1095     //prepare the fit
1096     XYFitCurve::FitData fitData = fitCurve.fitData();
1097     fitData.modelCategory = nsl_fit_model_custom;
1098     XYFitCurve::initFitData(fitData);
1099     fitData.model = "b1*(1.-1./(1.+b2*x/2)^2)";
1100     fitData.paramNames << "b1" << "b2";
1101     fitData.eps = 1.e-12;
1102     const int np = fitData.paramNames.size();
1103     fitData.paramStartValues << 500. << 0.0001;
1104     fitData.paramLowerLimits << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max();
1105     fitData.paramUpperLimits << std::numeric_limits<double>::max() << std::numeric_limits<double>::max();
1106     fitCurve.setFitData(fitData);
1107 
1108     //perform the fit
1109     fitCurve.recalculate();
1110     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
1111 
1112     //check the results
1113     QCOMPARE(fitResult.available, true);
1114     QCOMPARE(fitResult.valid, true);
1115 
1116     QCOMPARE(np, 2);
1117 
1118     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 337.99775062098
1119     FuzzyCompare(fitResult.paramValues.at(0), 3.3799746163E+02, 1.e-6);
1120     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 3.16358581006192
1121     FuzzyCompare(fitResult.errorValues.at(0), 3.1643950207E+00, 1.e-3);
1122     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: 0.000390390523934039
1123     FuzzyCompare(fitResult.paramValues.at(1), 3.9039091287E-04, 1.e-6);
1124     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 4.25373670682006e-06
1125     FuzzyCompare(fitResult.errorValues.at(1), 4.2547321834E-06, 1.e-3);
1126 
1127     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 0.0793014720259488
1128     FuzzyCompare(fitResult.rsd, 7.9301471998E-02, 1.e-9);
1129     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 0.0754646815857881
1130     FuzzyCompare(fitResult.sse, 7.5464681533E-02, 1.e-9);
1131 }
1132 
1133 void FitTest::testNonLinearMisra1b_2() {
1134     //NIST data for Misra1b dataset
1135     QVector<double> xData = {77.6E0,114.9E0,141.1E0,190.8E0,239.9E0,289.0E0,332.8E0,378.4E0,434.8E0,477.3E0,536.8E0,593.1E0,689.1E0,760.0E0};
1136     QVector<double> yData = {10.07E0,14.73E0,17.94E0,23.93E0,29.61E0,35.18E0,40.02E0,44.82E0,50.76E0,55.05E0,61.01E0,66.40E0,75.47E0,81.78E0};
1137 
1138     //data source columns
1139     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
1140     xDataColumn.replaceValues(0, xData);
1141 
1142     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
1143     yDataColumn.replaceValues(0, yData);
1144 
1145     XYFitCurve fitCurve("fit");
1146     fitCurve.setXDataColumn(&xDataColumn);
1147     fitCurve.setYDataColumn(&yDataColumn);
1148 
1149     //prepare the fit
1150     XYFitCurve::FitData fitData = fitCurve.fitData();
1151     fitData.modelCategory = nsl_fit_model_custom;
1152     XYFitCurve::initFitData(fitData);
1153     fitData.model = "b1*(1.-1./(1.+b2*x/2)^2)";
1154     fitData.paramNames << "b1" << "b2";
1155     fitData.eps = 1.e-12;
1156     const int np = fitData.paramNames.size();
1157     fitData.paramStartValues << 300. << 2.e-4;
1158     fitData.paramLowerLimits << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max();
1159     fitData.paramUpperLimits << std::numeric_limits<double>::max() << std::numeric_limits<double>::max();
1160     fitCurve.setFitData(fitData);
1161 
1162     //perform the fit
1163     fitCurve.recalculate();
1164     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
1165 
1166     //check the results
1167     QCOMPARE(fitResult.available, true);
1168     QCOMPARE(fitResult.valid, true);
1169 
1170     QCOMPARE(np, 2);
1171 
1172     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 337.99775062098
1173     FuzzyCompare(fitResult.paramValues.at(0), 3.3799746163E+02, 1.e-6);
1174     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 3.16358581006192
1175     FuzzyCompare(fitResult.errorValues.at(0), 3.1643950207E+00, 1.e-3);
1176     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: 0.000390390523934039
1177     FuzzyCompare(fitResult.paramValues.at(1), 3.9039091287E-04, 1.e-5);
1178     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 4.25373670682006e-06
1179     FuzzyCompare(fitResult.errorValues.at(1), 4.2547321834E-06, 1.e-3);
1180 
1181     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 0.0793014720259488
1182     FuzzyCompare(fitResult.rsd, 7.9301471998E-02, 1.e-9);
1183     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 0.0754646815857881
1184     FuzzyCompare(fitResult.sse, 7.5464681533E-02, 1.e-9);
1185 }
1186 
1187 void FitTest::testNonLinearMisra1b_3() {
1188     //NIST data for Misra1b dataset
1189     QVector<double> xData = {77.6E0,114.9E0,141.1E0,190.8E0,239.9E0,289.0E0,332.8E0,378.4E0,434.8E0,477.3E0,536.8E0,593.1E0,689.1E0,760.0E0};
1190     QVector<double> yData = {10.07E0,14.73E0,17.94E0,23.93E0,29.61E0,35.18E0,40.02E0,44.82E0,50.76E0,55.05E0,61.01E0,66.40E0,75.47E0,81.78E0};
1191 
1192     //data source columns
1193     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
1194     xDataColumn.replaceValues(0, xData);
1195 
1196     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
1197     yDataColumn.replaceValues(0, yData);
1198 
1199     XYFitCurve fitCurve("fit");
1200     fitCurve.setXDataColumn(&xDataColumn);
1201     fitCurve.setYDataColumn(&yDataColumn);
1202 
1203     //prepare the fit
1204     XYFitCurve::FitData fitData = fitCurve.fitData();
1205     fitData.modelCategory = nsl_fit_model_custom;
1206     XYFitCurve::initFitData(fitData);
1207     fitData.model = "b1*(1.-1./(1.+b2*x/2)^2)";
1208     fitData.paramNames << "b1" << "b2";
1209     fitData.eps = 1.e-12;
1210     const int np = fitData.paramNames.size();
1211     fitData.paramStartValues << 3.3799746163E+02 << 3.9039091287E-04;
1212     fitData.paramLowerLimits << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max();
1213     fitData.paramUpperLimits << std::numeric_limits<double>::max() << std::numeric_limits<double>::max();
1214     fitCurve.setFitData(fitData);
1215 
1216     //perform the fit
1217     fitCurve.recalculate();
1218     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
1219 
1220     //check the results
1221     QCOMPARE(fitResult.available, true);
1222     QCOMPARE(fitResult.valid, true);
1223 
1224     QCOMPARE(np, 2);
1225 
1226     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 337.99775062098
1227     FuzzyCompare(fitResult.paramValues.at(0), 3.3799746163E+02, 1.e-6);
1228     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 3.16358581006192
1229     FuzzyCompare(fitResult.errorValues.at(0), 3.1643950207E+00, 1.e-3);
1230     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: 0.000390390523934039
1231     FuzzyCompare(fitResult.paramValues.at(1), 3.9039091287E-04, 1.e-6);
1232     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 4.25373670682006e-06
1233     FuzzyCompare(fitResult.errorValues.at(1), 4.2547321834E-06, 1.e-3);
1234 
1235     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 0.0793014720259488
1236     FuzzyCompare(fitResult.rsd, 7.9301471998E-02, 1.e-9);
1237     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 0.0754646815857881
1238     FuzzyCompare(fitResult.sse, 7.5464681533E-02, 1.e-9);
1239 }
1240 
1241 void FitTest::testNonLinearMisra1c() {
1242     //NIST data for Misra1c dataset
1243     QVector<double> xData = {77.6E0,114.9E0,141.1E0,190.8E0,239.9E0,289.0E0,332.8E0,378.4E0,434.8E0,477.3E0,536.8E0,593.1E0,689.1E0,760.0E0};
1244     QVector<double> yData = {10.07E0,14.73E0,17.94E0,23.93E0,29.61E0,35.18E0,40.02E0,44.82E0,50.76E0,55.05E0,61.01E0,66.40E0,75.47E0,81.78E0};
1245 
1246     //data source columns
1247     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
1248     xDataColumn.replaceValues(0, xData);
1249 
1250     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
1251     yDataColumn.replaceValues(0, yData);
1252 
1253     XYFitCurve fitCurve("fit");
1254     fitCurve.setXDataColumn(&xDataColumn);
1255     fitCurve.setYDataColumn(&yDataColumn);
1256 
1257     //prepare the fit
1258     XYFitCurve::FitData fitData = fitCurve.fitData();
1259     fitData.modelCategory = nsl_fit_model_custom;
1260     XYFitCurve::initFitData(fitData);
1261     fitData.model = "b1*(1.-1./sqrt(1.+2.*b2*x))";
1262     fitData.paramNames << "b1" << "b2";
1263     fitData.eps = 1.e-12;
1264     const int np = fitData.paramNames.size();
1265     fitData.paramStartValues << 500. << 0.0001;
1266     fitData.paramLowerLimits << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max();
1267     fitData.paramUpperLimits << std::numeric_limits<double>::max() << std::numeric_limits<double>::max();
1268     fitCurve.setFitData(fitData);
1269 
1270     //perform the fit
1271     fitCurve.recalculate();
1272     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
1273 
1274     //check the results
1275     QCOMPARE(fitResult.available, true);
1276     QCOMPARE(fitResult.valid, true);
1277 
1278     QCOMPARE(np, 2);
1279 
1280     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 636.427904767969
1281     FuzzyCompare(fitResult.paramValues.at(0), 6.3642725809E+02, 1.e-5);
1282     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 4.66168062054875
1283     FuzzyCompare(fitResult.errorValues.at(0), 4.6638326572E+00, 1.e-3);
1284     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: 0.000208136026420746
1285     FuzzyCompare(fitResult.paramValues.at(1), 2.0813627256E-04, 1.e-5);
1286     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 1.77209416674174e-06
1287     FuzzyCompare(fitResult.errorValues.at(1), 1.7728423155E-06, 1.e-3);
1288 
1289     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 0.0584286153041661
1290     FuzzyCompare(fitResult.rsd, 5.8428615257E-02, 1.e-9);
1291     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 0.0409668370363468
1292     FuzzyCompare(fitResult.sse, 4.0966836971E-02, 1.e-8);
1293 }
1294 
1295 void FitTest::testNonLinearMisra1c_2() {
1296     //NIST data for Misra1c dataset
1297     QVector<double> xData = {77.6E0,114.9E0,141.1E0,190.8E0,239.9E0,289.0E0,332.8E0,378.4E0,434.8E0,477.3E0,536.8E0,593.1E0,689.1E0,760.0E0};
1298     QVector<double> yData = {10.07E0,14.73E0,17.94E0,23.93E0,29.61E0,35.18E0,40.02E0,44.82E0,50.76E0,55.05E0,61.01E0,66.40E0,75.47E0,81.78E0};
1299 
1300     //data source columns
1301     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
1302     xDataColumn.replaceValues(0, xData);
1303 
1304     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
1305     yDataColumn.replaceValues(0, yData);
1306 
1307     XYFitCurve fitCurve("fit");
1308     fitCurve.setXDataColumn(&xDataColumn);
1309     fitCurve.setYDataColumn(&yDataColumn);
1310 
1311     //prepare the fit
1312     XYFitCurve::FitData fitData = fitCurve.fitData();
1313     fitData.modelCategory = nsl_fit_model_custom;
1314     XYFitCurve::initFitData(fitData);
1315     fitData.model = "b1*(1.-1./sqrt(1.+2.*b2*x))";
1316     fitData.paramNames << "b1" << "b2";
1317     fitData.eps = 1.e-12;
1318     const int np = fitData.paramNames.size();
1319     fitData.paramStartValues << 600. << 2.e-4;
1320     fitData.paramLowerLimits << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max();
1321     fitData.paramUpperLimits << std::numeric_limits<double>::max() << std::numeric_limits<double>::max();
1322     fitCurve.setFitData(fitData);
1323 
1324     //perform the fit
1325     fitCurve.recalculate();
1326     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
1327 
1328     //check the results
1329     QCOMPARE(fitResult.available, true);
1330     QCOMPARE(fitResult.valid, true);
1331 
1332     QCOMPARE(np, 2);
1333 
1334     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 636.427904767969
1335     FuzzyCompare(fitResult.paramValues.at(0), 6.3642725809E+02, 1.e-5);
1336     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 4.66168062054875
1337     FuzzyCompare(fitResult.errorValues.at(0), 4.6638326572E+00, 1.e-3);
1338     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: 0.000208136026420746
1339     FuzzyCompare(fitResult.paramValues.at(1), 2.0813627256E-04, 1.e-5);
1340     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 1.77209416674174e-06
1341     FuzzyCompare(fitResult.errorValues.at(1), 1.7728423155E-06, 1.e-3);
1342 
1343     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 0.0584286153041661   (WIN: 0.0584286153252961)
1344     FuzzyCompare(fitResult.rsd, 5.8428615257E-02, 1.e-8);
1345     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 0.0409668370363468
1346     FuzzyCompare(fitResult.sse, 4.0966836971E-02, 1.e-8);
1347 }
1348 
1349 void FitTest::testNonLinearMisra1c_3() {
1350     //NIST data for Misra1c dataset
1351     QVector<double> xData = {77.6E0,114.9E0,141.1E0,190.8E0,239.9E0,289.0E0,332.8E0,378.4E0,434.8E0,477.3E0,536.8E0,593.1E0,689.1E0,760.0E0};
1352     QVector<double> yData = {10.07E0,14.73E0,17.94E0,23.93E0,29.61E0,35.18E0,40.02E0,44.82E0,50.76E0,55.05E0,61.01E0,66.40E0,75.47E0,81.78E0};
1353 
1354     //data source columns
1355     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
1356     xDataColumn.replaceValues(0, xData);
1357 
1358     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
1359     yDataColumn.replaceValues(0, yData);
1360 
1361     XYFitCurve fitCurve("fit");
1362     fitCurve.setXDataColumn(&xDataColumn);
1363     fitCurve.setYDataColumn(&yDataColumn);
1364 
1365     //prepare the fit
1366     XYFitCurve::FitData fitData = fitCurve.fitData();
1367     fitData.modelCategory = nsl_fit_model_custom;
1368     XYFitCurve::initFitData(fitData);
1369     fitData.model = "b1*(1.-1./sqrt(1.+2.*b2*x))";
1370     fitData.paramNames << "b1" << "b2";
1371     fitData.eps = 1.e-12;
1372     const int np = fitData.paramNames.size();
1373     fitData.paramStartValues << 6.3642725809E+02 << 2.0813627256E-04;
1374     fitData.paramLowerLimits << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max();
1375     fitData.paramUpperLimits << std::numeric_limits<double>::max() << std::numeric_limits<double>::max();
1376     fitCurve.setFitData(fitData);
1377 
1378     //perform the fit
1379     fitCurve.recalculate();
1380     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
1381 
1382     //check the results
1383     QCOMPARE(fitResult.available, true);
1384     QCOMPARE(fitResult.valid, true);
1385 
1386     QCOMPARE(np, 2);
1387 
1388     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 636.427904767969
1389     FuzzyCompare(fitResult.paramValues.at(0), 6.3642725809E+02, 1.e-5);
1390     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 4.66168062054875
1391     FuzzyCompare(fitResult.errorValues.at(0), 4.6638326572E+00, 1.e-3);
1392     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: 0.000208136026420746
1393     FuzzyCompare(fitResult.paramValues.at(1), 2.0813627256E-04, 1.e-5);
1394     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 1.77209416674174e-06
1395     FuzzyCompare(fitResult.errorValues.at(1), 1.7728423155E-06, 1.e-3);
1396 
1397     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 0.0584286153041661
1398     FuzzyCompare(fitResult.rsd, 5.8428615257E-02, 1.e-9);
1399     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 0.0409668370363468
1400     FuzzyCompare(fitResult.sse, 4.0966836971E-02, 1.e-8);
1401 }
1402 
1403 void FitTest::testNonLinearMisra1d() {
1404     //NIST data for Misra1d dataset
1405     QVector<double> xData = {77.6E0,114.9E0,141.1E0,190.8E0,239.9E0,289.0E0,332.8E0,378.4E0,434.8E0,477.3E0,536.8E0,593.1E0,689.1E0,760.0E0};
1406     QVector<double> yData = {10.07E0,14.73E0,17.94E0,23.93E0,29.61E0,35.18E0,40.02E0,44.82E0,50.76E0,55.05E0,61.01E0,66.40E0,75.47E0,81.78E0};
1407 
1408     //data source columns
1409     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
1410     xDataColumn.replaceValues(0, xData);
1411 
1412     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
1413     yDataColumn.replaceValues(0, yData);
1414 
1415     XYFitCurve fitCurve("fit");
1416     fitCurve.setXDataColumn(&xDataColumn);
1417     fitCurve.setYDataColumn(&yDataColumn);
1418 
1419     //prepare the fit
1420     XYFitCurve::FitData fitData = fitCurve.fitData();
1421     fitData.modelCategory = nsl_fit_model_custom;
1422     XYFitCurve::initFitData(fitData);
1423     fitData.model = "b1*b2*x/(1.+b2*x)";
1424     fitData.paramNames << "b1" << "b2";
1425     fitData.eps = 1.e-12;
1426     const int np = fitData.paramNames.size();
1427     fitData.paramStartValues << 500. << 0.0001;
1428     fitData.paramLowerLimits << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max();
1429     fitData.paramUpperLimits << std::numeric_limits<double>::max() << std::numeric_limits<double>::max();
1430     fitCurve.setFitData(fitData);
1431 
1432     //perform the fit
1433     fitCurve.recalculate();
1434     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
1435 
1436     //check the results
1437     QCOMPARE(fitResult.available, true);
1438     QCOMPARE(fitResult.valid, true);
1439 
1440     QCOMPARE(np, 2);
1441 
1442     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 437.370039987725
1443     FuzzyCompare(fitResult.paramValues.at(0), 4.3736970754E+02, 1.e-6);
1444     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 3.64772833062694
1445     FuzzyCompare(fitResult.errorValues.at(0), 3.6489174345E+00, 1.e-3);
1446     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: 0.000302272976784709
1447     FuzzyCompare(fitResult.paramValues.at(1), 3.0227324449E-04, 1.e-6);
1448     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 2.93256059733558e-06
1449     FuzzyCompare(fitResult.errorValues.at(1), 2.9334354479E-06, 1.e-3);
1450 
1451     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 0.068568272134244
1452     FuzzyCompare(fitResult.rsd, 6.8568272111E-02, 1.e-9);
1453     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 0.056419295321709 (new: 0.0564192953613416)
1454     FuzzyCompare(fitResult.sse, 5.6419295283E-02, 1.e-8);
1455 }
1456 
1457 void FitTest::testNonLinearMisra1d_2() {
1458     //NIST data for Misra1d dataset
1459     QVector<double> xData = {77.6E0,114.9E0,141.1E0,190.8E0,239.9E0,289.0E0,332.8E0,378.4E0,434.8E0,477.3E0,536.8E0,593.1E0,689.1E0,760.0E0};
1460     QVector<double> yData = {10.07E0,14.73E0,17.94E0,23.93E0,29.61E0,35.18E0,40.02E0,44.82E0,50.76E0,55.05E0,61.01E0,66.40E0,75.47E0,81.78E0};
1461 
1462     //data source columns
1463     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
1464     xDataColumn.replaceValues(0, xData);
1465 
1466     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
1467     yDataColumn.replaceValues(0, yData);
1468 
1469     XYFitCurve fitCurve("fit");
1470     fitCurve.setXDataColumn(&xDataColumn);
1471     fitCurve.setYDataColumn(&yDataColumn);
1472 
1473     //prepare the fit
1474     XYFitCurve::FitData fitData = fitCurve.fitData();
1475     fitData.modelCategory = nsl_fit_model_custom;
1476     XYFitCurve::initFitData(fitData);
1477     fitData.model = "b1*b2*x/(1.+b2*x)";
1478     fitData.paramNames << "b1" << "b2";
1479     fitData.eps = 1.e-12;
1480     const int np = fitData.paramNames.size();
1481     fitData.paramStartValues << 450. << 3.e-4;
1482     fitData.paramLowerLimits << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max();
1483     fitData.paramUpperLimits << std::numeric_limits<double>::max() << std::numeric_limits<double>::max();
1484     fitCurve.setFitData(fitData);
1485 
1486     //perform the fit
1487     fitCurve.recalculate();
1488     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
1489 
1490     //check the results
1491     QCOMPARE(fitResult.available, true);
1492     QCOMPARE(fitResult.valid, true);
1493 
1494     QCOMPARE(np, 2);
1495 
1496     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 437.370039987725
1497     FuzzyCompare(fitResult.paramValues.at(0), 4.3736970754E+02, 1.e-5);
1498     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 3.64772833062694
1499     FuzzyCompare(fitResult.errorValues.at(0), 3.6489174345E+00, 1.e-3);
1500     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: 0.000302272976784709
1501     FuzzyCompare(fitResult.paramValues.at(1), 3.0227324449E-04, 1.e-5);
1502     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 2.93256059733558e-06
1503     FuzzyCompare(fitResult.errorValues.at(1), 2.9334354479E-06, 1.e-3);
1504 
1505     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 0.068568272134244
1506     FuzzyCompare(fitResult.rsd, 6.8568272111E-02, 1.e-9);
1507     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 0.056419295321709
1508     FuzzyCompare(fitResult.sse, 5.6419295283E-02, 1.e-8);
1509 }
1510 
1511 void FitTest::testNonLinearMisra1d_3() {
1512     //NIST data for Misra1d dataset
1513     QVector<double> xData = {77.6E0,114.9E0,141.1E0,190.8E0,239.9E0,289.0E0,332.8E0,378.4E0,434.8E0,477.3E0,536.8E0,593.1E0,689.1E0,760.0E0};
1514     QVector<double> yData = {10.07E0,14.73E0,17.94E0,23.93E0,29.61E0,35.18E0,40.02E0,44.82E0,50.76E0,55.05E0,61.01E0,66.40E0,75.47E0,81.78E0};
1515 
1516     //data source columns
1517     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
1518     xDataColumn.replaceValues(0, xData);
1519 
1520     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
1521     yDataColumn.replaceValues(0, yData);
1522 
1523     XYFitCurve fitCurve("fit");
1524     fitCurve.setXDataColumn(&xDataColumn);
1525     fitCurve.setYDataColumn(&yDataColumn);
1526 
1527     //prepare the fit
1528     XYFitCurve::FitData fitData = fitCurve.fitData();
1529     fitData.modelCategory = nsl_fit_model_custom;
1530     XYFitCurve::initFitData(fitData);
1531     fitData.model = "b1*b2*x/(1.+b2*x)";
1532     fitData.paramNames << "b1" << "b2";
1533     fitData.eps = 1.e-12;
1534     const int np = fitData.paramNames.size();
1535     fitData.paramStartValues << 4.3736970754E+02 << 3.0227324449E-04;
1536     fitData.paramLowerLimits << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max();
1537     fitData.paramUpperLimits << std::numeric_limits<double>::max() << std::numeric_limits<double>::max();
1538     fitCurve.setFitData(fitData);
1539 
1540     //perform the fit
1541     fitCurve.recalculate();
1542     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
1543 
1544     //check the results
1545     QCOMPARE(fitResult.available, true);
1546     QCOMPARE(fitResult.valid, true);
1547 
1548     QCOMPARE(np, 2);
1549 
1550     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 437.370039987725
1551     FuzzyCompare(fitResult.paramValues.at(0), 4.3736970754E+02, 1.e-6);
1552     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 3.64772833062694
1553     FuzzyCompare(fitResult.errorValues.at(0), 3.6489174345E+00, 1.e-3);
1554     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: 0.000302272976784709
1555     FuzzyCompare(fitResult.paramValues.at(1), 3.0227324449E-04, 1.e-6);
1556     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 2.93256059733558e-06
1557     FuzzyCompare(fitResult.errorValues.at(1), 2.9334354479E-06, 1.e-3);
1558 
1559     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 0.068568272134244
1560     FuzzyCompare(fitResult.rsd, 6.8568272111E-02, 1.e-9);
1561     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 0.056419295321709
1562     FuzzyCompare(fitResult.sse, 5.6419295283E-02, 1.e-9);
1563 }
1564 
1565 void FitTest::testNonLinearMGH09() {
1566     //NIST data for MGH09 dataset
1567     QVector<double> xData = {4.000000E+00,2.000000E+00,1.000000E+00,5.000000E-01,2.500000E-01,1.670000E-01,1.250000E-01,1.000000E-01,
1568         8.330000E-02,7.140000E-02,6.250000E-02};
1569     QVector<double> yData = {1.957000E-01,1.947000E-01,1.735000E-01,1.600000E-01,8.440000E-02,6.270000E-02,4.560000E-02,3.420000E-02,
1570         3.230000E-02,2.350000E-02,2.460000E-02};
1571 
1572     //data source columns
1573     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
1574     xDataColumn.replaceValues(0, xData);
1575 
1576     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
1577     yDataColumn.replaceValues(0, yData);
1578 
1579     XYFitCurve fitCurve("fit");
1580     fitCurve.setXDataColumn(&xDataColumn);
1581     fitCurve.setYDataColumn(&yDataColumn);
1582 
1583     //prepare the fit
1584     XYFitCurve::FitData fitData = fitCurve.fitData();
1585     fitData.modelCategory = nsl_fit_model_custom;
1586     XYFitCurve::initFitData(fitData);
1587     fitData.model = "b1*(x^2 + b2*x)/(x^2 + x*b3 + b4)";
1588     fitData.paramNames << "b1" << "b2" << "b3" << "b4";
1589     //fitData.eps = 1.e-12;
1590     const int np = fitData.paramNames.size();
1591     fitData.paramStartValues << 2.5000000000E+01 << 3.9000000000E+01 << 4.1500000000E+01 << 3.9000000000E+01;
1592     fitData.paramLowerLimits << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max();
1593     fitData.paramUpperLimits << std::numeric_limits<double>::max() << std::numeric_limits<double>::max() << std::numeric_limits<double>::max() << std::numeric_limits<double>::max();
1594     fitCurve.setFitData(fitData);
1595 
1596     //perform the fit
1597     fitCurve.recalculate();
1598     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
1599 
1600     //check the results
1601     QCOMPARE(fitResult.available, true);
1602     QCOMPARE(fitResult.valid, true);
1603 
1604     QCOMPARE(np, 4);
1605 
1606 // TODO: fit does not find global minimum
1607 /*  DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result:
1608     FuzzyCompare(fitResult.paramValues.at(0), 1.9280693458E-01, 1.e-6);
1609     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result:
1610     FuzzyCompare(fitResult.errorValues.at(0), 1.1435312227E-02, 1.e-3);
1611     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result:
1612     FuzzyCompare(fitResult.paramValues.at(1), 1.9128232873E-01, 1.e-6);
1613     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result:
1614     FuzzyCompare(fitResult.errorValues.at(1), 1.9633220911E-01, 1.e-3);
1615     DEBUG(std::setprecision(15) << fitResult.paramValues.at(2));    // result:
1616     FuzzyCompare(fitResult.paramValues.at(2), 1.2305650693E-01, 1.e-6);
1617     DEBUG(std::setprecision(15) << fitResult.errorValues.at(2));    // result:
1618     FuzzyCompare(fitResult.errorValues.at(2), 8.0842031232E-02, 1.e-3);
1619     DEBUG(std::setprecision(15) << fitResult.paramValues.at(3));    // result:
1620     FuzzyCompare(fitResult.paramValues.at(3), 1.3606233068E-01, 1.e-6);
1621     DEBUG(std::setprecision(15) << fitResult.errorValues.at(3));    // result:
1622     FuzzyCompare(fitResult.errorValues.at(3), 9.0025542308E-02, 1.e-3);
1623 
1624     DEBUG(std::setprecision(15) << fitResult.rsd);  // result:
1625     FuzzyCompare(fitResult.rsd, 6.6279236551E-03, 1.e-9);
1626     DEBUG(std::setprecision(15) << fitResult.sse);  // result:
1627     FuzzyCompare(fitResult.sse, 3.0750560385E-04, 1.e-9);
1628 */
1629 }
1630 
1631 void FitTest::testNonLinearMGH09_2() {
1632     //NIST data for MGH09 dataset
1633     QVector<double> xData = {4.000000E+00,2.000000E+00,1.000000E+00,5.000000E-01,2.500000E-01,1.670000E-01,1.250000E-01,1.000000E-01,
1634         8.330000E-02,7.140000E-02,6.250000E-02};
1635     QVector<double> yData = {1.957000E-01,1.947000E-01,1.735000E-01,1.600000E-01,8.440000E-02,6.270000E-02,4.560000E-02,3.420000E-02,
1636         3.230000E-02,2.350000E-02,2.460000E-02};
1637 
1638     //data source columns
1639     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
1640     xDataColumn.replaceValues(0, xData);
1641 
1642     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
1643     yDataColumn.replaceValues(0, yData);
1644 
1645     XYFitCurve fitCurve("fit");
1646     fitCurve.setXDataColumn(&xDataColumn);
1647     fitCurve.setYDataColumn(&yDataColumn);
1648 
1649     //prepare the fit
1650     XYFitCurve::FitData fitData = fitCurve.fitData();
1651     fitData.modelCategory = nsl_fit_model_custom;
1652     XYFitCurve::initFitData(fitData);
1653     fitData.model = "b1*(x^2 + b2*x)/(x^2 + x*b3 + b4)";
1654     fitData.paramNames << "b1" << "b2" << "b3" << "b4";
1655     //fitData.eps = 1.e-12;
1656     const int np = fitData.paramNames.size();
1657     fitData.paramStartValues << 2.5000000000E-01 << 3.9000000000E-01 << 4.1500000000E-01 << 3.9000000000E-01;
1658     fitData.paramLowerLimits << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max();
1659     fitData.paramUpperLimits << std::numeric_limits<double>::max() << std::numeric_limits<double>::max() << std::numeric_limits<double>::max() << std::numeric_limits<double>::max();
1660     fitCurve.setFitData(fitData);
1661 
1662     //perform the fit
1663     fitCurve.recalculate();
1664     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
1665 
1666     //check the results
1667     QCOMPARE(fitResult.available, true);
1668     QCOMPARE(fitResult.valid, true);
1669 
1670     QCOMPARE(np, 4);
1671 
1672     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result:
1673     FuzzyCompare(fitResult.paramValues.at(0), 1.9280693458E-01, 1.e-5);
1674     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result:
1675     FuzzyCompare(fitResult.errorValues.at(0), 1.1435312227E-02, 1.e-4);
1676     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result:
1677     FuzzyCompare(fitResult.paramValues.at(1), 1.9128232873E-01, 1.e-3);
1678     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: (new: 0.196361378435283)
1679     FuzzyCompare(fitResult.errorValues.at(1), 1.9633220911E-01, 1.e-3);
1680     DEBUG(std::setprecision(15) << fitResult.paramValues.at(2));    // result:
1681     FuzzyCompare(fitResult.paramValues.at(2), 1.2305650693E-01, 1.e-4);
1682     DEBUG(std::setprecision(15) << fitResult.errorValues.at(2));    // result:
1683     FuzzyCompare(fitResult.errorValues.at(2), 8.0842031232E-02, 1.e-4);
1684     DEBUG(std::setprecision(15) << fitResult.paramValues.at(3));    // result:
1685     FuzzyCompare(fitResult.paramValues.at(3), 1.3606233068E-01, 1.e-4);
1686     DEBUG(std::setprecision(15) << fitResult.errorValues.at(3));    // result:
1687     FuzzyCompare(fitResult.errorValues.at(3), 9.0025542308E-02, 1.e-4);
1688 
1689     DEBUG(std::setprecision(15) << fitResult.rsd);  // result:
1690     FuzzyCompare(fitResult.rsd, 6.6279236551E-03, 1.e-8);
1691     DEBUG(std::setprecision(15) << fitResult.sse);  // result:
1692     FuzzyCompare(fitResult.sse, 3.0750560385E-04, 1.e-8);
1693 }
1694 
1695 void FitTest::testNonLinearMGH09_3() {
1696     //NIST data for MGH09 dataset
1697     QVector<double> xData = {4.000000E+00,2.000000E+00,1.000000E+00,5.000000E-01,2.500000E-01,1.670000E-01,1.250000E-01,1.000000E-01,
1698         8.330000E-02,7.140000E-02,6.250000E-02};
1699     QVector<double> yData = {1.957000E-01,1.947000E-01,1.735000E-01,1.600000E-01,8.440000E-02,6.270000E-02,4.560000E-02,3.420000E-02,
1700         3.230000E-02,2.350000E-02,2.460000E-02};
1701 
1702     //data source columns
1703     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
1704     xDataColumn.replaceValues(0, xData);
1705 
1706     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
1707     yDataColumn.replaceValues(0, yData);
1708 
1709     XYFitCurve fitCurve("fit");
1710     fitCurve.setXDataColumn(&xDataColumn);
1711     fitCurve.setYDataColumn(&yDataColumn);
1712 
1713     //prepare the fit
1714     XYFitCurve::FitData fitData = fitCurve.fitData();
1715     fitData.modelCategory = nsl_fit_model_custom;
1716     XYFitCurve::initFitData(fitData);
1717     fitData.model = "b1*(x^2 + b2*x)/(x^2 + x*b3 + b4)";
1718     fitData.paramNames << "b1" << "b2" << "b3" << "b4";
1719     //fitData.eps = 1.e-12;
1720     const int np = fitData.paramNames.size();
1721     fitData.paramStartValues << 1.9280693458E-01 << 1.9128232873E-01 << 1.2305650693E-01 << 1.3606233068E-01;
1722     fitData.paramLowerLimits << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max();
1723     fitData.paramUpperLimits << std::numeric_limits<double>::max() << std::numeric_limits<double>::max() << std::numeric_limits<double>::max() << std::numeric_limits<double>::max();
1724     fitCurve.setFitData(fitData);
1725 
1726     //perform the fit
1727     fitCurve.recalculate();
1728     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
1729 
1730     //check the results
1731     QCOMPARE(fitResult.available, true);
1732     QCOMPARE(fitResult.valid, true);
1733 
1734     QCOMPARE(np, 4);
1735 
1736     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result:
1737     FuzzyCompare(fitResult.paramValues.at(0), 1.9280693458E-01, 1.e-9);
1738     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result:
1739     FuzzyCompare(fitResult.errorValues.at(0), 1.1435312227E-02, 1.e-5);
1740     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result:
1741     FuzzyCompare(fitResult.paramValues.at(1), 1.9128232873E-01, 1.e-9);
1742     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result:
1743     FuzzyCompare(fitResult.errorValues.at(1), 1.9633220911E-01, 1.e-5);
1744     DEBUG(std::setprecision(15) << fitResult.paramValues.at(2));    // result:
1745     FuzzyCompare(fitResult.paramValues.at(2), 1.2305650693E-01, 1.e-9);
1746     DEBUG(std::setprecision(15) << fitResult.errorValues.at(2));    // result:
1747     FuzzyCompare(fitResult.errorValues.at(2), 8.0842031232E-02, 1.e-5);
1748     DEBUG(std::setprecision(15) << fitResult.paramValues.at(3));    // result:
1749     FuzzyCompare(fitResult.paramValues.at(3), 1.3606233068E-01, 1.e-9);
1750     DEBUG(std::setprecision(15) << fitResult.errorValues.at(3));    // result:
1751     FuzzyCompare(fitResult.errorValues.at(3), 9.0025542308E-02, 1.e-5);
1752 
1753     DEBUG(std::setprecision(15) << fitResult.rsd);  // result:
1754     FuzzyCompare(fitResult.rsd, 6.6279236551E-03, 1.e-9);
1755     DEBUG(std::setprecision(15) << fitResult.sse);  // result:
1756     FuzzyCompare(fitResult.sse, 3.0750560385E-04, 1.e-9);
1757 }
1758 
1759 void FitTest::testNonLinearMGH10() {
1760     //NIST data for MGH10 dataset
1761     QVector<double> xData = {5.000000E+01,5.500000E+01,6.000000E+01,6.500000E+01,7.000000E+01,7.500000E+01,8.000000E+01,8.500000E+01,9.000000E+01,
1762         9.500000E+01,1.000000E+02,1.050000E+02,1.100000E+02,1.150000E+02,1.200000E+02,1.250000E+02};
1763     QVector<double> yData = {3.478000E+04,2.861000E+04,2.365000E+04,1.963000E+04,1.637000E+04,1.372000E+04,1.154000E+04,9.744000E+03,8.261000E+03,
1764         7.030000E+03,6.005000E+03,5.147000E+03,4.427000E+03,3.820000E+03,3.307000E+03,2.872000E+03};
1765 
1766     //data source columns
1767     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
1768     xDataColumn.replaceValues(0, xData);
1769 
1770     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
1771     yDataColumn.replaceValues(0, yData);
1772 
1773     XYFitCurve fitCurve("fit");
1774     fitCurve.setXDataColumn(&xDataColumn);
1775     fitCurve.setYDataColumn(&yDataColumn);
1776 
1777     //prepare the fit
1778     XYFitCurve::FitData fitData = fitCurve.fitData();
1779     fitData.modelCategory = nsl_fit_model_custom;
1780     XYFitCurve::initFitData(fitData);
1781     fitData.model = "b1*exp(b2/(x+b3))";
1782     fitData.paramNames << "b1" << "b2" << "b3";
1783     //fitData.eps = 1.e-12;
1784     const int np = fitData.paramNames.size();
1785     fitData.paramStartValues << 2.0000000000E+00 << 4.0000000000E+05 << 2.5000000000E+04;
1786     fitData.paramLowerLimits << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max();
1787     fitData.paramUpperLimits << std::numeric_limits<double>::max() << std::numeric_limits<double>::max() << std::numeric_limits<double>::max();
1788     fitCurve.setFitData(fitData);
1789 
1790     //perform the fit
1791     fitCurve.recalculate();
1792     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
1793 
1794     //check the results
1795     QCOMPARE(fitResult.available, true);
1796     QCOMPARE(fitResult.valid, true);
1797 
1798     QCOMPARE(np, 3);
1799 
1800     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 0.00560963848336205 (Windows: 0.00560964247264364)
1801     FuzzyCompare(fitResult.paramValues.at(0), 5.6096364710E-03, 1.e-5);
1802     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 0.000156888682057687
1803     FuzzyCompare(fitResult.errorValues.at(0), 1.5687892471E-04, 1.e-4);
1804     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: 6181.34604697191 (Windows: 6181.34545410281)
1805     FuzzyCompare(fitResult.paramValues.at(1), 6.1813463463E+03, 1.e-6);
1806     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 23.3105479190063
1807     FuzzyCompare(fitResult.errorValues.at(1), 2.3309021107E+01, 1.e-4);
1808     DEBUG(std::setprecision(15) << fitResult.paramValues.at(2));    // result: 345.223624540718 (Windows: 345.223579103645)
1809     FuzzyCompare(fitResult.paramValues.at(2), 3.4522363462E+02, 1.e-6);
1810     DEBUG(std::setprecision(15) << fitResult.errorValues.at(2));    // result: 0.784915645388214
1811     FuzzyCompare(fitResult.errorValues.at(2), 7.8486103508E-01, 1.e-4);
1812 
1813     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 2.6009740064923  (Windows: 2.60097400662837, 2.60097400697918)
1814     FuzzyCompare(fitResult.rsd, 2.6009740065E+00, 1.e-9);
1815     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 87.9458551718321 (FreeBSD: 87.9458551726946, Windows: 87.9458551810338)
1816     FuzzyCompare(fitResult.sse, 8.7945855171E+01, 1.e-9);
1817 }
1818 
1819 void FitTest::testNonLinearMGH10_2() {
1820     //NIST data for MGH10 dataset
1821     QVector<double> xData = {5.000000E+01,5.500000E+01,6.000000E+01,6.500000E+01,7.000000E+01,7.500000E+01,8.000000E+01,8.500000E+01,9.000000E+01,
1822         9.500000E+01,1.000000E+02,1.050000E+02,1.100000E+02,1.150000E+02,1.200000E+02,1.250000E+02};
1823     QVector<double> yData = {3.478000E+04,2.861000E+04,2.365000E+04,1.963000E+04,1.637000E+04,1.372000E+04,1.154000E+04,9.744000E+03,8.261000E+03,
1824         7.030000E+03,6.005000E+03,5.147000E+03,4.427000E+03,3.820000E+03,3.307000E+03,2.872000E+03};
1825 
1826     //data source columns
1827     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
1828     xDataColumn.replaceValues(0, xData);
1829 
1830     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
1831     yDataColumn.replaceValues(0, yData);
1832 
1833     XYFitCurve fitCurve("fit");
1834     fitCurve.setXDataColumn(&xDataColumn);
1835     fitCurve.setYDataColumn(&yDataColumn);
1836 
1837     //prepare the fit
1838     XYFitCurve::FitData fitData = fitCurve.fitData();
1839     fitData.modelCategory = nsl_fit_model_custom;
1840     XYFitCurve::initFitData(fitData);
1841     fitData.model = "b1*exp(b2/(x+b3))";
1842     fitData.paramNames << "b1" << "b2" << "b3";
1843     //fitData.eps = 1.e-12;
1844     const int np = fitData.paramNames.size();
1845     fitData.paramStartValues << 2.0000000000E-02 << 4.0000000000E+03 << 2.5000000000E+02;
1846     fitData.paramLowerLimits << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max();
1847     fitData.paramUpperLimits << std::numeric_limits<double>::max() << std::numeric_limits<double>::max() << std::numeric_limits<double>::max();
1848     fitCurve.setFitData(fitData);
1849 
1850     //perform the fit
1851     fitCurve.recalculate();
1852     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
1853 
1854     //check the results
1855     QCOMPARE(fitResult.available, true);
1856     QCOMPARE(fitResult.valid, true);
1857 
1858     QCOMPARE(np, 3);
1859 
1860     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 0.00560963848336205
1861     FuzzyCompare(fitResult.paramValues.at(0), 5.6096364710E-03, 1.e-5);
1862     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 0.000156888586677272
1863     FuzzyCompare(fitResult.errorValues.at(0), 1.5687892471E-04, 1.e-4);
1864     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: 6181.34604697191
1865     FuzzyCompare(fitResult.paramValues.at(1), 6.1813463463E+03, 1.e-6);
1866     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 23.3105167849511
1867     FuzzyCompare(fitResult.errorValues.at(1), 2.3309021107E+01, 1.e-4);
1868     DEBUG(std::setprecision(15) << fitResult.paramValues.at(2));    // result: 345.223624540718
1869     FuzzyCompare(fitResult.paramValues.at(2), 3.4522363462E+02, 1.e-7);
1870     DEBUG(std::setprecision(15) << fitResult.errorValues.at(2));    // result: 0.784914752553929
1871     FuzzyCompare(fitResult.errorValues.at(2), 7.8486103508E-01, 1.e-4);
1872 
1873     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 2.6009740064923
1874     FuzzyCompare(fitResult.rsd, 2.6009740065E+00, 1.e-10);
1875     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 87.9458551718321
1876     FuzzyCompare(fitResult.sse, 8.7945855171E+01, 1.e-9);
1877 }
1878 
1879 void FitTest::testNonLinearMGH10_3() {
1880     //NIST data for MGH10 dataset
1881     QVector<double> xData = {5.000000E+01,5.500000E+01,6.000000E+01,6.500000E+01,7.000000E+01,7.500000E+01,8.000000E+01,8.500000E+01,9.000000E+01,
1882         9.500000E+01,1.000000E+02,1.050000E+02,1.100000E+02,1.150000E+02,1.200000E+02,1.250000E+02};
1883     QVector<double> yData = {3.478000E+04,2.861000E+04,2.365000E+04,1.963000E+04,1.637000E+04,1.372000E+04,1.154000E+04,9.744000E+03,8.261000E+03,
1884         7.030000E+03,6.005000E+03,5.147000E+03,4.427000E+03,3.820000E+03,3.307000E+03,2.872000E+03};
1885 
1886     //data source columns
1887     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
1888     xDataColumn.replaceValues(0, xData);
1889 
1890     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
1891     yDataColumn.replaceValues(0, yData);
1892 
1893     XYFitCurve fitCurve("fit");
1894     fitCurve.setXDataColumn(&xDataColumn);
1895     fitCurve.setYDataColumn(&yDataColumn);
1896 
1897     //prepare the fit
1898     XYFitCurve::FitData fitData = fitCurve.fitData();
1899     fitData.modelCategory = nsl_fit_model_custom;
1900     XYFitCurve::initFitData(fitData);
1901     fitData.model = "b1*exp(b2/(x+b3))";
1902     fitData.paramNames << "b1" << "b2" << "b3";
1903     //fitData.eps = 1.e-12;
1904     const int np = fitData.paramNames.size();
1905     fitData.paramStartValues << 5.6096364710E-03 << 6.1813463463E+03 << 3.4522363462E+02;
1906     fitData.paramLowerLimits << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max();
1907     fitData.paramUpperLimits << std::numeric_limits<double>::max() << std::numeric_limits<double>::max() << std::numeric_limits<double>::max();
1908     fitCurve.setFitData(fitData);
1909 
1910     //perform the fit
1911     fitCurve.recalculate();
1912     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
1913 
1914     //check the results
1915     QCOMPARE(fitResult.available, true);
1916     QCOMPARE(fitResult.valid, true);
1917 
1918     QCOMPARE(np, 3);
1919 
1920     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 0.00560963848336205
1921     FuzzyCompare(fitResult.paramValues.at(0), 5.6096364710E-03, 1.e-6);
1922     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 0.000156888348998521
1923     FuzzyCompare(fitResult.errorValues.at(0), 1.5687892471E-04, 1.e-4);
1924     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: 6181.34604697191
1925     FuzzyCompare(fitResult.paramValues.at(1), 6.1813463463E+03, 1.e-7);
1926     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 23.310508065631
1927     FuzzyCompare(fitResult.errorValues.at(1), 2.3309021107E+01, 1.e-4);
1928     DEBUG(std::setprecision(15) << fitResult.paramValues.at(2));    // result: 345.223624540718
1929     FuzzyCompare(fitResult.paramValues.at(2), 3.4522363462E+02, 1.e-7);
1930     DEBUG(std::setprecision(15) << fitResult.errorValues.at(2));    // result: 0.784914424350028
1931     FuzzyCompare(fitResult.errorValues.at(2), 7.8486103508E-01, 1.e-4);
1932 
1933     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 2.6009740064923
1934     FuzzyCompare(fitResult.rsd, 2.6009740065E+00, 1.e-11);
1935     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 87.9458551718321
1936     FuzzyCompare(fitResult.sse, 8.7945855171E+01, 1.e-11);
1937 }
1938 
1939 void FitTest::testNonLinearRat43() {
1940     //NIST data for Rat43 dataset
1941     QVector<double> xData = {1.0E0,2.0E0,3.0E0,4.0E0,5.0E0,6.0E0,7.0E0,8.0E0,9.0E0,10.0E0,11.0E0,12.0E0,13.0E0,14.0E0,15.0E0};
1942     QVector<double> yData = {16.08E0,33.83E0,65.80E0,97.20E0,191.55E0,326.20E0,386.87E0,520.53E0,590.03E0,651.92E0,724.93E0,699.56E0,689.96E0,637.56E0,717.41E0};
1943 
1944     //data source columns
1945     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
1946     xDataColumn.replaceValues(0, xData);
1947 
1948     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
1949     yDataColumn.replaceValues(0, yData);
1950 
1951     XYFitCurve fitCurve("fit");
1952     fitCurve.setXDataColumn(&xDataColumn);
1953     fitCurve.setYDataColumn(&yDataColumn);
1954 
1955     //prepare the fit
1956     XYFitCurve::FitData fitData = fitCurve.fitData();
1957     fitData.modelCategory = nsl_fit_model_custom;
1958     XYFitCurve::initFitData(fitData);
1959     fitData.model = "b1/pow(1. + exp(b2-b3*x), 1/b4)";
1960     fitData.paramNames << "b1" << "b2" << "b3" << "b4";
1961     fitData.eps = 1.e-9;
1962     const int np = fitData.paramNames.size();
1963     fitData.paramStartValues << 1.0000000000E+02 << 1.0000000000E+01 << 1.0000000000E+00 << 1.0000000000E+00;
1964     fitData.paramLowerLimits << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max();
1965     fitData.paramUpperLimits << std::numeric_limits<double>::max() << std::numeric_limits<double>::max() << std::numeric_limits<double>::max() << std::numeric_limits<double>::max();
1966     fitCurve.setFitData(fitData);
1967 
1968     //perform the fit
1969     fitCurve.recalculate();
1970     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
1971 
1972     //check the results
1973     QCOMPARE(fitResult.available, true);
1974     QCOMPARE(fitResult.valid, true);
1975 
1976     QCOMPARE(np, 4);
1977 
1978     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 699.641340982193
1979     FuzzyCompare(fitResult.paramValues.at(0), 6.9964151270E+02, 1.e-6);
1980     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 16.3022524293302
1981     FuzzyCompare(fitResult.errorValues.at(0), 1.6302297817E+01, 1.e-5);
1982     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: 5.2771555758844
1983     FuzzyCompare(fitResult.paramValues.at(1), 5.2771253025E+00, 1.e-5);
1984     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 2.08290034908325
1985     FuzzyCompare(fitResult.errorValues.at(1), 2.0828735829E+00, 1.e-4);
1986     DEBUG(std::setprecision(15) << fitResult.paramValues.at(2));    // result: 0.759632366113637
1987     FuzzyCompare(fitResult.paramValues.at(2), 7.5962938329E-01, 1.e-5);
1988     DEBUG(std::setprecision(15) << fitResult.errorValues.at(2));    // result: 0.195664372178938
1989     FuzzyCompare(fitResult.errorValues.at(2), 1.9566123451E-01, 1.e-4);
1990     DEBUG(std::setprecision(15) << fitResult.paramValues.at(3));    // result: 1.27925748993867
1991     FuzzyCompare(fitResult.paramValues.at(3), 1.2792483859E+00, 1.e-5);
1992     DEBUG(std::setprecision(15) << fitResult.errorValues.at(3));    // result: 0.687627478905195
1993     FuzzyCompare(fitResult.errorValues.at(3), 6.8761936385E-01, 1.e-4);
1994 
1995     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 28.2624146626284
1996     FuzzyCompare(fitResult.rsd, 2.8262414662E+01, 1.e-10);
1997     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 8786.4049081859
1998     FuzzyCompare(fitResult.sse, 8.7864049080E+03, 1.e-10);
1999 }
2000 
2001 void FitTest::testNonLinearRat43_2() {
2002     //NIST data for Rat43 dataset
2003     QVector<double> xData = {1.0E0,2.0E0,3.0E0,4.0E0,5.0E0,6.0E0,7.0E0,8.0E0,9.0E0,10.0E0,11.0E0,12.0E0,13.0E0,14.0E0,15.0E0};
2004     QVector<double> yData = {16.08E0,33.83E0,65.80E0,97.20E0,191.55E0,326.20E0,386.87E0,520.53E0,590.03E0,651.92E0,724.93E0,699.56E0,689.96E0,637.56E0,717.41E0};
2005 
2006     //data source columns
2007     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
2008     xDataColumn.replaceValues(0, xData);
2009 
2010     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
2011     yDataColumn.replaceValues(0, yData);
2012 
2013     XYFitCurve fitCurve("fit");
2014     fitCurve.setXDataColumn(&xDataColumn);
2015     fitCurve.setYDataColumn(&yDataColumn);
2016 
2017     //prepare the fit
2018     XYFitCurve::FitData fitData = fitCurve.fitData();
2019     fitData.modelCategory = nsl_fit_model_custom;
2020     XYFitCurve::initFitData(fitData);
2021     fitData.model = "b1/pow(1. + exp(b2-b3*x), 1/b4)";
2022     fitData.paramNames << "b1" << "b2" << "b3" << "b4";
2023     fitData.eps = 1.e-10;
2024     const int np = fitData.paramNames.size();
2025     fitData.paramStartValues << 7.0000000000E+02 << 5.0000000000E+00 << 7.5000000000E-01 << 1.3000000000E+00;
2026     fitData.paramLowerLimits << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max();
2027     fitData.paramUpperLimits << std::numeric_limits<double>::max() << std::numeric_limits<double>::max() << std::numeric_limits<double>::max() << std::numeric_limits<double>::max();
2028     fitCurve.setFitData(fitData);
2029 
2030     //perform the fit
2031     fitCurve.recalculate();
2032     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
2033 
2034     //check the results
2035     QCOMPARE(fitResult.available, true);
2036     QCOMPARE(fitResult.valid, true);
2037 
2038     QCOMPARE(np, 4);
2039 
2040     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 699.641340982193
2041     FuzzyCompare(fitResult.paramValues.at(0), 6.9964151270E+02, 1.e-6);
2042     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 16.3023134145464 (FreeBSD: 16.3023141645004)
2043     FuzzyCompare(fitResult.errorValues.at(0), 1.6302297817E+01, 1.e-5);
2044     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: 5.2771555758844
2045     FuzzyCompare(fitResult.paramValues.at(1), 5.2771253025E+00, 1.e-5);
2046     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 2.08288970703906
2047     FuzzyCompare(fitResult.errorValues.at(1), 2.0828735829E+00, 1.e-5);
2048     DEBUG(std::setprecision(15) << fitResult.paramValues.at(2));    // result: 0.759632366113637
2049     FuzzyCompare(fitResult.paramValues.at(2), 7.5962938329E-01, 1.e-5);
2050     DEBUG(std::setprecision(15) << fitResult.errorValues.at(2));    // result: 0.195662802156063
2051     FuzzyCompare(fitResult.errorValues.at(2), 1.9566123451E-01, 1.e-5);
2052     DEBUG(std::setprecision(15) << fitResult.paramValues.at(3));    // result: 1.27925748993867
2053     FuzzyCompare(fitResult.paramValues.at(3), 1.2792483859E+00, 1.e-5);
2054     DEBUG(std::setprecision(15) << fitResult.errorValues.at(3));    // result: 0.687623222160242
2055     FuzzyCompare(fitResult.errorValues.at(3), 6.8761936385E-01, 1.e-5);
2056 
2057     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 28.2624146626284
2058     FuzzyCompare(fitResult.rsd, 2.8262414662E+01, 1.e-10);
2059     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 8786.4049081859
2060     FuzzyCompare(fitResult.sse, 8.7864049080E+03, 1.e-11);
2061 }
2062 
2063 void FitTest::testNonLinearRat43_3() {
2064     //NIST data for Rat43 dataset
2065     QVector<double> xData = {1.0E0,2.0E0,3.0E0,4.0E0,5.0E0,6.0E0,7.0E0,8.0E0,9.0E0,10.0E0,11.0E0,12.0E0,13.0E0,14.0E0,15.0E0};
2066     QVector<double> yData = {16.08E0,33.83E0,65.80E0,97.20E0,191.55E0,326.20E0,386.87E0,520.53E0,590.03E0,651.92E0,724.93E0,699.56E0,689.96E0,637.56E0,717.41E0};
2067 
2068     //data source columns
2069     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
2070     xDataColumn.replaceValues(0, xData);
2071 
2072     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
2073     yDataColumn.replaceValues(0, yData);
2074 
2075     XYFitCurve fitCurve("fit");
2076     fitCurve.setXDataColumn(&xDataColumn);
2077     fitCurve.setYDataColumn(&yDataColumn);
2078 
2079     //prepare the fit
2080     XYFitCurve::FitData fitData = fitCurve.fitData();
2081     fitData.modelCategory = nsl_fit_model_custom;
2082     XYFitCurve::initFitData(fitData);
2083     fitData.model = "b1/pow(1. + exp(b2-b3*x), 1/b4)";
2084     fitData.paramNames << "b1" << "b2" << "b3" << "b4";
2085     //fitData.eps = 1.e-12;
2086     const int np = fitData.paramNames.size();
2087     fitData.paramStartValues << 6.9964151270E+02 << 5.2771253025E+00 << 7.5962938329E-01 << 1.2792483859E+00;
2088     fitData.paramLowerLimits << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max() << -std::numeric_limits<double>::max();
2089     fitData.paramUpperLimits << std::numeric_limits<double>::max() << std::numeric_limits<double>::max() << std::numeric_limits<double>::max() << std::numeric_limits<double>::max();
2090     fitCurve.setFitData(fitData);
2091 
2092     //perform the fit
2093     fitCurve.recalculate();
2094     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
2095 
2096     //check the results
2097     QCOMPARE(fitResult.available, true);
2098     QCOMPARE(fitResult.valid, true);
2099 
2100     QCOMPARE(np, 4);
2101 
2102     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 699.641340982193
2103     FuzzyCompare(fitResult.paramValues.at(0), 6.9964151270E+02, 1.e-8);
2104     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 16.3022905400761
2105     FuzzyCompare(fitResult.errorValues.at(0), 1.6302297817E+01, 1.e-6);
2106     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: 5.2771555758844
2107     FuzzyCompare(fitResult.paramValues.at(1), 5.2771253025E+00, 1.e-8);
2108     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 2.08289316520407
2109     FuzzyCompare(fitResult.errorValues.at(1), 2.0828735829E+00, 1.e-5);
2110     DEBUG(std::setprecision(15) << fitResult.paramValues.at(2));    // result: 0.759632366113637
2111     FuzzyCompare(fitResult.paramValues.at(2), 7.5962938329E-01, 1.e-8);
2112     DEBUG(std::setprecision(15) << fitResult.errorValues.at(2));    // result: 0.195663312668779
2113     FuzzyCompare(fitResult.errorValues.at(2), 1.9566123451E-01, 1.e-4);
2114     DEBUG(std::setprecision(15) << fitResult.paramValues.at(3));    // result: 1.27925748993867
2115     FuzzyCompare(fitResult.paramValues.at(3), 1.2792483859E+00, 1.e-8);
2116     DEBUG(std::setprecision(15) << fitResult.errorValues.at(3));    // result: 0.687624541478887
2117     FuzzyCompare(fitResult.errorValues.at(3), 6.8761936385E-01, 1.e-5);
2118 
2119     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 28.2624146626284
2120     FuzzyCompare(fitResult.rsd, 2.8262414662E+01, 1.e-11);
2121     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 8786.4049081859
2122     FuzzyCompare(fitResult.sse, 8.7864049080E+03, 1.e-11);
2123 }
2124 
2125 // https://bugs.kde.org/show_bug.cgi?id=393213
2126 void FitTest::testNonLinearMichaelis_Menten() {
2127     // generic data
2128     QVector<double> xData = {0.0,0.2,0.4,0.6,0.8,1.0,1.2,1.4,1.6,1.8,2.0};
2129     QVector<double> yData = {0.0,0.6,0.65,0.7,0.75,0.75,0.8,0.9,0.85,0.95,0.9};
2130 
2131     //data source columns
2132     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
2133     xDataColumn.replaceValues(0, xData);
2134 
2135     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
2136     yDataColumn.replaceValues(0, yData);
2137 
2138     XYFitCurve fitCurve("fit");
2139     fitCurve.setXDataColumn(&xDataColumn);
2140     fitCurve.setYDataColumn(&yDataColumn);
2141 
2142     //prepare the fit
2143     XYFitCurve::FitData fitData = fitCurve.fitData();
2144     fitData.modelCategory = nsl_fit_model_custom;
2145     XYFitCurve::initFitData(fitData);
2146     fitData.model = "Vm * x/(Km + x)";
2147     fitData.paramNames << "Vm" << "Km";
2148     fitData.eps = 1.e-12;
2149     const int np = fitData.paramNames.size();
2150     fitData.paramStartValues << 1.0 << 1.0 ;
2151     for (int i = 0; i < np; i++) {
2152         fitData.paramLowerLimits << -std::numeric_limits<double>::max();
2153         fitData.paramUpperLimits << std::numeric_limits<double>::max();
2154     }
2155     fitCurve.setFitData(fitData);
2156 
2157     //perform the fit
2158     fitCurve.recalculate();
2159     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
2160 
2161     //check the results
2162     QCOMPARE(fitResult.available, true);
2163     QCOMPARE(fitResult.valid, true);
2164 
2165     QCOMPARE(np, 2);
2166 
2167     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 0.945561082955744
2168     FuzzyCompare(fitResult.paramValues.at(0), 0.94556434933256, 1.e-5);
2169     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 0.0388724403232334
2170     FuzzyCompare(fitResult.errorValues.at(0), 0.0388803714011844, 3.e-4);
2171     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: 0.159396945453528
2172     FuzzyCompare(fitResult.paramValues.at(1), 0.159400761666661, 3.e-5);
2173     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 0.0388244491752518
2174     FuzzyCompare(fitResult.errorValues.at(1), 0.0388429738447119, 5.e-4);
2175 
2176     DEBUG(std::setprecision(15) << fitResult.rms);  // result: 0.00280486748619082
2177     FuzzyCompare(fitResult.rms, 0.00280486748877263, 1.e-9);
2178     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 0.0529609996713697
2179     FuzzyCompare(fitResult.rsd, 0.0529609996957444, 1.e-9);
2180     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 0.0252438073757174
2181     FuzzyCompare(fitResult.sse, 0.0252438073989537, 1.e-9);
2182 }
2183 //##############################################################################
2184 //#########################  Fits with weights #################################
2185 //##############################################################################
2186 
2187 // see http://gnuplot.sourceforge.net/demo_5.2/fit.html
2188 void FitTest::testNonLinearGP_lcdemo() {
2189     // data from https://github.com/gnuplot/gnuplot/blob/master/demo/lcdemo.dat
2190     QVector<double> xData = {39.471,40.091,40.602,41.058,41.438,41.880,42.437,42.836,43.209,43.599,43.997,44.313,44.908,45.169,45.594,45.743,45.796,45.816,
2191         45.841,45.876,45.908,45.959,46.008,46.040,46.060,46.096,46.126,46.149,46.372,46.625,46.945,47.326,47.708,48.095,48.540,48.927,49.314};
2192     QVector<double> yData = {1.03307,1.03246,1.03197,1.03153,1.03117,1.03074,1.03021,1.02982,1.02946,1.02907,1.02867,1.02833,1.02765,1.02735,1.02683,
2193         1.02661,1.02650,1.02644,1.02634,1.02623,1.02611,1.02592,1.02561,1.02526,1.02506,1.02500,1.02496,1.02494,1.02474,1.02452,1.02425,1.02393,
2194         1.02361,1.02329,1.02293,1.02262,1.02231};
2195     QVector<double> yError = {0.010,0.010,0.010,0.010,0.010,0.010,0.010,0.010,0.010,0.010,0.010,0.010,0.010,0.010,0.010,0.010,0.010,0.010,0.010,0.010,0.010,
2196         0.010,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001};
2197 
2198     //data source columns
2199     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
2200     xDataColumn.replaceValues(0, xData);
2201 
2202     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
2203     yDataColumn.replaceValues(0, yData);
2204 
2205     Column yErrorColumn("yerr", AbstractColumn::ColumnMode::Numeric);
2206     yErrorColumn.replaceValues(0, yError);
2207 
2208     XYFitCurve fitCurve("fit");
2209     fitCurve.setXDataColumn(&xDataColumn);
2210     fitCurve.setYDataColumn(&yDataColumn);
2211     fitCurve.setYErrorColumn(&yErrorColumn);
2212 
2213     //prepare the fit
2214     XYFitCurve::FitData fitData = fitCurve.fitData();
2215     fitData.modelCategory = nsl_fit_model_custom;
2216     XYFitCurve::initFitData(fitData);
2217     // x > Tc : d + mh(x-Tc)
2218     // x < Tc : d + ml(x-Tc) + b tanh(g(Tc-x))
2219     fitData.model = "d + theta(x-Tc)*mh*(x-Tc) + theta(Tc-x)*(ml*(x-Tc)+b*tanh(g*(Tc-x)))";
2220     fitData.paramNames << "d" << "Tc" << "mh" << "ml" << "b" << "g";
2221     fitData.eps = 1.e-12;
2222     const int np = fitData.paramNames.size();
2223     fitData.paramStartValues << 1.02 << 45. << -0.0005 << -0.0005 << 0.01002 << 1.0;
2224     for (int i = 0; i < np; i++) {
2225         fitData.paramLowerLimits << -std::numeric_limits<double>::max();
2226         fitData.paramUpperLimits << std::numeric_limits<double>::max();
2227     }
2228     fitData.yWeightsType = nsl_fit_weight_instrumental;
2229     fitCurve.setFitData(fitData);
2230 
2231     //perform the fit
2232     fitCurve.recalculate();
2233     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
2234 
2235     //check the results
2236     QCOMPARE(fitResult.available, true);
2237     QCOMPARE(fitResult.valid, true);
2238 
2239     QCOMPARE(np, 6);
2240 
2241     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 1.02499979307627 (Windows: 1.02561781433026)
2242     FuzzyCompare(fitResult.paramValues.at(0), 1.02499621370905, 1.e-3);
2243     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 4.81672854812941e-06
2244 //TODO  FuzzyCompare(fitResult.errorValues.at(0), 7.27819513635249e-06, 1.e-6);
2245     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: 46.0647953740441 (Windows: 45.4871250830364)
2246     FuzzyCompare(fitResult.paramValues.at(1), 46.0665367045608, 2.e-2);
2247     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 9.90288940612482
2248 //TODO  FuzzyCompare(fitResult.errorValues.at(1), 0.00159887430059728, 1.e-6);
2249     DEBUG(std::setprecision(15) << fitResult.paramValues.at(2));    // result:  -0.000835023995828296 (Windows: -0.000883960665773456)
2250     FuzzyCompare(fitResult.paramValues.at(2), -0.0008340717673769, 1.e-1);
2251     DEBUG(std::setprecision(15) << fitResult.errorValues.at(2));    // result:
2252 //TODO  FuzzyCompare(fitResult.errorValues.at(2), , 1.e-6);
2253     DEBUG(std::setprecision(15) << fitResult.paramValues.at(3));    // result: -0.000987547207638997
2254     FuzzyCompare(fitResult.paramValues.at(3), -0.00103152542276233, 1.e-1);
2255     DEBUG(std::setprecision(15) << fitResult.errorValues.at(3));    // result:
2256 //TODO  FuzzyCompare(fitResult.errorValues.at(3), , 1.e-6);
2257     DEBUG(std::setprecision(15) << fitResult.paramValues.at(4));    // result: 0.00158880319355268
2258     FuzzyCompare(fitResult.paramValues.at(4), 0.00139548391000006, 1.5e-1);
2259     DEBUG(std::setprecision(15) << fitResult.errorValues.at(4));    // result:
2260 //TODO  FuzzyCompare(fitResult.errorValues.at(4), , 1.e-6);
2261     DEBUG(std::setprecision(15) << fitResult.paramValues.at(5));    // result: 6.34254053273612 (Windows: 4.45482397068125)
2262 //  FuzzyCompare(fitResult.paramValues.at(5), 6.92493866108287, 1.e-1);
2263     DEBUG(std::setprecision(15) << fitResult.errorValues.at(5));    // result:
2264 //TODO  FuzzyCompare(fitResult.errorValues.at(5), , 1.e-6);
2265 
2266     DEBUG(std::setprecision(15) << fitResult.rms);  // result: 98.0672185899393
2267 //  FuzzyCompare(fitResult.rms, 0.000188776, 1.e-11);
2268     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 9.90288940612482
2269 //  FuzzyCompare(fitResult.rsd, 0.0137395924378767, 1.e-11);
2270     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 3040.08377628812
2271 //  FuzzyCompare(fitResult.sse, 0.00585206841112775, 1.e-11);
2272 }
2273 
2274 // see http://gnuplot.sourceforge.net/demo_5.2/fit.html
2275 void FitTest::testLinearGP_PY_noerror() {
2276     // Pearson's data and York's weights
2277     QVector<double> xData = {0.0,0.9,1.8,2.6,3.3,4.4,5.2,6.1,6.5,7.4};
2278     QVector<double> yData = {5.9,5.4,4.4,4.6,3.5,3.7,2.8,2.8,2.4,1.5};
2279 //  QVector<double> xError = {1000.,1000.,500.,800.,200.,80.,60.,20.,1.8,1.0};
2280 //  QVector<double> yError = {1.0,1.8,4.,8.,20.,20.,70.,70.,100.,500.};
2281 
2282     //data source columns
2283     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
2284     xDataColumn.replaceValues(0, xData);
2285 
2286     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
2287     yDataColumn.replaceValues(0, yData);
2288 
2289 //  Column yErrorColumn("yerr", AbstractColumn::ColumnMode::Numeric);
2290 //  yErrorColumn.replaceValues(0, yError);
2291 
2292     XYFitCurve fitCurve("fit");
2293     fitCurve.setXDataColumn(&xDataColumn);
2294     fitCurve.setYDataColumn(&yDataColumn);
2295 //  fitCurve.setYErrorColumn(&yErrorColumn);
2296 
2297     //prepare the fit
2298     XYFitCurve::FitData fitData = fitCurve.fitData();
2299     fitData.modelCategory = nsl_fit_model_custom;
2300     XYFitCurve::initFitData(fitData);
2301     fitData.model = "a1 + a2 * x";
2302     fitData.paramNames << "a1" << "a2";
2303     fitData.eps = 1.e-9;
2304     const int np = fitData.paramNames.size();
2305     fitData.paramStartValues << 5. << -0.5;
2306     for (int i = 0; i < np; i++) {
2307         fitData.paramLowerLimits << -std::numeric_limits<double>::max();
2308         fitData.paramUpperLimits << std::numeric_limits<double>::max();
2309     }
2310 //  fitData.yWeightsType = nsl_fit_weight_instrumental;
2311     fitCurve.setFitData(fitData);
2312 
2313     //perform the fit
2314     fitCurve.recalculate();
2315     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
2316 
2317     //check the results
2318     QCOMPARE(fitResult.available, true);
2319     QCOMPARE(fitResult.valid, true);
2320 
2321     QCOMPARE(np, 2);
2322 
2323     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 5.76118518568804
2324     FuzzyCompare(fitResult.paramValues.at(0), 5.76118519043878, 1.e-9);
2325     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 0.189485192391863
2326     FuzzyCompare(fitResult.errorValues.at(0), 0.189485195921141, 1.e-7);
2327     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: -0.539577274076964
2328     FuzzyCompare(fitResult.paramValues.at(1), -0.539577274983977, 1.e-8);
2329     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 0.0421265487265946
2330     FuzzyCompare(fitResult.errorValues.at(1), 0.0421265483886995, 1.e-8);
2331 
2332     DEBUG(std::setprecision(15) << fitResult.rms);  // result: 0.100082940279452
2333     QCOMPARE(fitResult.rms, 0.100082940279452);
2334     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 0.316358878932538
2335     QCOMPARE(fitResult.rsd, 0.316358878932538);
2336     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 0.800663522235619
2337     QCOMPARE(fitResult.sse, 0.800663522235619);
2338 }
2339 
2340 // see http://gnuplot.sourceforge.net/demo_5.2/fit.html
2341 void FitTest::testLinearGP_PY_yerror_polynomial() {
2342     // Pearson's data and York's weights
2343     QVector<double> xData = {0.0,0.9,1.8,2.6,3.3,4.4,5.2,6.1,6.5,7.4};
2344     QVector<double> yData = {5.9,5.4,4.4,4.6,3.5,3.7,2.8,2.8,2.4,1.5};
2345 //  QVector<double> xError = {1000.,1000.,500.,800.,200.,80.,60.,20.,1.8,1.0};
2346     QVector<double> yError = {1.0,1.8,4.,8.,20.,20.,70.,70.,100.,500.};
2347 
2348     //data source columns
2349     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
2350     xDataColumn.replaceValues(0, xData);
2351 
2352     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
2353     yDataColumn.replaceValues(0, yData);
2354 
2355     Column yErrorColumn("yerr", AbstractColumn::ColumnMode::Numeric);
2356     yErrorColumn.replaceValues(0, yError);
2357 
2358     XYFitCurve fitCurve("fit");
2359     fitCurve.setXDataColumn(&xDataColumn);
2360     fitCurve.setYDataColumn(&yDataColumn);
2361     fitCurve.setYErrorColumn(&yErrorColumn);
2362 
2363     //prepare the fit
2364     XYFitCurve::FitData fitData = fitCurve.fitData();
2365     fitData.modelCategory = nsl_fit_model_basic;
2366     fitData.modelType = nsl_fit_model_polynomial;
2367     fitData.degree = 1;
2368     XYFitCurve::initFitData(fitData);
2369 //  fitData.eps = 1.e-12;
2370     const int np = fitData.paramNames.size();
2371     fitData.paramStartValues << 5. << -0.5;
2372     fitData.yWeightsType = nsl_fit_weight_direct;
2373     fitCurve.setFitData(fitData);
2374 
2375     //perform the fit
2376     fitCurve.recalculate();
2377     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
2378 
2379     //check the results
2380     QCOMPARE(fitResult.available, true);
2381     QCOMPARE(fitResult.valid, true);
2382 
2383     QCOMPARE(np, 2);
2384 
2385     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 6.10010931666575
2386     FuzzyCompare(fitResult.paramValues.at(0), 6.10010931635002, 1.e-10);
2387     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 0.424059452104775, i386: 0.424059429083679
2388     FuzzyCompare(fitResult.errorValues.at(0), 0.424059452104785, 1.e-10);
2389     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: -0.610812956583933, i386: -0.610812954591566
2390     FuzzyCompare(fitResult.paramValues.at(1), -0.610812956537254, 1.e-9);
2391     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 0.0623409539388997, i386: 0.0623409508171503
2392     FuzzyCompare(fitResult.errorValues.at(1), 0.0623409539389024, 1.e-10);
2393 
2394     QCOMPARE(fitResult.rms, 4.29315093729054);
2395     QCOMPARE(fitResult.rsd, 2.07199202153158);
2396     QCOMPARE(fitResult.sse, 34.3452074983243);
2397     DEBUG(std::setprecision(15) << fitResult.fdist_p);  // result: 0.000101015996328551
2398 //TODO  QCOMPARE(fitResult.fdist_p, 3.51725605201025e-05);
2399 }
2400 
2401 // see http://gnuplot.sourceforge.net/demo_5.2/fit.html
2402 void FitTest::testLinearGP_PY_yerror_custom() {
2403     // Pearson's data and York's weights
2404     QVector<double> xData = {0.0,0.9,1.8,2.6,3.3,4.4,5.2,6.1,6.5,7.4};
2405     QVector<double> yData = {5.9,5.4,4.4,4.6,3.5,3.7,2.8,2.8,2.4,1.5};
2406 //  QVector<double> xError = {1000.,1000.,500.,800.,200.,80.,60.,20.,1.8,1.0};
2407     QVector<double> yError = {1.0,1.8,4.,8.,20.,20.,70.,70.,100.,500.};
2408 
2409     //data source columns
2410     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
2411     xDataColumn.replaceValues(0, xData);
2412 
2413     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
2414     yDataColumn.replaceValues(0, yData);
2415 
2416     Column yErrorColumn("yerr", AbstractColumn::ColumnMode::Numeric);
2417     yErrorColumn.replaceValues(0, yError);
2418 
2419     XYFitCurve fitCurve("fit");
2420     fitCurve.setXDataColumn(&xDataColumn);
2421     fitCurve.setYDataColumn(&yDataColumn);
2422     fitCurve.setYErrorColumn(&yErrorColumn);
2423 
2424     //prepare the fit
2425     XYFitCurve::FitData fitData = fitCurve.fitData();
2426     fitData.modelCategory = nsl_fit_model_custom;
2427     XYFitCurve::initFitData(fitData);
2428     fitData.model = "a1 + a2 * x";
2429     fitData.paramNames << "a1" << "a2";
2430     fitData.eps = 1.e-9;
2431     const int np = fitData.paramNames.size();
2432     fitData.paramStartValues << 5. << -0.5;
2433     for (int i = 0; i < np; i++) {
2434         fitData.paramLowerLimits << -std::numeric_limits<double>::max();
2435         fitData.paramUpperLimits << std::numeric_limits<double>::max();
2436     }
2437 
2438     fitData.yWeightsType = nsl_fit_weight_direct;
2439     fitCurve.setFitData(fitData);
2440 
2441     //perform the fit
2442     fitCurve.recalculate();
2443     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
2444 
2445     //check the results
2446     QCOMPARE(fitResult.available, true);
2447     QCOMPARE(fitResult.valid, true);
2448 
2449     QCOMPARE(np, 2);
2450 
2451     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 6.10010932451396
2452     FuzzyCompare(fitResult.paramValues.at(0), 6.10010931635002, 1.e-8);
2453     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 0.424059453530443 (new: 0.424059492144904)
2454     FuzzyCompare(fitResult.errorValues.at(0), 0.424059452104785, 1.e-7);
2455     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: -0.610812957040808 (new: -0.610812955065274)
2456     FuzzyCompare(fitResult.paramValues.at(1), -0.610812956537254, 1.e-8);
2457     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 0.0623409543258892 (new: 0.0623409596911536)
2458     FuzzyCompare(fitResult.errorValues.at(1), 0.0623409539389024, 1.e-7);
2459 
2460     QCOMPARE(fitResult.rms, 4.29315093729054);
2461     QCOMPARE(fitResult.rsd, 2.07199202153158);
2462     QCOMPARE(fitResult.sse, 34.3452074983243);
2463     DEBUG(std::setprecision(15) << fitResult.fdist_p);  // result: 0.000101015996328551
2464 //TODO  QCOMPARE(fitResult.fdist_p, 3.51725605201025e-05);
2465 }
2466 
2467 // see http://gnuplot.sourceforge.net/demo_5.2/fit.html
2468 void FitTest::testLinearGP_PY_xyerror_polynomial() {
2469     // Pearson's data and York's weights
2470     QVector<double> xData = {0.0,0.9,1.8,2.6,3.3,4.4,5.2,6.1,6.5,7.4};
2471     QVector<double> yData = {5.9,5.4,4.4,4.6,3.5,3.7,2.8,2.8,2.4,1.5};
2472     QVector<double> xError = {1000.,1000.,500.,800.,200.,80.,60.,20.,1.8,1.0};
2473     QVector<double> yError = {1.0,1.8,4.,8.,20.,20.,70.,70.,100.,500.};
2474 
2475     //data source columns
2476     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
2477     xDataColumn.replaceValues(0, xData);
2478 
2479     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
2480     yDataColumn.replaceValues(0, yData);
2481 
2482     Column xErrorColumn("xerr", AbstractColumn::ColumnMode::Numeric);
2483     xErrorColumn.replaceValues(0, xError);
2484 
2485     Column yErrorColumn("yerr", AbstractColumn::ColumnMode::Numeric);
2486     yErrorColumn.replaceValues(0, yError);
2487 
2488     XYFitCurve fitCurve("fit");
2489     fitCurve.setXDataColumn(&xDataColumn);
2490     fitCurve.setYDataColumn(&yDataColumn);
2491     fitCurve.setXErrorColumn(&xErrorColumn);
2492     fitCurve.setYErrorColumn(&yErrorColumn);
2493 
2494     //prepare the fit
2495     XYFitCurve::FitData fitData = fitCurve.fitData();
2496     fitData.modelCategory = nsl_fit_model_basic;
2497     fitData.modelType = nsl_fit_model_polynomial;
2498     fitData.degree = 1;
2499     XYFitCurve::initFitData(fitData);
2500     fitData.eps = 1.e-12;
2501     const int np = fitData.paramNames.size();
2502     fitData.paramStartValues << 5. << -0.5;
2503     fitData.xWeightsType = nsl_fit_weight_direct;
2504     fitData.yWeightsType = nsl_fit_weight_direct;
2505     fitCurve.setFitData(fitData);
2506 
2507     //perform the fit
2508     fitCurve.recalculate();
2509     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
2510 
2511     //check the results
2512     QCOMPARE(fitResult.available, true);
2513     QCOMPARE(fitResult.valid, true);
2514 
2515     QCOMPARE(np, 2);
2516 
2517     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 5.3960522989993
2518     FuzzyCompare(fitResult.paramValues.at(0), 5.39749958415886, 3.e-4); // gnuplot result ("effective variance" method)
2519     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 0.361458387983792
2520     FuzzyCompare(fitResult.errorValues.at(0), 0.361439886824914, 1.e-4);    // -""-
2521     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: -0.463448925094435
2522     FuzzyCompare(fitResult.paramValues.at(1), -0.463744669606207, 1.e-3);   // -""-
2523     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 0.0706627287153768
2524     FuzzyCompare(fitResult.errorValues.at(1), 0.0706637562101211, 1.e-4);   // -""-
2525 
2526     DEBUG(std::setprecision(15) << fitResult.rms);  // result: 1.49455608152396
2527     FuzzyCompare(fitResult.rms, 1.49417194665446, 1.e-3);   // gnuplot result ("effective variance" method)
2528     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 1.22252038082151
2529     FuzzyCompare(fitResult.rsd, 1.22236326296828, 1.e-3);   // -""-
2530     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 11.9564486521917
2531     FuzzyCompare(fitResult.sse, 11.9533755732357, 1.e-3);   // -""-
2532     DEBUG(std::setprecision(15) << fitResult.fdist_p);  // result: 0.00441031749154456
2533 //TODO  QCOMPARE(fitResult.fdist_p, 0.153296328355244);
2534 }
2535 
2536 // see http://gnuplot.sourceforge.net/demo_5.2/fit.html
2537 void FitTest::testLinearGP_PY_xyerror_custom() {
2538     // Pearson's data and York's weights
2539     QVector<double> xData = {0.0,0.9,1.8,2.6,3.3,4.4,5.2,6.1,6.5,7.4};
2540     QVector<double> yData = {5.9,5.4,4.4,4.6,3.5,3.7,2.8,2.8,2.4,1.5};
2541     QVector<double> xError = {1000.,1000.,500.,800.,200.,80.,60.,20.,1.8,1.0};
2542     QVector<double> yError = {1.0,1.8,4.,8.,20.,20.,70.,70.,100.,500.};
2543 
2544     //data source columns
2545     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
2546     xDataColumn.replaceValues(0, xData);
2547 
2548     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
2549     yDataColumn.replaceValues(0, yData);
2550 
2551     Column xErrorColumn("xerr", AbstractColumn::ColumnMode::Numeric);
2552     xErrorColumn.replaceValues(0, xError);
2553 
2554     Column yErrorColumn("yerr", AbstractColumn::ColumnMode::Numeric);
2555     yErrorColumn.replaceValues(0, yError);
2556 
2557     XYFitCurve fitCurve("fit");
2558     fitCurve.setXDataColumn(&xDataColumn);
2559     fitCurve.setYDataColumn(&yDataColumn);
2560     fitCurve.setXErrorColumn(&xErrorColumn);
2561     fitCurve.setYErrorColumn(&yErrorColumn);
2562 
2563     //prepare the fit
2564     XYFitCurve::FitData fitData = fitCurve.fitData();
2565     fitData.modelCategory = nsl_fit_model_custom;
2566     XYFitCurve::initFitData(fitData);
2567     fitData.model = "a1 + a2 * x";
2568     fitData.paramNames << "a1" << "a2";
2569     fitData.eps = 1.e-12;
2570     const int np = fitData.paramNames.size();
2571     fitData.paramStartValues << 5. << -0.5;
2572     for (int i = 0; i < np; i++) {
2573         fitData.paramLowerLimits << -std::numeric_limits<double>::max();
2574         fitData.paramUpperLimits << std::numeric_limits<double>::max();
2575     }
2576 
2577     fitData.xWeightsType = nsl_fit_weight_direct;
2578     fitData.yWeightsType = nsl_fit_weight_direct;
2579     fitCurve.setFitData(fitData);
2580 
2581     //perform the fit
2582     fitCurve.recalculate();
2583     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
2584 
2585     //check the results
2586     QCOMPARE(fitResult.available, true);
2587     QCOMPARE(fitResult.valid, true);
2588 
2589     QCOMPARE(np, 2);
2590 
2591     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 5.39605223831693
2592     FuzzyCompare(fitResult.paramValues.at(0), 5.39749958415886, 3.e-4); // gnuplot result ("effective variance" method)
2593     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 0.361458369696386
2594     FuzzyCompare(fitResult.errorValues.at(0), 0.361439886824914, 1.e-4);    // -""-
2595     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: -0.463448913528306
2596     FuzzyCompare(fitResult.paramValues.at(1), -0.463744669606207, 1.e-3);   // -""-
2597     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 0.0706627257036884
2598     FuzzyCompare(fitResult.errorValues.at(1), 0.0706637562101211, 1.e-4);   // -""-
2599 
2600     DEBUG(std::setprecision(15) << fitResult.rms);  // result: 1.49455596317092
2601     FuzzyCompare(fitResult.rms, 1.49417194665446, 1.e-3);   // gnuplot result ("effective variance" method)
2602     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 1.22252033241616
2603     FuzzyCompare(fitResult.rsd, 1.22236326296828, 1.e-3);   // -""-
2604     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 11.9564477053674
2605     FuzzyCompare(fitResult.sse, 11.9533755732357, 1.e-3);   // -""-
2606     DEBUG(std::setprecision(15) << fitResult.fdist_p);  // result: 0.00441031645455255
2607 //TODO  QCOMPARE(fitResult.fdist_p, 0.153296328355244);
2608 }
2609 
2610 // see http://gnuplot.sourceforge.net/demo_5.2/fit.html
2611 void FitTest::testLinearGP_PY_xyerror_custom_instrumental_weight() {
2612     // Pearson's data and York's weights
2613     QVector<double> xData = {0.0,0.9,1.8,2.6,3.3,4.4,5.2,6.1,6.5,7.4};
2614     QVector<double> yData = {5.9,5.4,4.4,4.6,3.5,3.7,2.8,2.8,2.4,1.5};
2615     QVector<double> xError = {1000.,1000.,500.,800.,200.,80.,60.,20.,1.8,1.0};
2616     QVector<double> yError = {1.0,1.8,4.,8.,20.,20.,70.,70.,100.,500.};
2617 
2618     // w_i -> s_i
2619     for (int i = 0; i < xError.size(); i++) {
2620         xError[i] = 1./sqrt(xError[i]);
2621         yError[i] = 1./sqrt(yError[i]);
2622     }
2623 
2624     //data source columns
2625     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
2626     xDataColumn.replaceValues(0, xData);
2627 
2628     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
2629     yDataColumn.replaceValues(0, yData);
2630 
2631     Column xErrorColumn("xerr", AbstractColumn::ColumnMode::Numeric);
2632     xErrorColumn.replaceValues(0, xError);
2633 
2634     Column yErrorColumn("yerr", AbstractColumn::ColumnMode::Numeric);
2635     yErrorColumn.replaceValues(0, yError);
2636 
2637     XYFitCurve fitCurve("fit");
2638     fitCurve.setXDataColumn(&xDataColumn);
2639     fitCurve.setYDataColumn(&yDataColumn);
2640     fitCurve.setXErrorColumn(&xErrorColumn);
2641     fitCurve.setYErrorColumn(&yErrorColumn);
2642 
2643     //prepare the fit
2644     XYFitCurve::FitData fitData = fitCurve.fitData();
2645     fitData.modelCategory = nsl_fit_model_custom;
2646     XYFitCurve::initFitData(fitData);
2647     fitData.model = "a1 + a2 * x";
2648     fitData.paramNames << "a1" << "a2";
2649 //  fitData.eps = 1.e-12;
2650     const int np = fitData.paramNames.size();
2651     fitData.paramStartValues << 5. << -0.5;
2652     for (int i = 0; i < np; i++) {
2653         fitData.paramLowerLimits << -std::numeric_limits<double>::max();
2654         fitData.paramUpperLimits << std::numeric_limits<double>::max();
2655     }
2656 
2657     fitData.xWeightsType = nsl_fit_weight_instrumental;
2658     fitData.yWeightsType = nsl_fit_weight_instrumental;
2659     fitCurve.setFitData(fitData);
2660 
2661     //perform the fit
2662     fitCurve.recalculate();
2663     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
2664 
2665     //check the results
2666     QCOMPARE(fitResult.available, true);
2667     QCOMPARE(fitResult.valid, true);
2668 
2669     QCOMPARE(np, 2);
2670 
2671     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 5.3960521880058
2672     FuzzyCompare(fitResult.paramValues.at(0), 5.39749958415886, 3.e-4); // gnuplot result ("effective variance" method)
2673     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 0.361458367406729
2674     FuzzyCompare(fitResult.errorValues.at(0), 0.361439886824914, 1.e-4);    // -""-
2675     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: -0.463448904801834
2676     FuzzyCompare(fitResult.paramValues.at(1), -0.463744669606207, 1.e-3);   // -""-
2677     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 0.0706627229337577
2678     FuzzyCompare(fitResult.errorValues.at(1), 0.0706637562101211, 1.e-4);   // -""-
2679 
2680     DEBUG(std::setprecision(15) << fitResult.rms);  // result: 1.49455610878403
2681     FuzzyCompare(fitResult.rms, 1.49417194665446, 1.e-3);   // gnuplot result ("effective variance" method)
2682     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 1.22252039197063
2683     FuzzyCompare(fitResult.rsd, 1.22236326296828, 1.e-3);   // -""-
2684     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 11.9564488702722
2685     FuzzyCompare(fitResult.sse, 11.9533755732357, 1.e-3);   // -""-
2686     DEBUG(std::setprecision(15) << fitResult.fdist_p);  // result: 0.00441031773039329
2687 //TODO  QCOMPARE(fitResult.fdist_p, 0.153296328355244);
2688 }
2689 
2690 // see http://gnuplot.sourceforge.net/demo_5.2/fit.html
2691 void FitTest::testLinearGP_PY_xyerror_custom_inverse_weight() {
2692     // Pearson's data and York's weights
2693     QVector<double> xData = {0.0,0.9,1.8,2.6,3.3,4.4,5.2,6.1,6.5,7.4};
2694     QVector<double> yData = {5.9,5.4,4.4,4.6,3.5,3.7,2.8,2.8,2.4,1.5};
2695     QVector<double> xError = {1000.,1000.,500.,800.,200.,80.,60.,20.,1.8,1.0};
2696     QVector<double> yError = {1.0,1.8,4.,8.,20.,20.,70.,70.,100.,500.};
2697 
2698     // w_i -> 1/w_i
2699     for (int i = 0; i < xError.size(); i++) {
2700         xError[i] = 1./xError[i];
2701         yError[i] = 1./yError[i];
2702     }
2703 
2704     //data source columns
2705     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
2706     xDataColumn.replaceValues(0, xData);
2707 
2708     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
2709     yDataColumn.replaceValues(0, yData);
2710 
2711     Column xErrorColumn("xerr", AbstractColumn::ColumnMode::Numeric);
2712     xErrorColumn.replaceValues(0, xError);
2713 
2714     Column yErrorColumn("yerr", AbstractColumn::ColumnMode::Numeric);
2715     yErrorColumn.replaceValues(0, yError);
2716 
2717     XYFitCurve fitCurve("fit");
2718     fitCurve.setXDataColumn(&xDataColumn);
2719     fitCurve.setYDataColumn(&yDataColumn);
2720     fitCurve.setXErrorColumn(&xErrorColumn);
2721     fitCurve.setYErrorColumn(&yErrorColumn);
2722 
2723     //prepare the fit
2724     XYFitCurve::FitData fitData = fitCurve.fitData();
2725     fitData.modelCategory = nsl_fit_model_custom;
2726     XYFitCurve::initFitData(fitData);
2727     fitData.model = "a1 + a2 * x";
2728     fitData.paramNames << "a1" << "a2";
2729 //  fitData.eps = 1.e-12;
2730     const int np = fitData.paramNames.size();
2731     fitData.paramStartValues << 5. << -0.5;
2732     for (int i = 0; i < np; i++) {
2733         fitData.paramLowerLimits << -std::numeric_limits<double>::max();
2734         fitData.paramUpperLimits << std::numeric_limits<double>::max();
2735     }
2736 
2737     fitData.xWeightsType = nsl_fit_weight_inverse;
2738     fitData.yWeightsType = nsl_fit_weight_inverse;
2739     fitCurve.setFitData(fitData);
2740 
2741     //perform the fit
2742     fitCurve.recalculate();
2743     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
2744 
2745     //check the results
2746     QCOMPARE(fitResult.available, true);
2747     QCOMPARE(fitResult.valid, true);
2748 
2749     QCOMPARE(np, 2);
2750 
2751     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 5.39605219384715
2752     FuzzyCompare(fitResult.paramValues.at(0), 5.39749958415886, 3.e-4); // gnuplot result ("effective variance" method)
2753     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 0.361458367208767
2754     FuzzyCompare(fitResult.errorValues.at(0), 0.361439886824914, 1.e-4);    // -""-
2755     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: -0.463448906090293
2756     FuzzyCompare(fitResult.paramValues.at(1), -0.463744669606207, 1.e-3);   // -""-
2757     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 0.0706627222052917
2758     FuzzyCompare(fitResult.errorValues.at(1), 0.0706637562101211, 1.e-4);   // -""-
2759 
2760     DEBUG(std::setprecision(15) << fitResult.rms);  // result: 1.49455610679827
2761     FuzzyCompare(fitResult.rms, 1.49417194665446, 1.e-3);   // gnuplot result ("effective variance" method)
2762     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 1.22252039115847
2763     FuzzyCompare(fitResult.rsd, 1.22236326296828, 1.e-3);   // -""-
2764     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 11.9564488543861
2765     FuzzyCompare(fitResult.sse, 11.9533755732357, 1.e-3);   // -""-
2766     DEBUG(std::setprecision(15) << fitResult.fdist_p);  // result: 0.00441031771299435
2767 //TODO  QCOMPARE(fitResult.fdist_p, 0.153296328355244);
2768 }
2769 
2770 // see https://bugs.kde.org/show_bug.cgi?id=408535
2771 void FitTest::testNonLinear_yerror_zero_bug408535() {
2772     QVector<double> xData = {0.0,320.,320.,360.,360.,400.,400.,440.,440.,480.,480.,520.,520.,560.,560.,600.,600.,640.,640.,680.,680.,720.,720.,760.,760.,800.,800.,840.,840.,880., 880.,1200.,1200.,1200.,1200.};
2773     QVector<double> yData = {0.0,160.,120.,190.,120.,210.,140.,220.,170.,230.,190.,240.,210.,250.,230.,270.,240.,260.,270.,290.,240.,310.,270.,320.,290.,330.,290.,320.,300.,330.,310.,370.,390.,390.,400.};
2774     QVector<double> yError = {0.0,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.,15.};
2775 
2776     //data source columns
2777     Column xDataColumn("x", AbstractColumn::ColumnMode::Numeric);
2778     xDataColumn.replaceValues(0, xData);
2779 
2780     Column yDataColumn("y", AbstractColumn::ColumnMode::Numeric);
2781     yDataColumn.replaceValues(0, yData);
2782 
2783     Column yErrorColumn("yerr", AbstractColumn::ColumnMode::Numeric);
2784     yErrorColumn.replaceValues(0, yError);
2785 
2786     XYFitCurve fitCurve("fit");
2787     fitCurve.setXDataColumn(&xDataColumn);
2788     fitCurve.setYDataColumn(&yDataColumn);
2789     fitCurve.setYErrorColumn(&yErrorColumn);
2790 
2791     //prepare the fit
2792     XYFitCurve::FitData fitData = fitCurve.fitData();
2793     fitData.modelCategory = nsl_fit_model_custom;
2794     XYFitCurve::initFitData(fitData);
2795     fitData.model = "A*exp(-B/x)";
2796     fitData.paramNames << "A" << "B";
2797 //  fitData.eps = 1.e-12;
2798     const int np = fitData.paramNames.size();
2799     fitData.paramStartValues << 100. << 100.;
2800     for (int i = 0; i < np; i++) {
2801         fitData.paramLowerLimits << -std::numeric_limits<double>::max();
2802         fitData.paramUpperLimits << std::numeric_limits<double>::max();
2803     }
2804 
2805     fitData.yWeightsType = nsl_fit_weight_instrumental;
2806     fitCurve.setFitData(fitData);
2807 
2808     //perform the fit
2809     fitCurve.recalculate();
2810     const XYFitCurve::FitResult& fitResult = fitCurve.fitResult();
2811 
2812     //check the results
2813     QCOMPARE(fitResult.available, true);
2814     QCOMPARE(fitResult.valid, true);
2815 
2816     QCOMPARE(np, 2);
2817 
2818     DEBUG(std::setprecision(15) << fitResult.paramValues.at(0));    // result: 557.463875234563, Win: 557.463888957409
2819     FuzzyCompare(fitResult.paramValues.at(0), 557.463875234563, 1.e-7);
2820     DEBUG(std::setprecision(15) << fitResult.errorValues.at(0));    // result: 22.0490332546127, FreeBSD: 22.0490429285665
2821     FuzzyCompare(fitResult.errorValues.at(0), 22.0490332546127, 1.e-6);
2822     DEBUG(std::setprecision(15) << fitResult.paramValues.at(1));    // result: 468.319724706721, Win: 468.319742522772
2823     FuzzyCompare(fitResult.paramValues.at(1), 468.319724706721, 1.e-7);
2824     DEBUG(std::setprecision(15) << fitResult.errorValues.at(1));    // result: 26.5105791274139, FreeBSD: 26.510591238283
2825     FuzzyCompare(fitResult.errorValues.at(1), 26.5105791274139, 1.e-6);
2826 
2827     DEBUG(std::setprecision(15) << fitResult.rms);  // result: 1.96172656494138
2828     FuzzyCompare(fitResult.rms, 1.96172656494138, 1.e-9);
2829     DEBUG(std::setprecision(15) << fitResult.rsd);  // result: 1.4006164945985
2830     FuzzyCompare(fitResult.rsd, 1.4006164945985, 1.e-9);
2831     DEBUG(std::setprecision(15) << fitResult.sse);  // result: 64.7369766430654
2832     FuzzyCompare(fitResult.sse, 64.7369766430654, 1.e-9);
2833     DEBUG(std::setprecision(15) << fitResult.rsquare);  // result: 0.999740417228134
2834     FuzzyCompare(fitResult.rsquare, 0.999740417228134, 1.e-9);
2835     DEBUG(std::setprecision(15) << fitResult.rsquareAdj);   // result: 0.999724193304893
2836     FuzzyCompare(fitResult.rsquareAdj, 0.999724193304893, 1.e-9);
2837 }
2838 
2839 QTEST_MAIN(FitTest)