File indexing completed on 2024-05-12 03:49:33

0001 /*
0002     File                 : NSLDFTTest.cpp
0003     Project              : LabPlot
0004     Description          : NSL Tests for DFT
0005     --------------------------------------------------------------------
0006     SPDX-FileCopyrightText: 2019 Stefan Gerlach <stefan.gerlach@uni.kn>
0007 
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 
0011 #include "NSLDFTTest.h"
0012 #include "backend/lib/macros.h"
0013 
0014 extern "C" {
0015 #include "backend/nsl/nsl_dft.h"
0016 }
0017 
0018 #define ONESIDED 0
0019 #define TWOSIDED 1
0020 const int N = 10;
0021 
0022 // ##############################################################################
0023 // #################  one sided tests
0024 // ##############################################################################
0025 
0026 void NSLDFTTest::testOnesided_real() {
0027     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0028     const double result[] = {10, 2, -5.85410196624968, 2, 0.854101966249685};
0029 
0030     nsl_dft_transform(data, 1, N, ONESIDED, nsl_dft_result_real);
0031     for (unsigned int i = 0; i < N / 2; i++)
0032         QCOMPARE(data[i], result[i]);
0033 }
0034 
0035 void NSLDFTTest::testOnesided_imag() {
0036     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0037     const double result[] = {0, -4.97979656976556, 0, 0.449027976579585, 0};
0038 
0039     nsl_dft_transform(data, 1, N, ONESIDED, nsl_dft_result_imag);
0040     for (unsigned int i = 0; i < N / 2; i++) {
0041         DEBUG(std::setprecision(15) << data[i]);
0042         if (i == 2)
0043             QCOMPARE(data[i] + 1., 1.); // -1.11022302462516e-16 (Win)
0044         else
0045             QCOMPARE(data[i], result[i]);
0046     }
0047 }
0048 
0049 void NSLDFTTest::testOnesided_magnitude() {
0050     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0051     const double result[] = {10, 5.36641163872553, 5.85410196624968, 2.04978684837013, 0.854101966249685};
0052 
0053     nsl_dft_transform(data, 1, N, ONESIDED, nsl_dft_result_magnitude);
0054     for (unsigned int i = 0; i < N / 2; i++)
0055         QCOMPARE(data[i], result[i]);
0056 }
0057 
0058 void NSLDFTTest::testOnesided_amplitude() {
0059     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0060     const double result[] = {1, 1.07328232774511, 1.17082039324994, 0.409957369674026, 0.170820393249937};
0061 
0062     nsl_dft_transform(data, 1, N, ONESIDED, nsl_dft_result_amplitude);
0063     for (unsigned int i = 0; i < N / 2; i++)
0064         QCOMPARE(data[i], result[i]);
0065 }
0066 
0067 void NSLDFTTest::testOnesided_power() {
0068     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0069     const double result[] = {10, 5.75967477524977, 6.85410196624968, 0.840325224750231, 0.145898033750316};
0070 
0071     nsl_dft_transform(data, 1, N, ONESIDED, nsl_dft_result_power);
0072     for (unsigned int i = 0; i < N / 2; i++)
0073         QCOMPARE(data[i], result[i]);
0074 }
0075 
0076 void NSLDFTTest::testOnesided_phase() {
0077     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0078     const double result[] = {0, 1.18889174012102, -3.14159265358979, -0.220851801285041, 0};
0079 
0080     nsl_dft_transform(data, 1, N, ONESIDED, nsl_dft_result_phase);
0081     for (unsigned int i = 0; i < N / 2; i++) {
0082         DEBUG(std::setprecision(15) << data[i]);
0083         if (i == 2) // sign can be + or -
0084             QCOMPARE(fabs(data[i]), fabs(result[i]));
0085         else
0086             QCOMPARE(data[i], result[i]);
0087     }
0088 }
0089 
0090 void NSLDFTTest::testOnesided_dB() {
0091     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0092     const double result[] = {0, 0.614279569861449, 1.36980556663896, -7.7452260401377, -15.3492056533593};
0093 
0094     nsl_dft_transform(data, 1, N, ONESIDED, nsl_dft_result_dB);
0095     for (unsigned int i = 0; i < N / 2; i++)
0096         QCOMPARE(data[i], result[i]);
0097 }
0098 
0099 void NSLDFTTest::testOnesided_squaremagnitude() {
0100     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0101     const double result[] = {100, 28.7983738762488, 34.2705098312484, 4.20162612375116, 0.729490168751578};
0102 
0103     nsl_dft_transform(data, 1, N, ONESIDED, nsl_dft_result_squaremagnitude);
0104     for (unsigned int i = 0; i < N / 2; i++)
0105         QCOMPARE(data[i], result[i]);
0106 }
0107 
0108 void NSLDFTTest::testOnesided_squareamplitude() {
0109     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0110     const double result[] = {1, 1.15193495504995, 1.37082039324994, 0.168065044950046, 0.0291796067500631};
0111 
0112     nsl_dft_transform(data, 1, N, ONESIDED, nsl_dft_result_squareamplitude);
0113     for (unsigned int i = 0; i < N / 2; i++)
0114         QCOMPARE(data[i], result[i]);
0115 }
0116 
0117 void NSLDFTTest::testOnesided_normdB() {
0118     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0119     const double result[] = {-1.36980556663896, -0.755525996777514, 0, -9.11503160677666, -16.7190112199983};
0120 
0121     nsl_dft_transform(data, 1, N, ONESIDED, nsl_dft_result_normdB);
0122     for (unsigned int i = 0; i < N / 2; i++)
0123         QCOMPARE(data[i], result[i]);
0124 }
0125 
0126 // ##############################################################################
0127 // #################  two sided tests
0128 // ##############################################################################
0129 
0130 void NSLDFTTest::testTwosided_real() {
0131     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0132     const double result[] = {10, 2, -5.85410196624968, 2, 0.854101966249685, 2, 0.854101966249685, 2, -5.85410196624968, 2};
0133 
0134     nsl_dft_transform(data, 1, N, TWOSIDED, nsl_dft_result_real);
0135     for (unsigned int i = 0; i < N; i++)
0136         QCOMPARE(data[i], result[i]);
0137 }
0138 
0139 void NSLDFTTest::testTwosided_imag() {
0140     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0141     const double result[] = {0, -4.97979656976556, 0, 0.449027976579585, 0, 0, 0, -0.449027976579585, 0, 4.97979656976556};
0142 
0143     nsl_dft_transform(data, 1, N, TWOSIDED, nsl_dft_result_imag);
0144     for (unsigned int i = 0; i < N; i++) {
0145         DEBUG(std::setprecision(15) << data[i]);
0146         if (i == 2 || i == 8)
0147             QCOMPARE(data[i] + 1., 1.); // -1.11022302462516e-16 (Win)
0148         else
0149             QCOMPARE(data[i], result[i]);
0150     }
0151 }
0152 
0153 void NSLDFTTest::testTwosided_magnitude() {
0154     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0155     const double result[] = {10,
0156                              5.36641163872553,
0157                              5.85410196624968,
0158                              2.04978684837013,
0159                              0.854101966249685,
0160                              2,
0161                              0.854101966249685,
0162                              2.04978684837013,
0163                              5.85410196624968,
0164                              5.36641163872553};
0165 
0166     nsl_dft_transform(data, 1, N, TWOSIDED, nsl_dft_result_magnitude);
0167     for (unsigned int i = 0; i < N; i++)
0168         QCOMPARE(data[i], result[i]);
0169 }
0170 
0171 void NSLDFTTest::testTwosided_amplitude() {
0172     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0173     const double result[] = {1,
0174                              1.07328232774511,
0175                              1.17082039324994,
0176                              0.409957369674026,
0177                              0.170820393249937,
0178                              0.4,
0179                              0.170820393249937,
0180                              0.409957369674026,
0181                              1.17082039324994,
0182                              1.07328232774511};
0183 
0184     nsl_dft_transform(data, 1, N, TWOSIDED, nsl_dft_result_amplitude);
0185     for (unsigned int i = 0; i < N; i++)
0186         QCOMPARE(data[i], result[i]);
0187 }
0188 
0189 void NSLDFTTest::testTwosided_power() {
0190     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0191     const double result[] = {10,
0192                              5.75967477524977,
0193                              6.85410196624968,
0194                              0.840325224750231,
0195                              0.145898033750316,
0196                              0.8,
0197                              0.145898033750316,
0198                              0.840325224750231,
0199                              6.85410196624968,
0200                              5.75967477524977};
0201 
0202     nsl_dft_transform(data, 1, N, TWOSIDED, nsl_dft_result_power);
0203     for (unsigned int i = 0; i < N; i++)
0204         QCOMPARE(data[i], result[i]);
0205 }
0206 
0207 void NSLDFTTest::testTwosided_phase() {
0208     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0209     const double result[] = {0, 1.18889174012102, -3.14159265358979, -0.220851801285041, 0, 0, 0, 0.220851801285041, 3.14159265358979, -1.18889174012102};
0210 
0211     nsl_dft_transform(data, 1, N, TWOSIDED, nsl_dft_result_phase);
0212     for (unsigned int i = 0; i < N; i++) {
0213         DEBUG(std::setprecision(15) << data[i]);
0214         if (i == 2 || i == 8) // sign can be + or -
0215             QCOMPARE(fabs(data[i]), fabs(result[i]));
0216         else
0217             QCOMPARE(data[i], result[i]);
0218     }
0219 }
0220 
0221 void NSLDFTTest::testTwosided_dB() {
0222     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0223     const double result[] = {0,
0224                              0.614279569861449,
0225                              1.36980556663896,
0226                              -7.7452260401377,
0227                              -15.3492056533593,
0228                              -7.95880017344075,
0229                              -15.3492056533593,
0230                              -7.7452260401377,
0231                              1.36980556663896,
0232                              0.614279569861449};
0233 
0234     nsl_dft_transform(data, 1, N, TWOSIDED, nsl_dft_result_dB);
0235     for (unsigned int i = 0; i < N; i++)
0236         QCOMPARE(data[i], result[i]);
0237 }
0238 
0239 void NSLDFTTest::testTwosided_squaremagnitude() {
0240     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0241     const double result[] = {100,
0242                              28.7983738762488,
0243                              34.2705098312484,
0244                              4.20162612375116,
0245                              0.729490168751578,
0246                              4,
0247                              0.729490168751578,
0248                              4.20162612375116,
0249                              34.2705098312484,
0250                              28.7983738762488};
0251 
0252     nsl_dft_transform(data, 1, N, TWOSIDED, nsl_dft_result_squaremagnitude);
0253     for (unsigned int i = 0; i < N; i++)
0254         QCOMPARE(data[i], result[i]);
0255 }
0256 
0257 void NSLDFTTest::testTwosided_squareamplitude() {
0258     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0259     const double result[] = {1,
0260                              1.15193495504995,
0261                              1.37082039324994,
0262                              0.168065044950046,
0263                              0.0291796067500631,
0264                              0.16,
0265                              0.0291796067500631,
0266                              0.168065044950046,
0267                              1.37082039324994,
0268                              1.15193495504995};
0269 
0270     nsl_dft_transform(data, 1, N, TWOSIDED, nsl_dft_result_squareamplitude);
0271     for (unsigned int i = 0; i < N; i++)
0272         QCOMPARE(data[i], result[i]);
0273 }
0274 
0275 void NSLDFTTest::testTwosided_normdB() {
0276     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0277     const double result[] = {-1.36980556663896,
0278                              -0.755525996777514,
0279                              0,
0280                              -9.11503160677666,
0281                              -16.7190112199983,
0282                              -9.32860574007971,
0283                              -16.7190112199983,
0284                              -9.11503160677666,
0285                              0,
0286                              -0.755525996777514};
0287 
0288     nsl_dft_transform(data, 1, N, TWOSIDED, nsl_dft_result_normdB);
0289     for (unsigned int i = 0; i < N; i++)
0290         QCOMPARE(data[i], result[i]);
0291 }
0292 
0293 // ##############################################################################
0294 // #################  performance
0295 // ##############################################################################
0296 
0297 #ifdef HAVE_FFTW3
0298 const int NN = 1e6;
0299 #else // GSL is much slower
0300 const int NN = 1e6;
0301 #endif
0302 
0303 void NSLDFTTest::testPerformance_onesided() {
0304     double* data = new double[NN];
0305 
0306     for (int i = 0; i < NN; i++)
0307         data[i] = 1.;
0308 
0309     QBENCHMARK { nsl_dft_transform(data, 1, NN, ONESIDED, nsl_dft_result_real); }
0310 
0311     delete[] data;
0312 }
0313 
0314 void NSLDFTTest::testPerformance_twosided() {
0315     double* data = new double[NN];
0316 
0317     for (int i = 0; i < NN; i++)
0318         data[i] = 1.;
0319 
0320     QBENCHMARK { nsl_dft_transform(data, 1, NN, TWOSIDED, nsl_dft_result_real); }
0321 
0322     delete[] data;
0323 }
0324 
0325 QTEST_MAIN(NSLDFTTest)