File indexing completed on 2024-05-05 03:48:24

0001 /*
0002     File                 : DifferentiationTest.cpp
0003     Project              : LabPlot
0004     Description          : Tests for numerical differentiation
0005     --------------------------------------------------------------------
0006     SPDX-FileCopyrightText: 2018-2022 Stefan Gerlach <stefan.gerlach@uni.kn>
0007 
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 
0011 #include "DifferentiationTest.h"
0012 #include "backend/core/column/Column.h"
0013 #include "backend/worksheet/plots/cartesian/XYDifferentiationCurve.h"
0014 
0015 // ##############################################################################
0016 
0017 void DifferentiationTest::testLinear() {
0018     // data
0019     QVector<int> xData = {1, 2, 3, 4};
0020     QVector<double> yData = {1., 2., 3., 4.};
0021 
0022     // data source columns
0023     Column xDataColumn(QStringLiteral("x"), AbstractColumn::ColumnMode::Integer);
0024     xDataColumn.replaceInteger(0, xData);
0025 
0026     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0027     yDataColumn.replaceValues(0, yData);
0028 
0029     XYDifferentiationCurve differentiationCurve(QStringLiteral("differentiation"));
0030     differentiationCurve.setXDataColumn(&xDataColumn);
0031     differentiationCurve.setYDataColumn(&yDataColumn);
0032 
0033     // prepare the differentiation
0034     XYDifferentiationCurve::DifferentiationData differentiationData = differentiationCurve.differentiationData();
0035     differentiationCurve.setDifferentiationData(differentiationData);
0036 
0037     // perform the differentiation
0038     differentiationCurve.recalculate();
0039     const XYDifferentiationCurve::DifferentiationResult& differentiationResult = differentiationCurve.differentiationResult();
0040 
0041     // check the results
0042     QCOMPARE(differentiationResult.available, true);
0043     QCOMPARE(differentiationResult.valid, true);
0044 
0045     const AbstractColumn* resultXDataColumn = differentiationCurve.xColumn();
0046     const AbstractColumn* resultYDataColumn = differentiationCurve.yColumn();
0047 
0048     const int np = resultXDataColumn->rowCount();
0049     QCOMPARE(np, 4);
0050 
0051     for (int i = 0; i < np; i++)
0052         QCOMPARE(resultXDataColumn->valueAt(i), (double)i + 1);
0053 
0054     QCOMPARE(resultYDataColumn->valueAt(0), 1.);
0055     QCOMPARE(resultYDataColumn->valueAt(1), 1.);
0056     QCOMPARE(resultYDataColumn->valueAt(2), 1.);
0057     QCOMPARE(resultYDataColumn->valueAt(3), 1.);
0058 }
0059 
0060 void DifferentiationTest::testLinearNonEquidistant() {
0061     // data
0062     QVector<double> xData = {1., 1.5, 3., 5.};
0063     QVector<double> yData = {1., 1.5, 3., 5.};
0064 
0065     // data source columns
0066     Column xDataColumn(QStringLiteral("x"), AbstractColumn::ColumnMode::Double);
0067     xDataColumn.replaceValues(0, xData);
0068 
0069     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0070     yDataColumn.replaceValues(0, yData);
0071 
0072     XYDifferentiationCurve differentiationCurve(QStringLiteral("differentiation"));
0073     differentiationCurve.setXDataColumn(&xDataColumn);
0074     differentiationCurve.setYDataColumn(&yDataColumn);
0075 
0076     // prepare the differentiation
0077     XYDifferentiationCurve::DifferentiationData differentiationData = differentiationCurve.differentiationData();
0078     differentiationCurve.setDifferentiationData(differentiationData);
0079 
0080     // perform the differentiation
0081     differentiationCurve.recalculate();
0082     const XYDifferentiationCurve::DifferentiationResult& differentiationResult = differentiationCurve.differentiationResult();
0083 
0084     // check the results
0085     QCOMPARE(differentiationResult.available, true);
0086     QCOMPARE(differentiationResult.valid, true);
0087 
0088     const AbstractColumn* resultXDataColumn = differentiationCurve.xColumn();
0089     const AbstractColumn* resultYDataColumn = differentiationCurve.yColumn();
0090 
0091     const int np = resultXDataColumn->rowCount();
0092     QCOMPARE(np, 4);
0093 
0094     for (int i = 0; i < np; i++)
0095         QCOMPARE(resultXDataColumn->valueAt(i), xData[i]);
0096 
0097     QCOMPARE(resultYDataColumn->valueAt(0), 1.);
0098     QCOMPARE(resultYDataColumn->valueAt(1), 1.);
0099     QCOMPARE(resultYDataColumn->valueAt(2), 1.);
0100     QCOMPARE(resultYDataColumn->valueAt(3), 1.);
0101 }
0102 
0103 void DifferentiationTest::testQuadratic() {
0104     // data
0105     QVector<double> xData = {1., 2., 3., 4.};
0106     QVector<double> yData = {1., 4., 9., 16.};
0107 
0108     // data source columns
0109     Column xDataColumn(QStringLiteral("x"), AbstractColumn::ColumnMode::Double);
0110     xDataColumn.replaceValues(0, xData);
0111 
0112     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0113     yDataColumn.replaceValues(0, yData);
0114 
0115     XYDifferentiationCurve differentiationCurve(QStringLiteral("differentiation"));
0116     differentiationCurve.setXDataColumn(&xDataColumn);
0117     differentiationCurve.setYDataColumn(&yDataColumn);
0118 
0119     // prepare the differentiation
0120     XYDifferentiationCurve::DifferentiationData differentiationData = differentiationCurve.differentiationData();
0121     differentiationCurve.setDifferentiationData(differentiationData);
0122 
0123     // perform the differentiation
0124     differentiationCurve.recalculate();
0125     const XYDifferentiationCurve::DifferentiationResult& differentiationResult = differentiationCurve.differentiationResult();
0126 
0127     // check the results
0128     QCOMPARE(differentiationResult.available, true);
0129     QCOMPARE(differentiationResult.valid, true);
0130 
0131     const AbstractColumn* resultXDataColumn = differentiationCurve.xColumn();
0132     const AbstractColumn* resultYDataColumn = differentiationCurve.yColumn();
0133 
0134     const int np = resultXDataColumn->rowCount();
0135     QCOMPARE(np, 4);
0136 
0137     for (int i = 0; i < np; i++)
0138         QCOMPARE(resultXDataColumn->valueAt(i), xData[i]);
0139 
0140     QCOMPARE(resultYDataColumn->valueAt(0), 2.);
0141     QCOMPARE(resultYDataColumn->valueAt(1), 4.);
0142     QCOMPARE(resultYDataColumn->valueAt(2), 6.);
0143     QCOMPARE(resultYDataColumn->valueAt(3), 8.);
0144 }
0145 
0146 void DifferentiationTest::testQuadraticNonEquidistant() {
0147     // data
0148     QVector<double> xData = {1., 1.5, 3., 5.};
0149     QVector<double> yData = {1., 2.25, 9., 25.};
0150 
0151     // data source columns
0152     Column xDataColumn(QStringLiteral("x"), AbstractColumn::ColumnMode::Double);
0153     xDataColumn.replaceValues(0, xData);
0154 
0155     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0156     yDataColumn.replaceValues(0, yData);
0157 
0158     XYDifferentiationCurve differentiationCurve(QStringLiteral("differentiation"));
0159     differentiationCurve.setXDataColumn(&xDataColumn);
0160     differentiationCurve.setYDataColumn(&yDataColumn);
0161 
0162     // prepare the differentiation
0163     XYDifferentiationCurve::DifferentiationData differentiationData = differentiationCurve.differentiationData();
0164     differentiationCurve.setDifferentiationData(differentiationData);
0165 
0166     // perform the differentiation
0167     differentiationCurve.recalculate();
0168     const XYDifferentiationCurve::DifferentiationResult& differentiationResult = differentiationCurve.differentiationResult();
0169 
0170     // check the results
0171     QCOMPARE(differentiationResult.available, true);
0172     QCOMPARE(differentiationResult.valid, true);
0173 
0174     const AbstractColumn* resultXDataColumn = differentiationCurve.xColumn();
0175     const AbstractColumn* resultYDataColumn = differentiationCurve.yColumn();
0176 
0177     const int np = resultXDataColumn->rowCount();
0178     QCOMPARE(np, 4);
0179 
0180     for (int i = 0; i < np; i++)
0181         QCOMPARE(resultXDataColumn->valueAt(i), xData[i]);
0182 
0183     QCOMPARE(resultYDataColumn->valueAt(0), 2.);
0184     QCOMPARE(resultYDataColumn->valueAt(1), 3.);
0185     QCOMPARE(resultYDataColumn->valueAt(2), 6.);
0186     QCOMPARE(resultYDataColumn->valueAt(3), 10.);
0187 }
0188 
0189 void DifferentiationTest::testQuadraticSecondOrder() {
0190     // data
0191     QVector<double> xData = {1., 2., 3., 4.};
0192     QVector<double> yData = {1., 4., 9., 16.};
0193 
0194     // data source columns
0195     Column xDataColumn(QStringLiteral("x"), AbstractColumn::ColumnMode::Double);
0196     xDataColumn.replaceValues(0, xData);
0197 
0198     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0199     yDataColumn.replaceValues(0, yData);
0200 
0201     XYDifferentiationCurve differentiationCurve(QStringLiteral("differentiation"));
0202     differentiationCurve.setXDataColumn(&xDataColumn);
0203     differentiationCurve.setYDataColumn(&yDataColumn);
0204 
0205     // prepare the differentiation
0206     XYDifferentiationCurve::DifferentiationData differentiationData = differentiationCurve.differentiationData();
0207     differentiationData.derivOrder = nsl_diff_deriv_order_second;
0208     differentiationCurve.setDifferentiationData(differentiationData);
0209 
0210     // perform the differentiation
0211     differentiationCurve.recalculate();
0212     const XYDifferentiationCurve::DifferentiationResult& differentiationResult = differentiationCurve.differentiationResult();
0213 
0214     // check the results
0215     QCOMPARE(differentiationResult.available, true);
0216     QCOMPARE(differentiationResult.valid, true);
0217 
0218     const AbstractColumn* resultXDataColumn = differentiationCurve.xColumn();
0219     const AbstractColumn* resultYDataColumn = differentiationCurve.yColumn();
0220 
0221     const int np = resultXDataColumn->rowCount();
0222     QCOMPARE(np, 4);
0223 
0224     for (int i = 0; i < np; i++)
0225         QCOMPARE(resultXDataColumn->valueAt(i), xData[i]);
0226 
0227     QCOMPARE(resultYDataColumn->valueAt(0), 2.);
0228     QCOMPARE(resultYDataColumn->valueAt(1), 2.);
0229     QCOMPARE(resultYDataColumn->valueAt(2), 2.);
0230     QCOMPARE(resultYDataColumn->valueAt(3), 2.);
0231 }
0232 
0233 void DifferentiationTest::testCubicSecondOrder() {
0234     // data
0235     QVector<double> xData = {1., 2., 3., 4.};
0236     QVector<double> yData = {1., 8., 27., 64.};
0237 
0238     // data source columns
0239     Column xDataColumn(QStringLiteral("x"), AbstractColumn::ColumnMode::Double);
0240     xDataColumn.replaceValues(0, xData);
0241 
0242     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0243     yDataColumn.replaceValues(0, yData);
0244 
0245     XYDifferentiationCurve differentiationCurve(QStringLiteral("differentiation"));
0246     differentiationCurve.setXDataColumn(&xDataColumn);
0247     differentiationCurve.setYDataColumn(&yDataColumn);
0248 
0249     // prepare the differentiation
0250     XYDifferentiationCurve::DifferentiationData differentiationData = differentiationCurve.differentiationData();
0251     differentiationData.derivOrder = nsl_diff_deriv_order_second;
0252     differentiationCurve.setDifferentiationData(differentiationData);
0253 
0254     // perform the differentiation
0255     differentiationCurve.recalculate();
0256     const XYDifferentiationCurve::DifferentiationResult& differentiationResult = differentiationCurve.differentiationResult();
0257 
0258     // check the results
0259     QCOMPARE(differentiationResult.available, true);
0260     QCOMPARE(differentiationResult.valid, true);
0261 
0262     const AbstractColumn* resultXDataColumn = differentiationCurve.xColumn();
0263     const AbstractColumn* resultYDataColumn = differentiationCurve.yColumn();
0264 
0265     const int np = resultXDataColumn->rowCount();
0266     QCOMPARE(np, 4);
0267 
0268     for (int i = 0; i < np; i++)
0269         QCOMPARE(resultXDataColumn->valueAt(i), xData[i]);
0270 
0271     QCOMPARE(resultYDataColumn->valueAt(0), 6.);
0272     QCOMPARE(resultYDataColumn->valueAt(1), 12.);
0273     QCOMPARE(resultYDataColumn->valueAt(2), 18.);
0274     QCOMPARE(resultYDataColumn->valueAt(3), 24.);
0275 }
0276 
0277 void DifferentiationTest::testCubicThirdOrder() {
0278     // data
0279     QVector<double> xData = {1., 2., 3., 4., 5.};
0280     QVector<double> yData = {1., 8., 27., 64., 125.};
0281 
0282     // data source columns
0283     Column xDataColumn(QStringLiteral("x"), AbstractColumn::ColumnMode::Double);
0284     xDataColumn.replaceValues(0, xData);
0285 
0286     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0287     yDataColumn.replaceValues(0, yData);
0288 
0289     XYDifferentiationCurve differentiationCurve(QStringLiteral("differentiation"));
0290     differentiationCurve.setXDataColumn(&xDataColumn);
0291     differentiationCurve.setYDataColumn(&yDataColumn);
0292 
0293     // prepare the differentiation
0294     XYDifferentiationCurve::DifferentiationData differentiationData = differentiationCurve.differentiationData();
0295     differentiationData.derivOrder = nsl_diff_deriv_order_third;
0296     differentiationCurve.setDifferentiationData(differentiationData);
0297 
0298     // perform the differentiation
0299     differentiationCurve.recalculate();
0300     const XYDifferentiationCurve::DifferentiationResult& differentiationResult = differentiationCurve.differentiationResult();
0301 
0302     // check the results
0303     QCOMPARE(differentiationResult.available, true);
0304     QCOMPARE(differentiationResult.valid, true);
0305 
0306     const AbstractColumn* resultXDataColumn = differentiationCurve.xColumn();
0307     const AbstractColumn* resultYDataColumn = differentiationCurve.yColumn();
0308 
0309     const int np = resultXDataColumn->rowCount();
0310     QCOMPARE(np, 5);
0311 
0312     for (int i = 0; i < np; i++)
0313         QCOMPARE(resultXDataColumn->valueAt(i), xData[i]);
0314 
0315     QCOMPARE(resultYDataColumn->valueAt(0), 6.);
0316     QCOMPARE(resultYDataColumn->valueAt(1), 6.);
0317     QCOMPARE(resultYDataColumn->valueAt(2), 6.);
0318     QCOMPARE(resultYDataColumn->valueAt(3), 6.);
0319     QCOMPARE(resultYDataColumn->valueAt(4), 6.);
0320 }
0321 
0322 void DifferentiationTest::testLinearDuplicateX() {
0323     // data
0324     QVector<int> xData = {1, 1, 2, 2, 3, 4, 4, 4, 5, 5};
0325     QVector<double> yData = {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.};
0326 
0327     // data source columns
0328     Column xDataColumn(QStringLiteral("x"), AbstractColumn::ColumnMode::Integer);
0329     xDataColumn.replaceInteger(0, xData);
0330 
0331     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0332     yDataColumn.replaceValues(0, yData);
0333 
0334     XYDifferentiationCurve differentiationCurve(QStringLiteral("differentiation"));
0335     differentiationCurve.setXDataColumn(&xDataColumn);
0336     differentiationCurve.setYDataColumn(&yDataColumn);
0337 
0338     // prepare the differentiation
0339     XYDifferentiationCurve::DifferentiationData differentiationData = differentiationCurve.differentiationData();
0340     differentiationCurve.setDifferentiationData(differentiationData);
0341 
0342     // perform the differentiation
0343     differentiationCurve.recalculate();
0344     const XYDifferentiationCurve::DifferentiationResult& differentiationResult = differentiationCurve.differentiationResult();
0345 
0346     /*for (int i = 0; i < 5; i++)
0347         QCOMPARE(xDataColumn.valueAt(i), (double)i + 1);
0348 
0349     QCOMPARE(yDataColumn.valueAt(0), 1.5);
0350     QCOMPARE(yDataColumn.valueAt(1), 3.5);
0351     QCOMPARE(yDataColumn.valueAt(2), 5.);
0352     QCOMPARE(yDataColumn.valueAt(3), 7.);
0353     QCOMPARE(yDataColumn.valueAt(4), 9.5);
0354     */
0355 
0356     // check the results
0357     QCOMPARE(differentiationResult.available, true);
0358     QCOMPARE(differentiationResult.valid, true);
0359 
0360     const AbstractColumn* resultXDataColumn = differentiationCurve.xColumn();
0361     const AbstractColumn* resultYDataColumn = differentiationCurve.yColumn();
0362 
0363     const int np = resultXDataColumn->rowCount();
0364     QCOMPARE(np, 5);
0365 
0366     for (int i = 0; i < np; i++)
0367         QCOMPARE(resultXDataColumn->valueAt(i), (double)i + 1);
0368 
0369     QCOMPARE(resultYDataColumn->valueAt(0), 2.25);
0370     QCOMPARE(resultYDataColumn->valueAt(1), 1.75);
0371     QCOMPARE(resultYDataColumn->valueAt(2), 3.);
0372     QCOMPARE(resultYDataColumn->valueAt(3), 2.5);
0373     QCOMPARE(resultYDataColumn->valueAt(4), -1.5);
0374 }
0375 
0376 QTEST_MAIN(DifferentiationTest)