File indexing completed on 2024-04-28 15:14:10

0001 /***************************************************************************
0002     File                 : NSLDFTTest.cpp
0003     Project              : LabPlot
0004     Description          : NSL Tests for DFT
0005     --------------------------------------------------------------------
0006     Copyright            : (C) 2019 Stefan Gerlach (stefan.gerlach@uni.kn)
0007  ***************************************************************************/
0008 
0009 /***************************************************************************
0010  *                                                                         *
0011  *  This program is free software; you can redistribute it and/or modify   *
0012  *  it under the terms of the GNU General Public License as published by   *
0013  *  the Free Software Foundation; either version 2 of the License, or      *
0014  *  (at your option) any later version.                                    *
0015  *                                                                         *
0016  *  This program is distributed in the hope that it will be useful,        *
0017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
0018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
0019  *  GNU General Public License for more details.                           *
0020  *                                                                         *
0021  *   You should have received a copy of the GNU General Public License     *
0022  *   along with this program; if not, write to the Free Software           *
0023  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
0024  *   Boston, MA  02110-1301  USA                                           *
0025  *                                                                         *
0026  ***************************************************************************/
0027 
0028 #include "NSLDFTTest.h"
0029 #include "backend/lib/macros.h"
0030 
0031 extern "C" {
0032 #include "backend/nsl/nsl_dft.h"
0033 }
0034 
0035 #define ONESIDED 0
0036 #define TWOSIDED 1
0037 const int N = 10;
0038 
0039 //##############################################################################
0040 //#################  one sided tests
0041 //##############################################################################
0042 
0043 void NSLDFTTest::testOnesided_real() {
0044     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0045     double result[] = {10, 2, -5.85410196624968, 2, 0.854101966249685};
0046 
0047     nsl_dft_transform(data, 1, N, ONESIDED, nsl_dft_result_real);
0048     for (unsigned int i = 0; i < N/2; i++)
0049         QCOMPARE(data[i], result[i]);
0050 }
0051 
0052 void NSLDFTTest::testOnesided_imag() {
0053     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0054     double result[] = {0, -4.97979656976556, 0, 0.449027976579585, 0};
0055 
0056     nsl_dft_transform(data, 1, N, ONESIDED, nsl_dft_result_imag);
0057     for (unsigned int i = 0; i < N/2; i++) {
0058         DEBUG(std::setprecision(15) << data[i]);
0059         if (i == 2)
0060             QCOMPARE(data[i] + 1., 1.); // -1.11022302462516e-16 (Win)
0061         else
0062             QCOMPARE(data[i], result[i]);
0063     }
0064 }
0065 
0066 void NSLDFTTest::testOnesided_magnitude() {
0067     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0068     double result[] = {10, 5.36641163872553, 5.85410196624968, 2.04978684837013, 0.854101966249685};
0069 
0070     nsl_dft_transform(data, 1, N, ONESIDED, nsl_dft_result_magnitude);
0071     for (unsigned int i = 0; i < N/2; i++)
0072         QCOMPARE(data[i], result[i]);
0073 }
0074 
0075 void NSLDFTTest::testOnesided_amplitude() {
0076     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0077     double result[] = {1, 1.07328232774511, 1.17082039324994, 0.409957369674026, 0.170820393249937};
0078 
0079     nsl_dft_transform(data, 1, N, ONESIDED, nsl_dft_result_amplitude);
0080     for (unsigned int i = 0; i < N/2; i++)
0081         QCOMPARE(data[i], result[i]);
0082 }
0083 
0084 void NSLDFTTest::testOnesided_power() {
0085     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0086     double result[] = {10, 5.75967477524977, 6.85410196624968, 0.840325224750231, 0.145898033750316};
0087 
0088     nsl_dft_transform(data, 1, N, ONESIDED, nsl_dft_result_power);
0089     for (unsigned int i = 0; i < N/2; i++)
0090         QCOMPARE(data[i], result[i]);
0091 }
0092 
0093 void NSLDFTTest::testOnesided_phase() {
0094     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0095     double result[] = {0, 1.18889174012102, -3.14159265358979, -0.220851801285041, 0};
0096 
0097     nsl_dft_transform(data, 1, N, ONESIDED, nsl_dft_result_phase);
0098     for (unsigned int i = 0; i < N/2; i++) {
0099         DEBUG(std::setprecision(15) << data[i]);
0100         if (i == 2) // sign can be + or -
0101             QCOMPARE(fabs(data[i]), fabs(result[i]));
0102         else
0103             QCOMPARE(data[i], result[i]);
0104     }
0105 }
0106 
0107 void NSLDFTTest::testOnesided_dB() {
0108     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0109     double result[] = {0, 0.614279569861449, 1.36980556663896, -7.7452260401377, -15.3492056533593};
0110 
0111     nsl_dft_transform(data, 1, N, ONESIDED, nsl_dft_result_dB);
0112     for (unsigned int i = 0; i < N/2; i++)
0113         QCOMPARE(data[i], result[i]);
0114 }
0115 
0116 void NSLDFTTest::testOnesided_squaremagnitude() {
0117     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0118     double result[] = {100, 28.7983738762488, 34.2705098312484, 4.20162612375116, 0.729490168751578};
0119 
0120     nsl_dft_transform(data, 1, N, ONESIDED, nsl_dft_result_squaremagnitude);
0121     for (unsigned int i = 0; i < N/2; i++)
0122         QCOMPARE(data[i], result[i]);
0123 }
0124 
0125 void NSLDFTTest::testOnesided_squareamplitude() {
0126     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0127     double result[] = {1, 1.15193495504995, 1.37082039324994, 0.168065044950046, 0.0291796067500631};
0128 
0129     nsl_dft_transform(data, 1, N, ONESIDED, nsl_dft_result_squareamplitude);
0130     for (unsigned int i = 0; i < N/2; i++)
0131         QCOMPARE(data[i], result[i]);
0132 }
0133 
0134 void NSLDFTTest::testOnesided_normdB() {
0135     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0136     double result[] = {-1.36980556663896, -0.755525996777514, 0, -9.11503160677666, -16.7190112199983};
0137 
0138     nsl_dft_transform(data, 1, N, ONESIDED, nsl_dft_result_normdB);
0139     for (unsigned int i = 0; i < N/2; i++)
0140         QCOMPARE(data[i], result[i]);
0141 }
0142 
0143 //##############################################################################
0144 //#################  two sided tests
0145 //##############################################################################
0146 
0147 void NSLDFTTest::testTwosided_real() {
0148     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0149     double result[] = {10, 2, -5.85410196624968, 2, 0.854101966249685, 2, 0.854101966249685, 2, -5.85410196624968, 2};
0150 
0151     nsl_dft_transform(data, 1, N, TWOSIDED, nsl_dft_result_real);
0152     for (unsigned int i = 0; i < N; i++)
0153         QCOMPARE(data[i], result[i]);
0154 }
0155 
0156 void NSLDFTTest::testTwosided_imag() {
0157     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0158     double result[] = {0, -4.97979656976556, 0, 0.449027976579585, 0, 0, 0, -0.449027976579585, 0, 4.97979656976556};
0159 
0160     nsl_dft_transform(data, 1, N, TWOSIDED, nsl_dft_result_imag);
0161     for (unsigned int i = 0; i < N; i++) {
0162         DEBUG(std::setprecision(15) << data[i]);
0163         if (i == 2 || i == 8)
0164             QCOMPARE(data[i] + 1., 1.); // -1.11022302462516e-16 (Win)
0165         else
0166             QCOMPARE(data[i], result[i]);
0167     }
0168 }
0169 
0170 void NSLDFTTest::testTwosided_magnitude() {
0171     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0172     double result[] = {10, 5.36641163872553, 5.85410196624968, 2.04978684837013, 0.854101966249685, 2, 0.854101966249685, 2.04978684837013, 5.85410196624968, 5.36641163872553};
0173 
0174     nsl_dft_transform(data, 1, N, TWOSIDED, nsl_dft_result_magnitude);
0175     for (unsigned int i = 0; i < N; i++)
0176         QCOMPARE(data[i], result[i]);
0177 }
0178 
0179 void NSLDFTTest::testTwosided_amplitude() {
0180     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0181     double result[] = {1, 1.07328232774511, 1.17082039324994, 0.409957369674026, 0.170820393249937, 0.4, 0.170820393249937, 0.409957369674026, 1.17082039324994, 1.07328232774511};
0182 
0183     nsl_dft_transform(data, 1, N, TWOSIDED, nsl_dft_result_amplitude);
0184     for (unsigned int i = 0; i < N; i++)
0185         QCOMPARE(data[i], result[i]);
0186 }
0187 
0188 void NSLDFTTest::testTwosided_power() {
0189     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0190     double result[] = {10, 5.75967477524977, 6.85410196624968, 0.840325224750231, 0.145898033750316, 0.8, 0.145898033750316, 0.840325224750231, 6.85410196624968, 5.75967477524977};
0191 
0192     nsl_dft_transform(data, 1, N, TWOSIDED, nsl_dft_result_power);
0193     for (unsigned int i = 0; i < N; i++)
0194         QCOMPARE(data[i], result[i]);
0195 }
0196 
0197 void NSLDFTTest::testTwosided_phase() {
0198     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0199     double result[] = {0, 1.18889174012102, -3.14159265358979, -0.220851801285041, 0, 0, 0, 0.220851801285041, 3.14159265358979, -1.18889174012102};
0200 
0201     nsl_dft_transform(data, 1, N, TWOSIDED, nsl_dft_result_phase);
0202     for (unsigned int i = 0; i < N; i++) {
0203         DEBUG(std::setprecision(15) << data[i]);
0204         if (i == 2 || i == 8)   // sign can be + or -
0205             QCOMPARE(fabs(data[i]), fabs(result[i]));
0206         else
0207             QCOMPARE(data[i], result[i]);
0208     }
0209 }
0210 
0211 void NSLDFTTest::testTwosided_dB() {
0212     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0213     double result[] = {0, 0.614279569861449, 1.36980556663896, -7.7452260401377, -15.3492056533593, -7.95880017344075, -15.3492056533593, -7.7452260401377, 1.36980556663896, 0.614279569861449};
0214 
0215     nsl_dft_transform(data, 1, N, TWOSIDED, nsl_dft_result_dB);
0216     for (unsigned int i = 0; i < N; i++)
0217         QCOMPARE(data[i], result[i]);
0218 }
0219 
0220 void NSLDFTTest::testTwosided_squaremagnitude() {
0221     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0222     double result[] = {100, 28.7983738762488, 34.2705098312484, 4.20162612375116, 0.729490168751578, 4, 0.729490168751578, 4.20162612375116, 34.2705098312484, 28.7983738762488};
0223 
0224     nsl_dft_transform(data, 1, N, TWOSIDED, nsl_dft_result_squaremagnitude);
0225     for (unsigned int i = 0; i < N; i++)
0226         QCOMPARE(data[i], result[i]);
0227 }
0228 
0229 void NSLDFTTest::testTwosided_squareamplitude() {
0230     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0231     double result[] = {1, 1.15193495504995, 1.37082039324994, 0.168065044950046, 0.0291796067500631, 0.16, 0.0291796067500631, 0.168065044950046, 1.37082039324994, 1.15193495504995};
0232 
0233     nsl_dft_transform(data, 1, N, TWOSIDED, nsl_dft_result_squareamplitude);
0234     for (unsigned int i = 0; i < N; i++)
0235         QCOMPARE(data[i], result[i]);
0236 }
0237 
0238 void NSLDFTTest::testTwosided_normdB() {
0239     double data[] = {1, 1, 3, 3, 1, -1, 0, 1, 1, 0};
0240     double result[] = {-1.36980556663896, -0.755525996777514, 0, -9.11503160677666, -16.7190112199983, -9.32860574007971, -16.7190112199983, -9.11503160677666, 0, -0.755525996777514};
0241 
0242     nsl_dft_transform(data, 1, N, TWOSIDED, nsl_dft_result_normdB);
0243     for (unsigned int i = 0; i < N; i++)
0244         QCOMPARE(data[i], result[i]);
0245 }
0246 
0247 //##############################################################################
0248 //#################  performance
0249 //##############################################################################
0250 
0251 #ifdef HAVE_FFTW3
0252 const int NN = 1e6;
0253 #else   // GSL is much slower
0254 const int NN = 1e6;
0255 #endif
0256 
0257 void NSLDFTTest::testPerformance_onesided() {
0258     double* data = new double[NN];
0259 
0260     for (int i = 0;  i < NN; i++)
0261         data[i] = 1.;
0262     
0263     QBENCHMARK {
0264         nsl_dft_transform(data, 1, NN, ONESIDED, nsl_dft_result_real);
0265     }
0266 
0267     delete[] data;
0268 }
0269 
0270 void NSLDFTTest::testPerformance_twosided() {
0271     double* data = new double[NN];
0272 
0273     for (int i = 0;  i < NN; i++)
0274         data[i] = 1.;
0275     
0276     QBENCHMARK {
0277         nsl_dft_transform(data, 1, NN, TWOSIDED, nsl_dft_result_real);
0278     }
0279 
0280     delete[] data;
0281 }
0282 
0283 QTEST_MAIN(NSLDFTTest)